📄 138.htm
字号:
ctl.len = 0; <br>
ctl.buf = bufp; <br>
<br>
strgetmsg (fd, &ctl, (struct strbuf*) NULL, <br>
&flags, "dlphysaddrack"); <br>
<br>
dlp = (union DL_primitives *) ctl.buf; <br>
<br>
<br>
expecting (DL_PHYS_ADDR_ACK, dlp); <br>
<br>
if (flags != RS_HIPRI) <br>
err ("dlphysaddrack: DL_OK_ACK was not M_PCPROTO"); <br>
<br>
if (ctl.len < sizeof (dl_phys_addr_ack_t)) <br>
err ("dlphysaddrack: short response ctl.len: %d", ctl.len); <br>
} <br>
<br>
Use the DL_SET_PHYS_ADDR_REQ primitive to set the physical address of the <br>
attached interface. NOTE: this is a destructive operation, and unlike all other <br>
primitives, it will affect other file descriptors for this physical interface. <br>
The new physical address for the interface will be retained until the next <br>
DL_SET_PHYS_ADDR_REQ is issued or the system is rebooted. Only the superuser <br>
may issue this primitive. <br>
<br>
<br>
** Multicast Addressing <br>
<br>
Use DL_ENABMULTI_REQ and DL_DISABMULTI_REQ to enable/disable specific multicast <br>
group addresses. These primitives allow the user to iteratively build a set of <br>
enabled multicast addresses on a per-file-descriptor basis. <br>
<br>
<br>
** Promiscuous Reception <br>
<br>
DL_PROMISCON_REQ and DL_PROMISCOFF_REQ allow the user to enable/disable <br>
promiscuous-mode reception. These two primitives take a level argument which <br>
may be one of: <br>
<br>
DL_PROMISC_PHYS <br>
DL_PROMISC_SAP <br>
DL_PROMISC_MULTI <br>
<br>
Each of the promiscuous levels acts like a "wildcard" for the particular level. <br>
Enabling DL_PROMISC_PHYS will match all physical addresses. Enabling <br>
DL_PROMISC_SAP will match all SAP addresses. Enabling DL_PROMISC_MULTI will <br>
match all multicast-group addresses. <br>
<br>
The following example demonstrates how one would enable physical-level <br>
promiscuous mode: <br>
<br>
... <br>
<br>
<br>
/* Enable promiscuous mode. */ <br>
<br>
dlpromisconreq (fd, DL_PROMISC_PHYS); <br>
dlokack (fd, buf); <br>
<br>
... <br>
<br>
<br>
dlpromisconreq (fd, level) <br>
int fd; <br>
u_long level; <br>
{ <br>
dl_promiscon_req_t promiscon_req; <br>
struct strbuf ctl; <br>
int flags; <br>
<br>
promiscon_req.dl_primitive = DL_PROMISCON_REQ; <br>
promiscon_req.dl_level = level; <br>
<br>
ctl.maxlen = 0; <br>
ctl.len = sizeof (promiscon_req); <br>
ctl.buf = (char *) &promiscon_req; <br>
<br>
flags = 0; <br>
<br>
if (putmsg (fd, &ctl, (struct strbuf*) NULL, flags) < 0) <br>
syserr ("dlpromiscon: putmsg"); <br>
} <br>
<br>
<br>
Converting NIT Programs to Use DLPI <br>
----------------------------------- <br>
The Network Interface Tap (NIT) STREAMS pseudo-driver is not included in <br>
SunOS 5.x. In previous releases of SunOS, the underlying datalink device <br>
drivers were not directly accessible as UNIX special files; therefore, a <br>
pseudo-driver, NIT, was supported to allow those few user-level programs which <br>
required access to the raw datalink drivers to access the devices. <br>
<br>
In SunOS 5.x, all networking drivers are real STREAMS hardware drivers <br>
accessible in the file system namespace. To access the "le0" networking <br>
interface, you now open /dev/le instead of /dev/nit , and issue DLPI primitives <br>
instead of NIT primitives. DLPI provides a superset of the features previously <br>
provided by the NIT pseudo-driver. <br>
<br>
<br>
Applications which used NIT in SunOS 4.x will require some source-level <br>
modifications to run in SunOS 5.x . With the information provided below, the <br>
application programmer should find these changes relatively simple and <br>
straightforward. <br>
<br>
<br>
SunOS 4.x included three NIT components: <br>
<br>
o nit_if(4M) pseudo-driver <br>
o nit_pf(4M) packet filter module <br>
o nit_buf(4M) buffer module <br>
<br>
The nit_if pseudo-driver is not included in SunOS 5.x. The packet filter and <br>
buffer modules have been ported to 5.x and minor enhancements made. Refer <br>
to the pfmod(1M) and bufmod(1M) manual pages for the complete programmatic <br>
interfaces for these two general-purpose STREAMS modules. <br>
<br>
** Open Driver Directly <br>
<br>
Open the datalink driver instead of /dev/nit : <br>
<br>
/* Open the device. */ <br>
<br>
if ((fd = open ("/dev/le", 2)) < 0) <br>
syserr ("/dev/le"); <br>
<br>
<br>
** NIT ioctls to DLPI Primitives or Buffer Module ioctls <br>
<br>
The NIT ioctl commands have changed slightly: <br>
<br>
o Replace use of the SIOCGIFADDR ioctl with the DL_PHYS_ADDR_REQ <br>
DLPI primitive to get the current or default physical Ethernet address. <br>
<br>
o Replace use of the SIOCSIFADDR ioctl with the DL_SET_PHYS_ADDR_REQ DLPI <br>
primitive to set the current physical Ethernet address. You must be <br>
superuser to do this; the operation is destructive and permanently changes <br>
the individual Ethernet address of the interface for all open Streams <br>
until it is changed again or the system reboots. <br>
<br>
o Replace use of the SIOCADDMULTI and SIOCDELMULTI ioctls with the <br>
DL_ENABMULTI_REQ and DL_DISABMULTI_REQ DLPI primitives. Each datalink <br>
provider will support a fixed number of specific multicast addresses. <br>
Use the DL_PROMISCON_REQ with DL_PROMISC_MULTI dl_level value to enable <br>
all multicast group addresses. <br>
<br>
o Replace use of the NIOCBIND ioctl command with the DL_ATTACH_REQ and <br>
DL_BIND_REQ DLPI primitives. The attach primitive performs the equivalent <br>
function of the NIOCBIND ioctl, and the bind primitive then labels the <br>
attached interface with a service access point (SAP) address. The bundled <br>
Ethernet drivers implement the SAP address as the Ethernet type. You must <br>
bind a SAP address to the interface before you can send or receive; this <br>
is *not* an optional command. <br>
<br>
o Replace use of the NIOCSSNAP ioctl command with the SBIOCSSNAP buffer <br>
module ioctl command. You must push "bufmod" before issuing the SBIOCSSNAP <br>
in the same manner as the old NIT NIOCSSNAP ioctl. <br>
<br>
o The NIOCSFLAGS ioctl command has changed. Instead of setting the <br>
NI_PROMISC flag, you must now issue the DL_PROMISCON_REQ DLPI primitive, <br>
setting the DL_PROMISC_PHYS value in the dl_level field. Instead of <br>
setting the NL_TIMESTAMP and NI_DROPS flags, you must push the buffer <br>
module; timestamp and dropcounts are included in the default buffer module <br>
chunk message headers, which also include the original and truncated <br>
packet lengths. <br>
<br>
<br>
<br>
** Attach and Bind <br>
<br>
Use the DLPI primitives DL_ATTACH_REQ and DL_BIND_REQ to first associate the <br>
file descriptor with a particular physical interface (like NIOCBIND), and then <br>
label the attached file descriptor with a SAP address. The bundled SunOS 4.x <br>
Ethernet drivers implement the SAP as the Ethernet type. So if you wanted to <br>
receive IP (0x0800) type Ethernet packets only, you'd do this: <br>
<br>
... <br>
<br>
/* Attach. <br>
* Arguments: file descriptor, ppa identifier. */ <br>
<br>
dlattachreq (fd, ppa); <br>
dlokack (fd, buf); <br>
<br>
/* Bind. <br>
* Arguments: file descriptor, sap, max conind, <br>
* service mode, conn_mgmt, xidtest. */ <br>
<br>
dlbindreq (fd, 0x800, 0, DL_CLDLS, 0, 0); <br>
dlbindack (fd, buf); <br>
<br>
... <br>
<br>
The complete example routines for attaching and binding are included in the <br>
first example in the previous section ("How to Use DLPI: Attaching and <br>
Binding"). <br>
<br>
<br>
** Filtering on Ethernet Type <br>
<br>
After binding to a specific type, only packets of that ethertype will be <br>
received on that file descriptor. You don't need to push and configure the <br>
packet filter module to filter on ethertype, since you get that "for free." If <br>
you want to enable multiple Ethernet types on the same file descriptor, you'll <br>
have to enable promiscuous SAP-level service using the DL_PROMISCON_REQ <br>
primitive and setting the DL_PROMISC_SAP value in the dl_level field, and then <br>
push and configure the packet filter module to filter out the packets with <br>
ethertype you're not interested in receiving. <br>
<br>
<br>
** Raw Mode <br>
** Raw Mode <br>
<br>
The standard connectionless DLPI primitives to send and receive datalink <br>
packets are DL_UNITDATA_REQ and DL_UNITDATA_IND. Each of these primitives is <br>
implemented as an M_PROTO STREAMS message type followed by one or more M_DATA <br>
message types. <br>
<br>
If you just want to send and receive "raw" Ethernet frames including the <br>
Ethernet header, you can do this by enabling "raw mode" on the particular file <br>
descriptor. Issue the DLIOCRAW ioctl: <br>
<br>
... <br>
<br>
/* Issue DLIOCRAW ioctl. */ <br>
<br>
if (strioctl (fd, DLIOCRAW, -1, 0, NULL) < 0) <br>
syserr ("DLIOCRAW"); <br>
<br>
... <br>
<br>
<br>
strioctl (fd, cmd, timout, len, dp) <br>
int fd; <br>
int fd; <br>
int cmd; <br>
int timout; <br>
int len; <br>
char *dp; <br>
{ <br>
struct strioctl sioc; <br>
int rc; <br>
<br>
sioc.ic_cmd = cmd; <br>
sioc.ic_timout = timout; <br>
sioc.ic_len = len; <br>
sioc.ic_dp = dp; <br>
rc = ioctl (fd, I_STR, &sioc); <br>
<br>
if (rc < 0) <br>
return (rc); <br>
else <br>
return (sioc.ic_len); <br>
} <br>
<br>
Now all received frames will be passed up without changes within M_DATA <br>
messages, and you can send raw Ethernet frames downstream in M_DATA messages. <br>
<br>
<br>
** Enabling Promiscuous Mode <br>
<br>
Use the DL_PROMISCON_REQ with the dl_level field set to DL_PROMISC_PHYS to <br>
enable physical-level promiscuous mode: <br>
<br>
... <br>
<br>
/* Enable promiscuous mode. */ <br>
<br>
dlpromisconreq (fd, DL_PROMISCON_PHYS); <br>
dlokack (fd, buf); <br>
<br>
... <br>
<br>
<br>
dlpromisconreq (fd, level) <br>
int fd; <br>
u_long level; <br>
{ <br>
dl_promiscon_req_t promiscon_req; <br>
struct strbuf ctl; <br>
int flags; <br>
<br>
promiscon_req.dl_primitive = DL_PROMISCON_REQ; <br>
promiscon_req.dl_level = level; <br>
<br>
ctl.maxlen = 0; <br>
ctl.len = sizeof (promiscon_req); <br>
ctl.buf = (char *) &promiscon_req; <br>
<br>
flags = 0; <br>
<br>
if (putmsg (fd, &ctl, (struct strbuf*) NULL, flags) < 0) <br>
syserr ("dlpromiscon: putmsg"); <br>
} <br>
<br>
<br>
** Packet Filter Module <br>
<br>
The packet filter module, now called "pfmod", is almost identical to the SunOS <br>
4.x version. You can push it and program it as before. <br>
<br>
<br>
<br>
** Buffer Module <br>
<br>
<br>
The buffer module, now called "bufmod", has had a few additions and includes a <br>
few features that were a part of the SunOS 4.x nit_if pseudo-driver. In <br>
addition to the standard chunksize and timeout values for defining when the <br>
"chunk" is passed upstream, the SunOS 5.x bufmod also includes a snaplength <br>
parameter to truncate uninteresting parts of the packet; dropcount of number of <br>
received packets dropped due to read-side flow-control; and timestamp of each <br>
received packet. You push "bufmod" on any Stream in which you want one or more <br>
of these generic features. <br>
<br>
The buffer module header data structure has changed slightly: <br>
<br>
struct sb_hdr { <br>
u_int sbh_origlen; <br>
u_int sbh_msglen; <br>
u_int sbh_totlen; <br>
u_int sbh_drops; <br>
struct timeval sbh_timestamp; <br>
}; <br>
<br>
The names of the buffer module ioctl commands have all changed to take on the <br>
new prefix ("SB" stands for STREAMS Buffer Module): <br>
<br>
NIOCSTIME is now SBIOSCTIME <br>
NIOCGTIME is now SBIOCGTIME <br>
NIOCCTIME is now SBIOCCTIME <br>
NIOCSCHUNK is now SBIOCSCHUNK <br>
NIOCGCHUNK is now SBIOCGCHUNK <br>
<br>
Additional ioctls are documented in the bufmod(1M) manual page. <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="133.htm">上一层</a>][<a href="139.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -