📄 138.htm
字号:
strgetmsg (fd, &ctl, (struct strbuf*) NULL, &flags, "dlbindack"); <br>
<br>
dlp = (union DL_primitives *) ctl.buf; <br>
<br>
expecting (DL_BIND_ACK, dlp); <br>
<br>
if (flags != RS_HIPRI) <br>
err ("dlbindack: DL_OK_ACK was not M_PCPROTO"); <br>
<br>
if (ctl.len < sizeof (dl_bind_ack_t)) <br>
err ("dlbindack: short response ctl.len: %d", ctl.len); <br>
} <br>
<br>
dlokack (fd, bufp) <br>
int fd; <br>
char *bufp; <br>
{ <br>
union DL_primitives*dlp; <br>
struct strbuf ctl; <br>
int flags; <br>
<br>
ctl.maxlen = MAXDLBUF; <br>
ctl.len = 0; <br>
ctl.buf = bufp; <br>
<br>
strgetmsg (fd, &ctl, (struct strbuf*) NULL, &flags, "dlokack"); <br>
<br>
dlp = (union DL_primitives *) ctl.buf; <br>
<br>
expecting (DL_OK_ACK, dlp); <br>
<br>
if (ctl.len < sizeof (dl_ok_ack_t)) <br>
err ("dlokack: response ctl.len too short: %d", ctl.len); <br>
<br>
if (flags != RS_HIPRI) <br>
err ("dlokack: DL_OK_ACK was not M_PCPROTO"); <br>
<br>
if (ctl.len < sizeof (dl_ok_ack_t)) <br>
err ("dlokack: short response ctl.len: %d", ctl.len); <br>
} <br>
<br>
dlinforeq (fd) <br>
int fd; <br>
{ <br>
dl_info_req_t info_req; <br>
struct strbuf ctl; <br>
int flags; <br>
<br>
info_req.dl_primitive = DL_INFO_REQ; <br>
<br>
ctl.maxlen = 0; <br>
ctl.len = sizeof (info_req); <br>
ctl.buf = (char *) &info_req; <br>
<br>
flags = RS_HIPRI; <br>
<br>
if (putmsg (fd, &ctl, (struct strbuf*) NULL, flags) < 0) <br>
syserr ("dlinforeq: putmsg"); <br>
} <br>
<br>
dlinfoack (fd, bufp) <br>
int fd; <br>
char *bufp; <br>
{ <br>
union DL_primitives*dlp; <br>
struct strbuf ctl; <br>
int flags; <br>
<br>
ctl.maxlen = MAXDLBUF; <br>
ctl.len = 0; <br>
ctl.buf = bufp; <br>
<br>
strgetmsg (fd, &ctl, (struct strbuf*) NULL, &flags, "dlinfoack"); <br>
<br>
dlp = (union DL_primitives *) ctl.buf; <br>
<br>
expecting (DL_INFO_ACK, dlp); <br>
<br>
if (ctl.len < sizeof (dl_info_ack_t)) <br>
err ("dlinfoack: response ctl.len too short: %d", ctl.len); <br>
<br>
if (flags != RS_HIPRI) <br>
err ("dlinfoack: DL_INFO_ACK was not M_PCPROTO"); <br>
<br>
if (ctl.len < sizeof (dl_info_ack_t)) <br>
err ("dlinfoack: short response ctl.len: %d", ctl.len); <br>
} <br>
<br>
<br>
When executed, the program produces the following output: <br>
<br>
# dlinfo <br>
dlinfo: Usage: dlinfo device ppa sap <br>
<br>
# dlinfo /dev/le 0 0 <br>
DL_INFO_ACK: max_sdu 1500 min_sdu 0 <br>
addr_length 8 mac_type DL_CSMACD current_state DL_IDLE <br>
sap_length -2 service_mode DL_CLDLS qos_length 0 <br>
qos_offset 0 qos_range_length 0 qos_range_offset 0 <br>
provider_style DL_STYLE2 addr_offset 76 version 2 <br>
brdcst_addr_length 6 brdcst_addr_offset 84 <br>
addr 8:0:20:10:ab:ed:0:0 <br>
brdcst_addr ff:ff:ff:ff:ff:ff <br>
# <br>
<br>
Note that the DLSAP address length for the le driver is 8 and the sap_length is <br>
-2, which means that the first six bytes are the physical address (Ethernet <br>
address) and the final two bytes are the SAP (Ethernet type) for this <br>
particular provider. <br>
<br>
<br>
** Transmitting Messages <br>
<br>
Once the file descriptor has been attached to a physical interface and a SAP <br>
has been bound, you can send and receive datalink messages using the <br>
DL_UNITDATA_REQ and DL_UNITDATA_IND DLPI primitives. <br>
<br>
<br>
/* Xmit data buffer. Fill with whatever pattern you like ... */ <br>
char xmitbuf[MAXDLBUF]; <br>
<br>
<br>
main (ac, av) <br>
int ac; <br>
char *av[]; <br>
{ <br>
char *device; <br>
int ppa, fd, localsap, sapval, n, size, physlen, saplen; <br>
u_char phys[MAXDLADDR], sap[MAXDLADDR], addr[MAXDLADDR]; <br>
int addrlen; <br>
long buf[MAXDLBUF]; <br>
union DL_primitives*dlp; <br>
int i; <br>
<br>
... <br>
<br>
if (ac != 8) <br>
usage (av[0]); <br>
<br>
device = av[1]; <br>
ppa = atoi (av[2]); <br>
localsap = atoi (av[3]); <br>
n = atoi (av[6]); <br>
size = atoi (av[7]); <br>
<br>
... <br>
<br>
/* Convert destination address string to address. */ <br>
<br>
physlen = stringtoaddr (av[4], phys); <br>
sapval = atoi (av[5]); <br>
for (i = 0; i < sizeof (long); i++) <br>
sap[i] = (sapval >> (i * BITSPERBYTE)) & 0xff; <br>
<br>
... <br>
<br>
/* Get info. */ <br>
<br>
dlinforeq (fd); <br>
dlinfoack (fd, buf); <br>
<br>
... <br>
<br>
saplen = ABS (dlp->info_ack.dl_sap_length); <br>
addrlen = saplen + physlen; <br>
<br>
<br>
/* Construct destination address. */ <br>
<br>
if (dlp->info_ack.dl_sap_length > 0) { /* order is sap+phys */ <br>
(void) memcpy ((char*)addr, (char*)sap, saplen); <br>
(void) memcpy ((char*)addr+saplen, (char*)phys, physlen); <br>
} else { /* order is phys+sap */ <br>
(void) memcpy ((char*)addr, (char*)phys, physlen); <br>
(void) memcpy ((char*)addr+physlen, (char*)sap, saplen); <br>
} <br>
<br>
/* Transmit 'size' packet 'n' times. */ <br>
<br>
for (i = 0; i < n; i++) <br>
dlunitdatareq (fd, addr, addrlen, 0, 0, xmitbuf, size); <br>
<br>
... <br>
<br>
<br>
dlunitdatareq (fd, addrp, addrlen, minpri, maxpri, datap, datalen) <br>
int fd; <br>
u_char *addrp; <br>
int addrlen; <br>
u_long minpri, maxpri; <br>
u_char *datap; <br>
int datalen; <br>
{ <br>
long buf[MAXDLBUF]; <br>
union DL_primitives*dlp; <br>
struct strbuf data, ctl; <br>
<br>
dlp = (union DL_primitves*) buf; <br>
<br>
dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; <br>
dlp->unitdata_req.dl_dest_addr_length = addrlen; <br>
dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); <br>
dlp->unitdata_req.dl_priority.dl_min = minpri; <br>
dlp->unitdata_req.dl_priority.dl_max = maxpri; <br>
<br>
(void) memcpy (OFFADDR (dlp, sizeof (dl_unitdata_req_t)), <br>
addrp, addrlen); <br>
<br>
ctl.maxlen = 0; <br>
ctl.len = sizeof (dl_unitdata_req_t) + addrlen; <br>
ctl.buf = (char *) buf; <br>
<br>
data.maxlen = 0; <br>
data.len = datalen; <br>
data.buf = (char *) datap; <br>
<br>
if (putmsg (fd, &ctl, &data, 0) < 0) <br>
syserr ("dlunitdatareq: putmsg"); <br>
} <br>
<br>
<br>
<br>
** Receiving Messages <br>
<br>
Received datalink packets are subject to two levels of address matching. <br>
Packets which do not match the enabled physical address for the file descriptor <br>
are rejected. Packets which do not match the enabled SAP address(es) for the <br>
file descriptor are rejected. Physical and SAP level address matching are <br>
independent on a per-packet and per-file-descriptor basis. The physical and <br>
SAP addresses enabled on one opened file descriptor have no effect on the <br>
packets received on another file descriptor. Only those received packets which <br>
match both the enabled physical address(es) and enabled SAP address(es) are <br>
sent upstream to the user. <br>
<br>
Attaching to a PPA enables that physical address on the file descriptor. <br>
Binding a SAP enables that SAP address on the file descriptor. Additional <br>
physical and SAP addresses can be enabled for the file descriptor using the <br>
promiscuous and multicast primitives. <br>
<br>
... <br>
<br>
data.buf = (char *) databuf; <br>
data.maxlen = MAXDLBUF; <br>
data.len = 0; <br>
<br>
while (getmsg (fd, NULL, &data, &flags) == 0) { <br>
if (data.len) { <br>
for (i = 0; i < data.len; i++) <br>
printf ("%02x ", data.buf[i] & 0xff); <br>
printf ("\n"); <br>
} <br>
data.len = 0; <br>
} <br>
<br>
... <br>
... <br>
<br>
<br>
** Raw Mode <br>
<br>
One feature which is not included in the USL DLPI Version 2 specification but <br>
is frequently necessary for several types of applications is "raw" mode. <br>
Support for this mode has been added to SunOS 5.x. The user enables raw mode by <br>
issuing the DLIOCRAW ioctl, which is defined in the version of dlpi.h shipped <br>
with SunOS 5.x. After this, "raw" Ethernet frames which include the 14-byte <br>
Ethernet header may be sent downstream in M_DATA type messages, and all <br>
received frames will be sent upstream with Ethernet header included in M_DATA <br>
type messages. <br>
<br>
The DLIOCRAW ioctl takes no arguments. <br>
<br>
<br>
** Getting and Setting the Physical Address <br>
<br>
Use the DL_PHYS_ADDR_REQ primitive to request the current or default factory <br>
physical (Ethernet) address which is returned in the DL_PHYS_ADDR_ACK message. <br>
<br>
... <br>
... <br>
<br>
/* Get our current physical address. */ <br>
<br>
dlphysaddrreq (fd, DL_CURR_PHYS_ADDR); <br>
dlphysaddrack (fd, buf); <br>
<br>
dlp = (union DL_primitives*) buf; <br>
<br>
/* Create raw Ethernet header. */ <br>
<br>
ehp = (struct ether_header*) xmitbuf; <br>
memcpy (&ehp->ether_dhost, phys, ETHERADDRL); <br>
memcpy (&ehp->ether_shost, <br>
OFFADDR (dlp, dlp->physaddr_ack.dl_addr_offset), ETHERADDRL); <br>
ehp->ether_type = (u_short) sapval; <br>
<br>
/* Put file descriptor in "raw mode". */ <br>
<br>
if (strioctl (fd, DLIOCRAW, -1, 0, 0) < 0) <br>
syserr ("ioctl DLIOCRAW"); <br>
<br>
/* Transmit it as an M_DATA msg. */ <br>
<br>
if (write (fd, xmitbuf, size) < 0) <br>
syserr ("write"); <br>
<br>
... <br>
<br>
<br>
dlphysaddrreq (fd, addrtype) <br>
int fd; <br>
u_long addrtype; <br>
{ <br>
dl_phys_addr_req_t phys_addr_req; <br>
struct strbuf ctl; <br>
int flags; <br>
<br>
phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ; <br>
phys_addr_req.dl_addr_type = addrtype; <br>
<br>
ctl.maxlen = 0; <br>
ctl.len = sizeof (phys_addr_req); <br>
ctl.buf = (char *) &phys_addr_req; <br>
<br>
<br>
flags = 0; <br>
if (putmsg (fd, &ctl, (struct strbuf*) NULL, flags) < 0) <br>
syserr ("dlphysaddrreq: putmsg"); <br>
} <br>
<br>
dlphysaddrack (fd, bufp) <br>
int fd; <br>
char *bufp; <br>
{ <br>
union DL_primitives*dlp; <br>
struct strbuf ctl; <br>
int flags; <br>
<br>
ctl.maxlen = MAXDLBUF; <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -