./c0de/c/halfscan.txt

0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
/*
 * Half open port scanner. Send SYNs, and look for a SYN-ACK. If you see one,
 * the port is listening.
 *
 * The whole point is to evade TCP-wrapper software and other alarm systems
 * which look for a fully established connection. Since this never establishes
 * a connection, its existance isn't logged.
 *
 * Note, this can be detected by things like TCPdump, or other raw network
 * monitors.
 *
 * Runs under SunOS 4.x with NIT. This is a proof-of-concept toy, not a
 * production model. :-)
 *
 * Mike Neuman
 * 12/7/93
 *
 * You can do whatever you want with this code as long as you leave this
 * header intact.
 *
 * Contact information:
 *
 * Mike Neuman ([email protected]) - http://www.engarde.com/~mcn
 */
 
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <malloc.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <net/nit.h>
#include <sys/fcntlcom.h>
 
#include <sys/param.h>
#include <sys/dir.h>
#include <net/nit_if.h>
#include <net/nit_pf.h>
#include <net/nit_buf.h>
#include <net/packetfilt.h>
#include <sys/stropts.h>
 
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <sys/stream.h>
#include <sys/tihdr.h>
 
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
 
/* RPC makes an rpcdump call, which may be logged by a secure portmapper.
 * If you're paranoid and want to guess at rpc stuff, specify -r
 */
 
main(argc,argv)
int argc;
char *argv[];
 
{
  struct sockaddr_in server;
  struct servent *sp;
  struct hostent *hp;
  int c, s, count, userpc=1, sock=RPC_ANYSOCK, minport = 1, maxport = 6001;
  struct pmaplist *head = NULL, *headp=NULL;
  struct timeval timeout;
  register CLIENT *client;
  struct rpcent *rpc;
  unsigned long addr;
  char *hostp;
  extern char *optarg;
  extern int optind;
 
 
  /* 1: Parse options, get host addr */
  while ((c = getopt(argc, argv, "rhm:M:")) != -1)
    switch(c) {
      case 'r':
        userpc = 0;
        break;
      case 'm':
        minport = atoi(optarg);
        break;
      case 'M':
        maxport = atoi(optarg);
        break;
      case 'h':
        usage(argv[0]);
        exit(1);
    }
 
  if (optind != argc-1) {
    usage(argv[0]);
    exit(1);
  }
 
  if (minport > maxport || minport <= 0) {
    fprintf(stderr, "ERROR: minport must be > 0 and <= maxport\n");
    usage(argv[0]);
    exit(1);
  }
  hostp = argv[optind];
 
  if ((hp=gethostbyname(hostp))==NULL) {
    addr = inet_addr(hostp);
    if (addr == (u_long)-1) {
      fprintf(stderr, "Unknown host '%s'\n", hostp);
      usage(argv[0]);
      exit(1);
    }
    bcopy(&server.sin_addr, &addr, 4);
  } else {
    bzero((char *)&server, sizeof server);
    bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
    server.sin_family=hp->h_addrtype;
  }
 
  printf("Connections established for host %s:\n",hostp);
 
  /* 2: Call rpc and get its ports */
  head=NULL;
  if (userpc) {
    server.sin_port=htons(PMAPPORT);
    timeout.tv_sec=10;
    timeout.tv_usec=0;
    if ((client = clnttcp_create(&server, PMAPPROG,
                                 PMAPVERS, &sock, 50, 500))!=NULL) {
      if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
                    xdr_pmaplist, &head, timeout) != RPC_SUCCESS)
        head=NULL;
    }
  }
 
  /* 3: Try each port from minport - maxport */
  for (count=minport;count<=maxport;count++) {
    printf("\r%6d",count);
    fflush(stdout);
    server.sin_port=count;
    if (!fakeconnect(&server, hostp)) {
      printf("\r   %4d tcp   ",count);
      sp=getservbyport(count,"tcp");
      if (sp==NULL) {
        switch(count) {
          /* Put in known services not in /etc/services here */
          case 2000: printf("(Xnews)");
            break;
          case 6000: printf("(X)");
            break;
          default:
            if (userpc) {
              headp=head;
              while (headp!=NULL) {
                if (headp->pml_map.pm_prot!=IPPROTO_TCP) {
                  headp=headp->pml_next;
                  continue;
                }
                if (count!=headp->pml_map.pm_port) {
                  headp=headp->pml_next;
                  continue;
                }
                rpc = getrpcbynumber(headp->pml_map.pm_prog);
                if (rpc) {
                  printf("%-15s [rpc]", rpc->r_name);
                  break;
                } else {
                  headp=headp->pml_next;
                  continue;
                }
              }
              if (rpc==NULL)
                printf("                [rpc]");
            } else
              printf("???\n");
            break;
        }
      } else
        printf("%-15s",sp->s_name);
      printf("\n");
    }
  }
  printf("\n");
  exit(0);
}
 
usage(prog)
char *prog;
{
  fprintf(stderr,"Usage: %s [-r] [-m minport] [-M maxport] host\n", prog);
  fprintf(stderr,"Options:\n");
  fprintf(stderr,"-r       Don't use RPC for port info\n");
  fprintf(stderr,"-m port  Specify port number to start at (default 1)\n");
  fprintf(stderr,"-M port  Specify port number to end at   (default 6001)\n");
  return;
}
 
 
int scan_return(fd, iph, tcph)
int fd;
struct ip *iph;
struct tcphdr *tcph;
 
{
  char buf[8*1024], *bp, *bufstop, *cp, abuf[2048];
  int cc, done=0, retval=0;
  struct nit_bufhdr *hdrp;
  struct nit_iftime *ntp;
  struct nit_ifdrops *ndp;
  struct nit_iflen *nlp;
  struct ether_header *ep;
  u_short et;
  register struct ip *ip;
  struct tcphdr *tp;
 
  while (!done) {
    if ((cc=read(fd, buf, 8*1024)) >= 0) {
      bp=buf;
      bufstop = buf+cc;
      while (bp < bufstop) {
        cp = bp;
 
        /* Get past NIT buffer */
        hdrp = (struct nit_bufhdr *)cp;
        cp += sizeof(*hdrp);
 
        /* get past NIT timer   */
        ntp = (struct nit_iftime *)cp;
        cp += sizeof(*ntp);
 
        /* get past the drops */
        ndp = (struct nit_ifdrops *)cp;
        cp += sizeof(*ndp);
 
        /* get past packet len  */
        nlp = (struct nit_iflen *)cp;
        cp += sizeof(*nlp);
 
        /* next snapshot        */
        bp += hdrp->nhb_totlen;
 
        /* Okay, got the packet, make sure it's a SYN-ACK reply */
        ep = (struct ether_header *)cp;
        et = ntohs(ep->ether_type);
        if ( et >= ETHERTYPE_TRAIL && et < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)
          continue;
        cp += sizeof(struct ether_header);
        nlp->nh_pktlen -= sizeof(struct ether_header);
        if (et != ETHERTYPE_IP) continue;
 
        /* It's: ethernet + IP */
 
        ip=(struct ip *)cp;
        bcopy((char *)ip, (char *)abuf, nlp->nh_pktlen); /* Align */
        ip = (struct ip *)abuf;
 
        if (ip->ip_p != IPPROTO_TCP)
          continue;
 
        /* It's ethernet + IP + TCP */
        if (ip->ip_src.s_addr != iph->ip_dst.s_addr)
          continue;
        if (ip->ip_dst.s_addr != iph->ip_src.s_addr)
          continue;
 
        /* It's ethernet + IP + TCP + from target + to us */
        cp+=sizeof(struct ip);
        tp = (struct tcphdr *)cp;
        if (tp->th_sport != tcph->th_dport)
          continue;
        if (tp->th_dport != tcph->th_sport)
          continue;
 
        /* It's ethernet + IP + TCP + from target + to us + ports right */
        if ((tp->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
          retval=0;
          done=1;
        } else {
          retval=1;
          done=1;
        }
        break;
      } /* While (bp<bufstop) */
    } /* if read */
  } /* while !done */
  return(retval);
}
 
jmp_buf env_buf;
 
/* Signal handler for receive timeout */
handle_alarm()
{
  alarm(0); /* Clear the alarm */
  longjmp(env_buf, 1);
}
 
/*
 * Sends a packet, and waits for the reply
 */
int send_packet(fd, server, servername, localnet, netmask)
int fd;
struct sockaddr_in *server;
char *servername;
u_long localnet;
u_long netmask;
 
{
  static struct sockaddr sa;
  static struct strbuf ctl, datah;
  static struct ip iph;
  static char buf[2048], pbuf[2048], *oldbp;
  static int computed=0;
 
  struct ether_header eh;
  struct tcphdr tcph;
  char *bp, *pbp;
  struct ether_addr myaddr, faddr;
  FILE *fp;
  struct hostent *he;
  u_long x;
  int retval;
 
  if (!computed) {
    /* ARP for the router/host, if possible */
    int s;
    struct arpreq arpreq;
    struct sockaddr_in *s_arp;
 
    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
      perror("Socket");
      exit(1);
    }
 
    arpreq.arp_pa.sa_family = AF_INET;
    s_arp = (struct sockaddr_in *)&arpreq.arp_pa;
    s_arp->sin_family = AF_INET;
    s_arp->sin_addr.s_addr = server->sin_addr.s_addr;
 
    /* First, send junk to it to get an ARP entry */
    s_arp->sin_port = 9;
    sendto(s, "blah", 4, 0, (struct sockaddr *)s_arp,
           sizeof(struct sockaddr_in));
    s_arp = (struct sockaddr_in *)&arpreq.arp_ha;
    s_arp->sin_family = AF_UNSPEC;
 
    if (ioctl(s, SIOCGARP, &arpreq) < 0) {
      perror("ioctl");
      close(s);
      exit(1);
    }
 
    if (arpreq.arp_flags & ATF_COM) {
      bcopy(arpreq.arp_ha.sa_data, &faddr, 6);
    } else {
      fprintf(stderr, "Can't find destination/router hardware address.\n");
      exit(1);
    }
    /* faddr and myaddr are now computed, create the ether header */
    bcopy(&faddr, &eh.ether_dhost, 6);
    eh.ether_type = htons(ETHERTYPE_IP);
    sa.sa_family = AF_UNSPEC;
    bcopy((char *)&eh, (char *)sa.sa_data, sizeof(struct ether_header));
    ctl.len = sizeof(struct sockaddr);
    ctl.buf = (char *)&sa;
    bp = buf;
 
    iph.ip_v = IPVERSION;
    iph.ip_hl = 5; /* 20 octets--no options */
    iph.ip_tos = htons(0);   /* No special service */
    iph.ip_len = htons(40);
    iph.ip_id = htons(27); /* "unique" identification */
    iph.ip_off = htons(0);
    iph.ip_ttl = htons(60);
    iph.ip_p = htons(IPPROTO_TCP);
    iph.ip_dst.s_addr = server->sin_addr.s_addr;
    gethostname(buf, 2048);
    he = gethostbyname(buf);
    bcopy((char *)he->h_addr,
          (char *)&iph.ip_src.s_addr,
          sizeof(iph.ip_src.s_addr));
    iph.ip_sum = 0;
    iph.ip_sum = htons(in_cksum_c(&iph, (iph.ip_hl << 2)));
    bcopy((char *)&iph, bp, sizeof(struct ip));
    bp += sizeof(struct ip);
    oldbp = bp;
    computed=1;
  } /* if !computed */
  /* Set up the TCP header */
  bp = oldbp;
  tcph.th_sport = 5894; /* Random number */
  tcph.th_dport = server->sin_port;
  tcph.th_seq = 59595; /* Random number */
  tcph.th_ack = 0;
  tcph.th_off = 5;
  tcph.th_flags = TH_SYN;
  tcph.th_win = 4096;
  tcph.th_sum = 0;
  /* Calculate the TCP checksum on the TCP pseudoheader*/
  pbp=pbuf;
  bcopy((char *)&iph.ip_src.s_addr, pbp, 4);
  pbp+=4;
  bcopy((char *)&iph.ip_dst.s_addr, pbp, 4);
  pbp+=4;
  *pbp=0;
  pbp++;
  *pbp=(char)iph.ip_p;
  pbp++;
  *(u_short *)pbp=(u_short)sizeof(struct tcphdr);
  pbp+=2; /* go past the u_short */
  bcopy((char *)&tcph, pbp, sizeof(struct tcphdr));
  pbp+=sizeof(struct tcphdr);
  if ((pbp-pbuf)%2) {
    *pbp=(char)0;
    pbp++;
  }
  tcph.th_sum = htons(in_cksum_c(pbuf, (int)(pbp-pbuf)));
 
  bcopy((char *)&tcph, bp, sizeof(struct tcphdr));
  bp += sizeof(struct tcphdr);
 
  datah.len = (int)(bp-buf);
  datah.buf = (char *)buf;
 
  if (putmsg(fd, &ctl, &datah, 0) < 0) {
    perror("putmsg (ctl)");
    switch(errno) {
      case EAGAIN: fprintf(stderr,"EAGAIN\n");break;
      case EBADF: fprintf(stderr,"Bad FD\n");break;
      case EFAULT: fprintf(stderr,"Bad ctlptr or dataptr\n");break;
      case EINTR: fprintf(stderr,"Signal caught\n");break;
      case EINVAL: fprintf(stderr,"undefined flag\n");break;
      case ENOSTR: fprintf(stderr,"No stream\n");break;
      case ENXIO: fprintf(stderr,"hangup downstream\n");break;
      case ERANGE: fprintf(stderr,"data size problem\n");break;
    }
    exit(1);
  }
  /* Now that we've sent the syn, scan all return packets for reply */
  if (!setjmp(env_buf)) {
    signal(SIGALRM, handle_alarm, -1);
    alarm(1);
    retval=scan_return(fd, &iph, &tcph);
    alarm(0);
  } else retval=1;
  return(retval);
}
 
int fakeconnect(server, servername)
/*
 * Fake the connection, return 1 on failure, 0 on success
 */
struct sockaddr_in *server;
char *servername;
{
  static int if_fd = -1;
  char *device=0;
  u_long localnet;
  u_long netmask;
  int linktype;
  char *lookup_device();
  void lookup_net();
 
  if (if_fd == -1) {
    if (device==0) {
      device = lookup_device();
      if (device == 0)
        perror("can't find any interfaces");
    }
    if_fd = initdevice(device, &linktype);
    lookup_net(device, &localnet, &netmask);
  }
  return(send_packet(if_fd, server, servername, localnet, netmask));
}
 
 
/* ====================== begin nasty NIT stuff ======================= */
 
 
/* Not all systems have IFF_LOOPBACK */
#ifdef IFF_LOOPBACK
#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
#else
#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0)
#endif
 
char *lookup_device()
{
  struct ifreq ibuf[16], *ifrp, *ifend, *mp;
  struct ifconf ifc;
  int fd;
  int minunit, n;
  char *cp;
  static char device[sizeof(ifrp->ifr_name)];
 
  fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (fd < 0) {
    perror("newscan: socket");
    exit(1);
  }
  ifc.ifc_len = sizeof(ibuf);
  ifc.ifc_buf = (caddr_t)ibuf;
 
  if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
      ifc.ifc_len < sizeof(struct ifreq)) {
    perror("newscan: SIOCGIFCONF: ");
    exit(1);
  }
  ifrp = ibuf;
  ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
 
  mp = 0;
  minunit = 666;
  while (ifrp < ifend) {
    struct ifreq ifr;
    /*
     * Need a template to preserve address info that is
     * used below to locate the next entry.  (Otherwise,
     * SIOCGIFFLAGS stomps over it because the requests
     * are returned in a union.)
     */
    bcopy(ifrp->ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
    if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
      fprintf(stderr, "newscan: SIOCGIFFLAGS: ");
      perror(ifrp->ifr_name);
      exit(1);
    }
    if ((ifr.ifr_flags & IFF_UP) && !ISLOOPBACK(&ifr)) {
      for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
        ;
      n = atoi(cp);
      if (n < minunit) {
        minunit = n;
        mp = ifrp;
      }
    }
#if BSD >= 199006
    n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
    if (n < sizeof(*ifrp))
      ++ifrp;
    else
      ifrp = (struct ifreq *)((char *)ifrp + n);
#else
    ++ifrp;
#endif
  }
  close(fd);
  if (mp == 0)
    return (0);
 
  (void)strcpy(device, mp->ifr_name);
  return (device);
}
 
/*
 * Get the netmask of an IP address.  This routine is used if
 * SIOCGIFNETMASK doesn't work.
 */
static u_long
ipaddrtonetmask(addr)
u_long addr;
{
  char str[80];
 
  if (IN_CLASSA(addr))
    return (IN_CLASSA_NET);
  if (IN_CLASSB(addr))
    return (IN_CLASSB_NET);
  if (IN_CLASSC(addr))
    return (IN_CLASSC_NET);
  sprintf(str,"unknown IP address class: %08X", addr);
  perror(str);
  /* NOTREACHED */
}
 
void
lookup_net(device, netp, maskp)
char *device;
u_long *netp;
u_long *maskp;
{
  int fd;
  struct ifreq ifr;
  struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
 
  /* Use data gram socket to get IP address. */
  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("newscan: socket");
    exit(1);
  }
  (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
    /*
     * This will fail if an IP address hasn't been assigned.
     */
    *netp = 0;
    *maskp = 0;
    return;
  }
  *netp = sin->sin_addr.s_addr;
  if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0)
    *maskp = 0;
  else
    *maskp = sin->sin_addr.s_addr;
  if (*maskp == 0)
    *maskp = ipaddrtonetmask(*netp);
  *netp &= *maskp;
  (void)close(fd);
}
 
u_long snaplen = 0;
 
int
initdevice(device,linktype)
char *device;
int *linktype;
{
  struct strioctl si;             /* struct for ioctl() */
  struct timeval timeout;         /* timeout for ioctl() */
  struct ifreq ifr;               /* interface request struct */
  u_long if_flags;                /* modes for interface             */
  int  ret;
  /*  int chunksize = (8*1024); */
  int chunksize = 0;
  int if_fd;
  char *dev = "/dev/nit";
  int nonblock;
 
  struct ether_header eh;
  struct ip iptest;
  struct packetfilt pf;
  register u_short *fwp = pf.Pf_Filter;
  u_short ethoffset;
  u_short ipoffset;
  u_short masker = 255;
 
  si.ic_timout = INFTIM;
 
  /* Set up the Packet Filter */
  ethoffset=((u_int)&eh.ether_type-(u_int)&eh.ether_dhost)/(sizeof(u_short));
  ipoffset = 11;
  *fwp++ = ENF_PUSHZERO;
  *fwp++ = ENF_PUSHWORD + ethoffset;
  *fwp++ = ENF_PUSHLIT;
  *fwp++ = htons(ETHERTYPE_IP);
  *fwp++ = ENF_COR;
  *fwp++ = ENF_PUSHWORD + ipoffset;
  *fwp++ = ENF_PUSHLIT;
  *fwp++ = (u_short)255;
  *fwp++ = ENF_AND;
  *fwp++ = ENF_PUSHLIT;
  *fwp++ = (u_short)6;
  *fwp++ = ENF_COR;
  *fwp++ = ENF_PUSHLIT;
  *fwp++ = (u_short)1;
 
  /* open /dev/nit Read/write */
  if ((if_fd = open(dev, O_RDWR)) < 0) {
    (void) fprintf(stderr, "newscan: open: ");
    perror(dev);
    exit(-1);
  }
 
  /* arrange to get discrete messages from the STREAM and use NIT_BUF */
  ioctl(if_fd, I_SRDOPT, (char*)RMSGD);
 
  /* it is important to have this stuff in the stream BEFORE! the nbuf */
  si.ic_cmd = NIOCSETF;
  si.ic_len = sizeof(struct packetfilt);
  si.ic_dp = (char*)&pf;
  pf.Pf_FilterLen = fwp - &pf.Pf_Filter[0];
  if (ioctl(if_fd, I_PUSH, "pf")<0) {
    perror("I_PUSH pf");
    fprintf(stderr,"No pf being used\n");
  } else {
    if ((ioctl(if_fd, I_STR, (char*)&si)) < 0) {
      perror("newscan: NIOCSETF");
      /* exit(-1); */
      fprintf(stderr,"No pf being used (or one already applied)\n");
    }
  }
 
  ioctl(if_fd, I_PUSH, "nbuf");
 
  /* set the timeout */
  timeout.tv_sec = 1;
  timeout.tv_usec = 0;
  si.ic_cmd = NIOCSTIME;
  si.ic_len = sizeof(timeout);
  si.ic_dp = (char*)&timeout;
  if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
    perror("newscan: NIOCSTIME");
    exit(-1);
  }
 
  /* set the chunksize */
  si.ic_cmd = NIOCSCHUNK;
  si.ic_len = sizeof(chunksize);
  si.ic_dp = (char*)&chunksize;
  if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
    perror("newscan: NIOCSCHUNK");
    exit(-1);
  }
 
  /* Set up the NIT device (bind it,set snapshot length etc) */
  /* bind the interface */
  strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
  si.ic_cmd = NIOCBIND;
  si.ic_len = sizeof(ifr);
  si.ic_dp = (char*)&ifr;
  if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
    (void) fprintf(stderr, "newscan: NIOCBIND");
    perror(ifr.ifr_name);
    exit(1);
  }
 
  /* set the snapshot length */
  si.ic_cmd = NIOCSSNAP;
  si.ic_len = sizeof(snaplen);
  si.ic_dp = (char*)&snaplen;
  if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
    perror("newscan: NIOCSSNAP");
    exit(1);
  }
 
  /* set the interface flags */
  si.ic_cmd = NIOCSFLAGS;
  if_flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
  if_flags |= NI_PROMISC;
  si.ic_len = sizeof(if_flags);
  si.ic_dp = (char*)&if_flags;
  if ((ioctl(if_fd, I_STR, (char*)&si)) < 0) {
    perror("newscan: NIOCSFLAGS");
    exit(1);
  }
 
  nonblock = 1;
  ioctl(if_fd, FIONBIO,&nonblock);
 
  ioctl(if_fd, I_FLUSH, (char*)FLUSHR);
  /*
   * NIT supports only ethernets.
   */
  *linktype = 1;
 
  return if_fd;
}
 
 
 

Back