📄 140.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>123</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center"> ● UNIX网络编程 (BM: clown) </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="133.htm">上一层</a>][<a href="141.htm">下一篇</a>]
<hr><p align="left"><small>发信人: guru (好读书,不求甚解), 信区: UNP <br>
标 题: dlpi简介 <br>
发信站: UNIX编程 (2001年08月15日09:46:18 星期三), 站内信件 <br>
<br>
dlpi简介 <br>
作者:pan8848 2000-05-24这篇稿件被阅读==170次 <br>
<br>
<br>
unix中要想直接对数据链路层读写有三种方法:dlpi(data <br>
link provider interface),bpf(bsd packet filter),还 <br>
有linux中的sock_packet. <br>
有关dlpi方面的资料很少,本文对dlpi作简要的介绍。 <br>
对dlpi或网络编程感兴趣的大侠可与我联系:pan8848@263.net <br>
OSI参考模型的每一层都有两种标准:1 定义该层提供的 <br>
服务。2 定义可以提供该服务的协议。DLPI属于第一种标准, <br>
即不提供实现方法。 <br>
1 通信类型 <br>
DLPI提供三种类型的通信方式:连接、无连接和公认无连接。 <br>
1.1 连接方式 <br>
连接方式是面向电路的,数据通过一个预先建立的连接进行 <br>
传输。整个通信过程分为四个阶段:本地管理,连接建立,数据 <br>
传输,连接释放。 <br>
本地管理阶段,DLS用户初始化一个用于通信的流并为自己建 <br>
立一个标识符。 <br>
连接建立阶段,DLS主叫用户初始化连接建立过程,被叫用户 <br>
等待连接请求。DLS被叫用户是通过一个与流相联系的地址来标 <br>
识自己。被叫用户可以接收请求,也可以拒绝请求。如果接收, <br>
双方就进入数据传输阶段。每个流上只能建立一个连接。被叫用 <br>
户可以选择在收到连接请求的流上接收连接,也可以打开一个新 <br>
流,在这个新流上接收连接。如果在一个独立的流上接收连接, <br>
则初始化流可以被设计成一个侦听流以处理所有的连接请求。当 <br>
一个请求到达时就打开一个新流以处理这个连接,随后到达的请 <br>
求在侦听流排队等待接收处理。 <br>
数据传输阶段,两个DLS用户被认为是对等的,可以全双工 <br>
通信。数据按顺序可靠的到达对方。 <br>
连接释放阶段,DLS用户和DLS提供者都可以释放连接。连接 <br>
释放时,任何未到达目的地的数据都被DLS提供者丢弃。 <br>
1.2 无连接方式 <br>
无连接方式不需要连接建立和连接释放阶段。本地管理阶段仍需 <br>
初始化流。之后,立即进入数据传输阶段。因为没有建立连接,每一 <br>
个数据单元都必需标明目的地。目的的DLS是通过与用户相联系的地 <br>
址来标识自己的。无连接方式不保证数据单元按顺序到达,也不保证 <br>
数据会到达目的DLS用户。 <br>
<br>
1.3 公认无连接方式 <br>
公认无连接方式与无连接方式类似,但是它保证数据按顺序 <br>
到达目的地。 <br>
<br>
无连接方式是面向消息的,传输的数据单元之间没有逻辑的 <br>
联系,这种方式在大多数情况下是不可靠的。公认无连接使用户 <br>
可以同时发送数据和请求数据返回,数据单元的传输是点对点的。 <br>
<br>
2 DLPI 地址 <br>
每一个DLPI用户都要建立一个标识符以与其它数据链路层用户 <br>
通信。这个标识符包括两部分。首先,DLPI必须指明它通信的物 <br>
理媒介。在一个与多个物理媒介相连的系统上,这一点更加明显 <br>
。其次,DLS用户必须相DLS提供者登记。 <br>
<br>
2.1 物理层标识 <br>
PPA(physical point of attachment)是系统与物理介质 <br>
的连接点。该物理介质上的所有通信都要经过PPA。有的系统上, <br>
DLS提供者支持多个物理介质,DLS用户必须指明它要与哪个物理 <br>
介质通信。一个PPA由唯一的PPA标识符来标识。 <br>
对于支持物理层复用的介质(如ISDN的B和D通道),PPA标识符 <br>
必须指明通信的通道。 <br>
2.2 数据链路层标识 <br>
DLSAP(Data Link Service Access Point)是用户与DLS <br>
提供者的连接点。DLSAP由唯一的DLSAP标识符来标识。 <br>
通过Bind原语,DLS用户可以指定DLSAP地址来选择DLSAP,或 <br>
重申被绑定的DLSAP地址来决定与流相联系的DLSAP。 <br>
DLS提供者具有绑定多个DLSAP地址的能力。DLPI 支持对等绑 <br>
定和等级绑定。对等绑定,在随后绑定中指定的DLSAP可用来替 <br>
代在DL_BIND_REQ中绑定的DLSAP。例如,在DL_BIND_REQ指定 <br>
ether-_type的值为IP,在随后绑定中可以指定ether-_type的 <br>
值为ARP。则DLS提供者复用ether-_type域,允许IP或ARP数据发 <br>
送到流上。若没有指明,则第一个被绑定的SAP被作为源SAP。等 <br>
级绑定,随后绑定指定一个与在DL_BIND_REQ 中绑定的DLSAP不 <br>
同的DLSAP。 <br>
<br>
3 dlpi编程的大体框架 <br>
仅以捕捉数据包为例,其中设计一些函数,未给出,有兴趣者 <br>
可向我索要。 <br>
/* <br>
* NAME <br>
* dlrcv - read and display raw datalink packets <br>
* SYNOPSIS: <br>
* dlrcv [ -bp ] device ppa sap <br>
* <br>
* Open datalink provider. <br>
* Attach to PPA. <br>
* Bind to sap <br>
* Issue DLIOCRAW ioctl. <br>
* Read and print messages <br>
*/ <br>
<br>
/* <br>
typedef unsigned long ulong; <br>
*/ <br>
<br>
#include "../h/conf.h" <br>
#include "../h/kernel.h" <br>
#include "../h/network.h" <br>
<br>
<br>
#include <sys/types.h> <br>
#include <sys/time.h> <br>
#include <sys/stream.h> <br>
#include <sys/stropts.h> <br>
#include <sys/dlpi.h> <br>
#include <sys/bufmod.h> <br>
#include <stdio.h> <br>
#include "dltest.h" <br>
#include <sys/signal.h> <br>
#include <string.h> <br>
long databuf[MAXDLBUF]; <br>
<br>
<br>
extern char *optarg; <br>
extern int optind; <br>
<br>
int promisc = 0; /* promiscuous mode "off" by default */ <br>
int bufmod = 0; /* push buffer module, "off" by default */ <br>
<br>
<br>
main() <br>
{ <br>
dlrcv("/dev/le",0,2048); <br>
} <br>
<br>
dlrcv(char *device, int ppa,int sap) <br>
{ <br>
long buf[MAXDLBUF]; <br>
int fd; <br>
int fd; <br>
struct strbuf data; <br>
int flags; <br>
int i,j,cnt=0; <br>
int c; <br>
int offset; <br>
int len; <br>
struct timeval t; <br>
u_int chunksize = 16 * 1024; <br>
struct sb_hdr *bp; <br>
char *p, *limp; <br>
u_char buf1[4*MAXDLBUF]; <br>
struct udp *pudp; <br>
char udata[]; <br>
int idata; <br>
char cdata; <br>
struct ip *pip; <br>
<br>
int wfd,nwrite; <br>
/* <br>
* Validate arguments. <br>
*/ <br>
if (ppa < 0) <br>
err("ppa cannot be negative"); <br>
if (sap < 0) <br>
err("sap cannot be negative"); <br>
<br>
/* <br>
* Open the device. <br>
*/ <br>
if ((fd = open(device, 2)) < 0) <br>
syserr(device); <br>
<br>
/* <br>
* Attach. <br>
*/ <br>
dlattachreq(fd, ppa); <br>
dlokack(fd, buf); <br>
<br>
/* <br>
* Optionally enable promiscuous mode. <br>
*/ <br>
if (promisc) { <br>
dlpromisconreq(fd, DL_PROMISC_PHYS); <br>
dlokack(fd, buf); <br>
} <br>
<br>
/* <br>
* Bind. <br>
*/ <br>
dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0); <br>
dlbindack(fd, buf); <br>
<br>
/* <br>
* Issue DLIOCRAW ioctl. <br>
*/ <br>
<br>
if (strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0) <br>
syserr("DLIOCRAW"); <br>
<br>
/* <br>
* Push and configure buffer module. <br>
*/ <br>
if (bufmod) { <br>
if (ioctl(fd, I_PUSH, "bufmod") < 0) <br>
syserr("push bufmod"); <br>
<br>
<br>
t.tv_sec = 0; <br>
t.tv_usec = 500000; /* 0.5s */ <br>
if (strioctl(fd, SBIOCSTIME, -1, sizeof (struct timeval), <br>
&t) < 0) <br>
syserr("SBIOCSTIME"); <br>
if (strioctl(fd, SBIOCSCHUNK, -1, sizeof (u_int), <br>
&chunksize) < 0) <br>
syserr("SBIOCSCHUNK"); <br>
} <br>
<br>
/* <br>
* Flush the read side of the Stream. <br>
*/ <br>
if (ioctl(fd, I_FLUSH, FLUSHR) < 0) <br>
syserr("I_FLUSH"); <br>
<br>
/* <br>
* Read packets. <br>
*/ <br>
<br>
data.buf = (char *) databuf; <br>
data.maxlen = MAXDLBUF; <br>
data.len = 0; <br>
printf("read "); <br>
<br>
while (getmsg(fd, NULL, &data, &flags) == 0) { <br>
<br>
printf("getmsg "); <br>
limp = p + data.len; <br>
<br>
if (data.len && bufmod) { <br>
for (p = data.buf; p < limp; p += bp-> sbh_totlen) { <br>
bp = (struct sb_hdr*) p; <br>
for (i = 0; i < bp->sbh_msglen; i++) <br>
printf("%02x ", *(p + <br>
sizeof (struct sb_hdr) + i) <br>
& 0xff); <br>
printf(" "); <br>
} <br>
} else if (data.len) { <br>
<br>
memcpy(buf1,(u_char *)(data.buf+14),data.len-14); <br>
pip = (struct ip *)buf1; <br>
<br>
<br>
if(1){ <br>
printf("source ip:%x ",pip->ip_src); <br>
printf("dest ip:%x ",pip->ip_dst); <br>
if (pip->ip_proto==IPT_UDP){ <br>
<br>
pudp=pip->ip_data; <br>
<br>
printf("datalen:%d ",pudp->u_len-U_HLEN); <br>
printf("udp source port:%d ",pudp->u_src); <br>
printf("udp dest port:%d ",pudp->u_dst); <br>
printf("data: "); <br>
<br>
for (i= 14+20+8; i < data.len; i++){ <br>
idata=data.buf[i]&0xff; <br>
printf("%d:%c ", i-14-20-8,idata); <br>
} <br>
printf(" "); <br>
<br>
i=data.len-14-20-8; <br>
<br>
for (i= 14+20+8; i < data.len; i++) <br>
printf("%d:%02x ", i-14-20-8,data.buf[i] & 0xff); <br>
printf(" "); <br>
<br>
i=data.len-14-20-8; <br>
} <br>
<br>
<br>
} <br>
<br>
} <br>
data.len = 0; <br>
}/*while*/ <br>
} <br>
<br>
<br>
-- <br>
Target Locked:Guru In Darkness. <br>
我只是一只静静卧着的狮子。。。 <br>
※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.36.225] <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="133.htm">上一层</a>][<a href="141.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 + -