免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6010 | 回复: 5

使用DLPI来编写协议分析工具 [复制链接]

论坛徽章:
0
发表于 2005-07-12 18:28 |显示全部楼层
系统环境:solaris 10 for x86,gcc 3.4.3,100M快速以太网
(偶是个初学者,本文难免存在错误,希望大家多多指教)
前一阵子要写一个简单的arp协议的分析程序,在翻阅了一些资料以后,决定使用libpcap库来实现,但是后来涉及到写链路层数据的缘故(另外一个程序,这个程序就是发送一个假冒的arp request,在本文没有实现,今后有空再整理吧),所以放弃了libpcap。由于本人使用的是solaris环境,所以无法使用bpf,但是sun公司仍然为开发者提供了一个与设备底层无关的接口DLPI,DLPI的全称是Data Link Provider Interface,通过DLPI开发者可以访问数据链路层的数据包,在早期的sunos系统中基本上采用的是NIT设备,但是现在solaris系统都使用了DLPI.关于DLPI的具体介绍大家可以访问网站www.opengroup.org/pubs/catalog/c811.htm,我这里就不多说了。
在搜索了许多资料之后发现目前关于DLPI的编程资料不多,没有具体的过程,后来翻阅了Neal Nuckolls写的一篇文章How to Use the STREAMS Data Link Provider Interface (DLPI),根据例子做了修改(主要是提供了协议分析的部分),现在把编写一个DLPI过程共享一下,希望能对大家有所帮助。建议大家可以先看看Neal Nuckolls的文章,其中有部分涉及到流编程的,可以参考http://docs.sun.com/app/docs/doc/816-4855的streams programming guide(不过这不是必须的)。
使用DLPI来访问数据链路层有几个步骤:
1、打开网络设备
2、将一个流 attach到一个特定的设备上,这里就是我们刚才打开的设备
3、将设备设置为混杂模式(可选)
4、把数据链路层sap绑定到流
5、调用ioctl,设置raw模式
6、配置其他模块(可选)
7、刷新缓存
8、接收数据进入分析阶段
第一步,我们首先打开一个网络设备,在本例中我们打开的是/dev/bge设备,这是本机的网络接口,注意不是/dev/bge0,通过open调用打开,并且返回一个描述符
fd=open(device, 2)
第二步,attach一个流到设备上,这是通过发送DL_ATTACH_REQ原语来完成的
dlattachreq(fd, ppa)
int        fd;
u_long        ppa;
{
        dl_attach_req_t        attach_req;
        struct        strbuf        ctl;
        int        flags;

        attach_req.dl_primitive = DL_ATTACH_REQ;
        attach_req.dl_ppa = ppa;

        ctl.maxlen = 0;
        ctl.len = sizeof (attach_req);
        ctl.buf = (char *) &attach_req;

        flags = 0;

        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
                syserr("dlattachreq:  putmsg";
}
dl_attach_req_t是一个定义在dlpi.h中的结构体,我们通过填写结构体来发布原语,putmsg将消息发送到一个流,以上这个函数是DLPI中发布原语的主要格式
发布了DL_ATTACH_REQ原语之后,还要确认是否成功,
dlokack(fd, bufp)
int        fd;
char        *bufp;
{
        union        DL_primitives        *dlp;
        struct        strbuf        ctl;
        int        flags;

        ctl.maxlen = MAXDLBUF;
        ctl.len = 0;
        ctl.buf = bufp;

        strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack";

        dlp = (union DL_primitives *) ctl.buf;

        expecting(DL_OK_ACK, dlp);

        if (ctl.len < sizeof (dl_ok_ack_t))
                err("dlokack:  response ctl.len too short:  %d", ctl.len);

        if (flags != RS_HIPRI)
                err("dlokack:  DL_OK_ACK was not M_PCPROTO";

        if (ctl.len < sizeof (dl_ok_ack_t))
                err("dlokack:  short response ctl.len:  %d", ctl.len);
}
第三步,将设备设置为混杂模式下工作(可选)
dlpromisconreq(fd, DL_PROMISC_PHYS);
这一个步骤也是通过发布DLPI原语来实现的,具体代码后面给出
第四步,绑定流
dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0);
dlbindack(fd, buf);
第五步,设置raw模式
strioctl(fd, DLIOCRAW, -1, 0, NULL)
第六步,配置其他模块(在详细代码中给出)
第七步,刷新数据,这是通过ioctl调用实现的
ioctl(fd, I_FLUSH, FLUSHR)
第八步,这是我们最关心的步骤,实际上,前面的这些步骤我们都可以忽略,大致明白有这么个过程就可以了,到时候写代码的时候照搬这个框架就可以。使用DLPI编程并不难,关键在于大家要了解它的框架,没必要非得自己去写一个框架来,本文就是利用了Michael R. Widner的代码,今后如果要增加功能只需要往这个框架里填就可以了。
协议分析的过程是在函数filter完成的,函数申明如下
void filter(register char *cp,register u_int  pktlen);
该函数接收两个参数,cp是直接从设备缓存里拷贝过来的待分析数据,是链路层的封装数据,pktlen是数据的长度。在本文中由于操作环境是以太网,因此接收的数据链路层数据是以太网封装格式,如不清楚以太网封装的可以参考《TCP/IP详解 卷一:协议》,以太网封装三种标准的协议类型:IP协议、ARP协议和RARP协议。14字节的以太网首部包括了6字节的目的地址,6字节的源地址和2字节的类型字段,IP的类型值为0x0800,ARP的类型值为0x0806,RARP的类型值为0x8035。通过检查类型字段来区别接收到的数据是属于哪一种协议,函数实现代码如下
void filter(cp, pktlen)
register char *cp;
register u_int pktlen;
{
register struct ip     *ip;
register struct tcphdr *tcph;
register struct ether_header *eth;
char *head=cp;
static long line_count=0;//计数器,用来记录接收的数据次数

u_short EtherType=ntohs(((struct ether_header *)cp)->;ether_type);
   //如果EtherType小于0x600说明这是一个符合802.3标准的数据格式,应当对数据作出调整
   if(EtherType < 0x600) {
     EtherType = *(u_short *)(cp + SZETH + 6);
     cp+=8; pktlen-=8;
   }
   eth=(struct ether_header*)cp;
   fprintf(LOG,"%-5d",++line_count);
   if(EtherType == ETHERTYPE_IP) //检查协议类型是否IP协议
   {
   ip=(struct ip *)(cp+SZETH);//调整指针的位置,SZETH是以太网首部长度
   Mac_info(&eth->;ether_shost);//Mac_info函数打印出物理地址
   fprintf(LOG,"(";
   Ip_info(&ip->;ip_src);//Ip_info函数打印出IP地址
   fprintf(LOG,"";
   fprintf(LOG,"--->;";
   Mac_info(&eth->;ether_dhost);
   fprintf(LOG,"(";
   Ip_info(&ip->;ip_dst);
   fprintf(LOG,"";
   fprintf(LOG,"\n");
   }
   else if(EtherType == ARP_PROTO)//如果协议类型是ARP
   {
      cp+=SZETH;
      struct ether_arp *arp=(struct ether_arp *)cp;
      switch(ntohs(arp->;ea_hdr.ar_op))//检查arp的操作
      {
        case ARPOP_REQUEST:   //如果是arp请求
            fprintf(LOG,"arp request:who has ");
            arp_ip_info(arp->;arp_tpa);  //打印arp报文信息中的地址
            fprintf(LOG," tells ");
            arp_ip_info(arp->;arp_spa);
            fprintf(LOG,"\n");
            break;
        case ARPOP_REPLY:     //arp应答
            fprintf(LOG,"arp reply: ");
            arp_ip_info(arp->;arp_spa);
            fprintf(LOG," is at  ");
            Mac_info((struct ether_addr*)&arp->;arp_sha);
            fprintf(LOG,"\n");
            break;
       }        
       //可以在这里添加代码打印出arp数据报的具体内容
    }
}
程序的具体实现代码如下:
/*  程序sniffer.c的代码清单 */
#include        <sys/stream.h>;
#include        <sys/dlpi.h>;
#include        <sys/bufmod.h>;

#include <stdio.h>;
#include <ctype.h>;
#include <string.h>;

#include <sys/time.h>;
#include <sys/file.h>;
#include <sys/stropts.h>;
#include <sys/signal.h>;
#include <sys/types.h>;
#include <sys/socket.h>;
#include <sys/ioctl.h>;

#include <net/if.h>;
#include <net/if_arp.h>;

#include <netinet/in.h>;
#include <netinet/if_ether.h>;
#include <netinet/in_systm.h>;
#include <netinet/ip.h>;
#include <netinet/udp.h>;
#include <netinet/ip_var.h>;
#include <netinet/udp_var.h>;
#include <netinet/in_systm.h>;
#include <netinet/tcp.h>;
#include <netinet/ip_icmp.h>;

#include <netdb.h>;
#include <arpa/inet.h>;


#define                MAXDLBUF        32768
#define                MAXWAIT                15
#define                MAXDLADDR        1024
#define         BITSPERBYTE        8

#define bcopy(s1, s2, len) memcpy(s2, s1, len)
#define index(s, c) strchr(s, c)
#define rindex(s, c) strrchr(s, c)

#define bcmp(s1, s2, len) (memcmp(s1, s2, len)!=0)

#define ERR stderr

char    *device,
        *ProgName,
        *LogName;
FILE    *LOG;
int     debug=0;
long        databuf[MAXDLBUF];
int sap=0;
#define NIT_DEV     "/dev/bge"
#define CHUNKSIZE   4096      
int     if_fd = -1;
int     Packet[CHUNKSIZE+32];


int        promisc = 1;       
int        bufmod = 0;               
int        filter_flags=0;       

int        maxbuflen=128;       

void Pexit(err,msg)
int err; char *msg;
{ perror(msg);
  exit(err); }

void Zexit(err,msg)
int err; char *msg;
{ fprintf(ERR,msg);
  exit(err); }
#define ARP_PROTO   (0x0806)
#define IP          ((struct ip *)Packet)
#define IP_OFFSET   (0x1FFF)
#define SZETH       (sizeof(struct ether_header))
#define ARPLEN      (sizeof(struct ether_arp))
#define MACLEN      (6)
#define IPALEN      (4)
#define IPLEN       (ntohs(ip->;ip_len))
#define IPHLEN      (ip->;ip_hl)
#define INET_ADDRSTRLEN 16



#define MAXBUFLEN  (8192)
time_t  LastTIME = 0;



char *Ptm(t)
register time_t *t;
{ register char *p = ctime(t);
  p[strlen(p)-6]=0;
  return(p);
}

char *NOWtm()
{ time_t tm;
  time(&tm);
  return( Ptm(&tm) );
}


void print_data(uchar_t *buf,int size)
{
        int i=0;
        char *p=buf;
        for(;i<size;i++){
                if(i%16 == 0) fprintf(LOG,"\n");
                if(i%2 == 0) fprintf(LOG," ");
                fprintf(LOG,"%02x",*p++&0x00ff);
        }
        fprintf(LOG,"\n");
}
//打印物理地址
void Mac_info(struct ether_addr*mac)
{
   fprintf(LOG,"%02x:%02x:%02x:%02x:%02x:%02x",
           mac->;ether_addr_octet[0],
           mac->;ether_addr_octet[1],
           mac->;ether_addr_octet[2],  
           mac->;ether_addr_octet[3],  
           mac->;ether_addr_octet[4],
           mac->;ether_addr_octet[5]);
}
//打印ip地址char buf[MAXDLBUF];
  
void Ip_info(struct in_addr *ip)
{
   char str[INET_ADDRSTRLEN];
   inet_ntop(AF_INET,ip,str,sizeof(str));
   if(*str)
   fprintf(LOG,"%s",str);
   
}
//打印ip地址的另外一个版本
void arp_ip_info(uchar_t pa[])
{
    fprintf(LOG,"%d.%d.%d.%d",pa[0],pa[1],pa[2],pa[3]);
}

void death()
{ register struct CREC *CLe;

   
    fprintf(LOG,"\nLog ended at =>; %s\n",NOWtm());
    fflush(LOG);
    if(LOG != stdout)
        fclose(LOG);
    exit(1);
}



err(fmt, a1, a2, a3, a4)
char        *fmt;
char        *a1, *a2, *a3, *a4;
{
        (void) fprintf(stderr, fmt, a1, a2, a3, a4);
        (void) fprintf(stderr, "\n");
        (void) exit(1);
}

void
sigalrm()
{
        (void) err("sigalrm:  TIMEOUT");
}

strgetmsg(fd, ctlp, datap, flagsp, caller)
int        fd;
struct        strbuf        *ctlp, *datap;
int        *flagsp;
char        *caller;
{
        int        rc;
        static        char        errmsg[80];

       
        (void) signal(SIGALRM, sigalrm);
        if (alarm(MAXWAIT) < 0) {
                (void) sprintf(errmsg, "%s:  alarm", caller);
                syserr(errmsg);
        }

       
        *flagsp = 0;
        if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
                (void) sprintf(errmsg, "%s:  getmsg", caller);
                syserr(errmsg);
        }

       
        if (alarm(0) < 0) {
                (void) sprintf(errmsg, "%s:  alarm", caller);
                syserr(errmsg);
        }

       
        if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA))
                err("%s:  MORECTL|MOREDATA", caller);
        if (rc & MORECTL)
                err("%s:  MORECTL", caller);
        if (rc & MOREDATA)
                err("%s:  MOREDATA", caller);

       
        if (ctlp->;len < sizeof (long))
                err("getmsg:  control portion length < sizeof (long):  %d", ctlp->;len);
}

expecting(prim, dlp)
int        prim;
union        DL_primitives        *dlp;
{
        if (dlp->;dl_primitive != (u_long)prim) {
                err("unexpected dlprim error\n");
                exit(1);
        }
}
strioctl(fd, cmd, timout, len, dp)
int        fd;
int        cmd;
int        timout;
int        len;
char        *dp;
{
        struct        strioctl        sioc;
        int        rc;

        sioc.ic_cmd = cmd;
        sioc.ic_timout = timout;
        sioc.ic_len = len;
        sioc.ic_dp = dp;
        rc = ioctl(fd, I_STR, &sioc);

        if (rc < 0)
                return (rc);
        else
                return (sioc.ic_len);
}
dlattachreq(fd, ppa)
int        fd;
u_long        ppa;
{
        dl_attach_req_t        attach_req;
        struct        strbuf        ctl;
        int        flags;

        attach_req.dl_primitive = DL_ATTACH_REQ;
        attach_req.dl_ppa = ppa;

        ctl.maxlen = 0;
        ctl.len = sizeof (attach_req);
        ctl.buf = (char *) &attach_req;

        flags = 0;

        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
                syserr("dlattachreq:  putmsg");
}

dlokack(fd, bufp)
int        fd;
char        *bufp;
{
        union        DL_primitives        *dlp;
        struct        strbuf        ctl;
        int        flags;

        ctl.maxlen = MAXDLBUF;
        ctl.len = 0;
        ctl.buf = bufp;

        strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");

        dlp = (union DL_primitives *) ctl.buf;

        expecting(DL_OK_ACK, dlp);

        if (ctl.len < sizeof (dl_ok_ack_t))
                err("dlokack:  response ctl.len too short:  %d", ctl.len);

        if (flags != RS_HIPRI)
                err("dlokack:  DL_OK_ACK was not M_PCPROTO");

        if (ctl.len < sizeof (dl_ok_ack_t))
                err("dlokack:  short response ctl.len:  %d", ctl.len);
}


dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
int        fd;
u_long        sap;
u_long        max_conind;
u_long        service_mode;
u_long        conn_mgmt;
u_long        xidtest;
{
        dl_bind_req_t        bind_req;
        struct        strbuf        ctl;
        int        flags;

        bind_req.dl_primitive = DL_BIND_REQ;
        bind_req.dl_sap = sap;
        bind_req.dl_max_conind = max_conind;
        bind_req.dl_service_mode = service_mode;
        bind_req.dl_conn_mgmt = conn_mgmt;
        bind_req.dl_xidtest_flg = xidtest;

        ctl.maxlen = 0;
        ctl.len = sizeof (bind_req);
        ctl.buf = (char *) &bind_req;

        flags = 0;

        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
                syserr("dlbindreq:  putmsg");
}

dlbindack(fd, bufp)
int        fd;
char        *bufp;
{
        union        DL_primitives        *dlp;
        struct        strbuf        ctl;
        int        flags;

        ctl.maxlen = MAXDLBUF;
        ctl.len = 0;
        ctl.buf = bufp;

        strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");

        dlp = (union DL_primitives *) ctl.buf;

        expecting(DL_BIND_ACK, dlp);

        if (flags != RS_HIPRI)
                err("dlbindack:  DL_OK_ACK was not M_PCPROTO");

        if (ctl.len < sizeof (dl_bind_ack_t))
                err("dlbindack:  short response ctl.len:  %d", ctl.len);
}

dlpromisconreq(fd, level)
int        fd;
u_long        level;
{
        dl_promiscon_req_t        promiscon_req;
        struct        strbuf        ctl;
        int        flags;

        promiscon_req.dl_primitive = DL_PROMISCON_REQ;
        promiscon_req.dl_level = level;

        ctl.maxlen = 0;
        ctl.len = sizeof (promiscon_req);
        ctl.buf = (char *) &promiscon_req;

        flags = 0;

        if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
                syserr("dlpromiscon:  putmsg");

}

syserr(s)
char        *s;
{
        (void) perror(s);
        exit(1);
}




void filter(cp, pktlen)
register char *cp;
register u_int pktlen;
{
register struct ip     *ip;
register struct tcphdr *tcph;
register struct ether_header *eth;
char *head=cp;
static long line_count=0;

u_short EtherType=ntohs(((struct ether_header *)cp)->;ether_type);
   
   if(EtherType < 0x600) {
     EtherType = *(u_short *)(cp + SZETH + 6);
     cp+=8; pktlen-=8;
   }
   eth=(struct ether_header*)cp;
   fprintf(LOG,"%-5d",++line_count);
   if(EtherType == ETHERTYPE_IP)
   {
   ip=(struct ip *)(cp+SZETH);
   

   Mac_info(&eth->;ether_shost);
   fprintf(LOG,"(");
   Ip_info(&ip->;ip_src);
  
   fprintf(LOG,")");
   fprintf(LOG,"--->;");
   Mac_info(&eth->;ether_dhost);
   fprintf(LOG,"(");
   Ip_info(&ip->;ip_dst);
  
   fprintf(LOG,")");
   fprintf(LOG,"\n");
   
   
  
   }
   else if(EtherType == ARP_PROTO)
   {
      cp+=SZETH;
      struct ether_arp *arp=(struct ether_arp *)cp;
      switch(ntohs(arp->;ea_hdr.ar_op))
      {
        case ARPOP_REQUEST:
            fprintf(LOG,"arp request:who has ");
            arp_ip_info(arp->;arp_tpa);
            fprintf(LOG," tells ");
            arp_ip_info(arp->;arp_spa);
            fprintf(LOG,"\n");
            break;
        case ARPOP_REPLY:
            fprintf(LOG,"arp reply: ");
            arp_ip_info(arp->;arp_spa);
            fprintf(LOG," is at  ");
            Mac_info((struct ether_addr*)&arp->;arp_sha);
            fprintf(LOG,"\n");
            break;
        
       }        
       //打印出arp数据报的内容
      
    }



}

do_it()
{
        long        buf[MAXDLBUF];
        char        *device;
        int        ppa;
        int        fd;
       
        struct        strbuf        data;
        int        flags;
        int        i;
        int        c;
        int        offset;
        int        len;
        struct        timeval        t;
        u_int        chunksize = 16 * 1024;
        struct        sb_hdr        *bp;
        char        *p, *limp;

        int mrwtmp;

        device = "/dev/bge";
        ppa = 0;
        sap= 0x0806;

       
        if ((fd = open(device, 2)) < 0)
                syserr(device);

        dlattachreq(fd, ppa);
        dlokack(fd, buf);

       
        if (promisc) {
                dlpromisconreq(fd, DL_PROMISC_PHYS);         
                dlokack(fd, buf);
        }

       
        dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0);
        dlbindack(fd, buf);
      
       
        if (strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0)
                syserr("DLIOCRAW");
       
        if (bufmod) {
                if (ioctl(fd, I_PUSH, "bufmod") < 0)
                        syserr("push bufmod");

                t.tv_sec = 0;
                t.tv_usec = 500000;       
                if (strioctl(fd, SBIOCSTIME, -1, sizeof (struct timeval),
                        &t) < 0)
                        syserr("SBIOCSTIME");
                if (strioctl(fd, SBIOCSCHUNK, -1, sizeof (u_int),
                        &chunksize) < 0)
                        syserr("SBIOCSCHUNK");
        }

       
        if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
                syserr("I_FLUSH");
         
        if(1){
        data.buf = (char *) databuf;
        data.maxlen = MAXDLBUF;
        data.len = 0;

      
        while (((mrwtmp=getmsg(fd, NULL, &data, &flags))==0) ||
                 (mrwtmp==MOREDATA) || (mrwtmp=MORECTL)) {
                p = data.buf;
                limp = p + data.len;
                        filter(data.buf, data.len);
                data.len = 0;
        }
        printf("finished getmsg() = %i\n",mrwtmp);
             }
        
}


int main(argc, argv)
int argc;
char **argv;
{
    char   cbuf[BUFSIZ];
    struct ifconf ifc;
    int    s,
           ac=1,
           backg=0;

    ProgName=argv[0];


    device=NIT_DEV;
    while((ac<argc) && (argv[ac][0] == '-')) {
       register char ch = argv[ac++][1];
       switch(toupper(ch)) {
            case 'I': device=argv[ac++];
                      break;
            case 'O': if(!(LOG=fopen((LogName=argv[ac++]),"a")))
                         Zexit(1,"Output file cant be opened\n");
                      break;
            case 's':
                      sap=atoi(argv[ac++]);
                      break;
            default : fprintf(ERR,
                        "Usage: %s  [-s]  [-i interface] [-o file]\n",
                            ProgName);
                fprintf(ERR,"        -d int    set new data limit (128 default)\n");
                fprintf(ERR,"        -o <file>; output to <file>;\n");
                      exit(1);
       }
    }

    fprintf(ERR,"Using logical device %s [%s]\n",device,NIT_DEV);
    fprintf(ERR,"Output to %s.%s%s",(LOG)?LogName:"stdout",
            (debug)?" (debug)":"",(backg)?" Backgrounding ":"\n");

    if(!LOG)
        LOG=stdout;

    signal(SIGINT, death);
    signal(SIGTERM,death);
    signal(SIGKILL,death);
    signal(SIGQUIT,death);

    if(backg && debug) {
         fprintf(ERR,"[Cannot bg with debug on]\n");
         backg=0;
    }

    fprintf(LOG,"\nLog started at =>; %s [pid %d]\n",NOWtm(),getpid());
    fflush(LOG);

    do_it();
}



编译运行:
#gcc -lsocket -lsnl -o sniffer sniffer.c
#./sniffer
同时在另一个终端上运行ping 192.168.1.10

Using logical device /dev/bge [/dev/bge]
Output to stdout.

Log started at =>; Tue Jul 12 18:13:44 [pid 948]
1    arp request:who has 192.168.1.22 tells 192.168.1.10
2    arp request:who has 192.168.1.22 tells 192.168.1.10
3    arp request:who has 192.168.1.22 tells 192.168.1.10
4    arp request:who has 192.168.1.22 tells 192.168.1.10
5    arp request:who has 192.168.1.22 tells 192.168.1.10

论坛徽章:
0
发表于 2005-07-13 13:57 |显示全部楼层

使用DLPI来编写协议分析工具

原帖由 "stevens_wu" 发表:

1    arp request:who has 192.168.1.22 tells 192.168.1.10
2    arp request:who has 192.168.1.22 tells 192.168.1.10
3    arp request:who has 192.168.1.22 tells 192.168.1.10
4    arp request:who has..........



不错,不错,
不过DLPI比较老,好像solaris有新的链路层接口:

gld v2.0

不知道是不是更好用?

论坛徽章:
0
发表于 2005-07-13 18:35 |显示全部楼层

使用DLPI来编写协议分析工具

正在努力学习gld中......,不过最近比较忙
使用DLPI的有一点好处是不仅仅在sun的系统上运行,同样能在svr4的兼容系统中运行

论坛徽章:
0
发表于 2007-12-03 16:58 |显示全部楼层
不过该程序只能过滤得到arp的报文,其他ip的报文却得不到,不知道这是为什么
有高手指点一下吧。

论坛徽章:
0
发表于 2007-12-13 17:08 |显示全部楼层

回复 #4 mingjwan 的帖子

因为我在程序中过滤了其他的报文,只保留了arp,你可以自己动手来实现其他的协议。

论坛徽章:
0
发表于 2007-12-13 17:10 |显示全部楼层
原帖由 stevens_wu 于 2007-12-13 17:08 发表
因为我在程序中过滤了其他的报文,只保留了arp,你可以自己动手来实现其他的协议。

不要一直等别人喂你
代码最好用[code]包一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP