#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2012
    Posts
    2
    Rep Power
    0

    Need help identifying packet headers


    I'm required to write a packet sniffer in the C programming language and Identify the Packet as IP, ARP, or Broadcast. I'm able to get IP packets identified but don't seem to be seeing any ARP or Broadcasts correctly.

    I also get this warning when I compile my code:
    /netdump.c: In function 'raw_print':
    ./netdump.c:284: warning: cast to pointer from integer of different size
    ./netdump.c:285: warning: comparison between pointer and integer


    Code:
    #define RETSIGTYPE void
    #include <sys/types.h>
    #include <sys/time.h>
    #include <netinet/in.h>
    #include <pcap.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    #ifndef setsignal_h
    #define setsignal_h
    
    RETSIGTYPE (*setsignal(int, RETSIGTYPE (*)(int)))(int);
    #endif
    
    /* Ethernet addresses are 6 bytes */
    #define ETHER_ADDR_LEN	6
    #define SIZE_ETHERNET 	14
    #define SIZE_IPHDR		20
    
    /* Ethernet header */
    struct sniff_ethernet {
    	u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
    	u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
    	u_short ether_type; 				/* IP? ARP? etc */
    };
    
    /* ARP packet */
    struct sniff_arp {
    	u_short arp_hwtype;
    	u_short arp_proto;
    	u_char arp_addrlen;
    	u_char arp_protolen;
    	u_short arp_operation;
    	u_char arp_src[6];
    	u_char arp_src_proto_addr[4];
    	u_char arp_dst[6];
    	u_char arp_dst_proto_addr[4];
    };
    
    /* IP header */
    struct sniff_ip {
    	u_char ip_vhl;				/* version << 4 | header length >> 2 */
    	u_char ip_tos;				/* type of service */
    	u_short ip_len;				/* total length */
    	u_short ip_id;				/* identification */
    	u_short ip_off;				/* fragment offset field */
    	#define IP_RF 0x8000		/* reserved fragment flag */
    	#define IP_DF 0x4000		/* dont fragment flag */
    	#define IP_MF 0x2000		/* more fragments flag */
    	#define IP_OFFMASK 0x1fff	/* mask for fragmenting bits */
    	u_char ip_ttl;				/* time to live */
    	u_char ip_p;				/* protocol */
    	u_short ip_sum;				/* checksum */
    	u_char ip_src[4];			/* source port */
    	u_char ip_dst[4];			/* destination port */
    	//	struct in_addr ip_src,ip_dst; /* source and dest address */
    };
    
    int nPackets = 1;
    int nARP = 0;
    int nIP = 0;
    int nBroadcast = 0;
    
    
    char cpre580f98[] = "netdump";
    
    void raw_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p);
    
    int packettype;
    
    char *program_name;
    
    /* Externs */
    extern void bpf_dump(struct bpf_program *, int);
    
    extern char *copy_argv(char **);
    
    /* Forwards */
     void program_ending(int);
    
    /* Length of saved portion of packet. */
    int snaplen = 1500;;
    
    static pcap_t *pd;
    
    extern int optind;
    extern int opterr;
    extern char *optarg;
    int pflag = 0, aflag = 0;
    
    int
    main(int argc, char **argv)
    {
            int cnt, op, i, done = 0;
            bpf_u_int32 localnet, netmask;
            char *cp, *cmdbuf, *device;
            struct bpf_program fcode;
             void (*oldhandler)(int);
            u_char *pcap_userdata;
            char ebuf[PCAP_ERRBUF_SIZE];
    
            cnt = -1;
            device = NULL;
    
            if ((cp = strrchr(argv[0], '/')) != NULL)
                    program_name = cp + 1;
            else
                    program_name = argv[0];
    
            opterr = 0;
            while ((i = getopt(argc, argv, "pa")) != -1)
            {
                    switch (i)
                    {
                    case 'p':
                            pflag = 1;
                    break;
                    case 'a':
                            aflag = 1;
                    break;
                    case '?':
                    default:
                            done = 1;
                    break;
                    }
                    if (done) break;
            }
            if (argc > (optind)) cmdbuf = copy_argv(&argv[optind]);
                    else cmdbuf = "";
    
            if (device == NULL) {
                    device = pcap_lookupdev(ebuf);
                    if (device == NULL)
                            error("%s", ebuf);
            }
            pd = pcap_open_live(device, snaplen,  1, 1000, ebuf);
            if (pd == NULL)
                    error("%s", ebuf);
            i = pcap_snapshot(pd);
            if (snaplen < i) {
                    warning("snaplen raised from %d to %d", snaplen, i);
                    snaplen = i;
            }
            if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
                    localnet = 0;
                    netmask = 0;
                    warning("%s", ebuf);
            }
            /*
             * Let user own process after socket has been opened.
             */
            setuid(getuid());
    
            if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
                    error("%s", pcap_geterr(pd));
    
            (void)setsignal(SIGTERM, program_ending);
            (void)setsignal(SIGINT, program_ending);
            /* Cooperate with nohup(1) */
            if ((oldhandler = setsignal(SIGHUP, program_ending)) != SIG_DFL)
                    (void)setsignal(SIGHUP, oldhandler);
    
            if (pcap_setfilter(pd, &fcode) < 0)
                    error("%s", pcap_geterr(pd));
            pcap_userdata = 0;
            (void)fprintf(stderr, "%s: listening on %s\n", program_name, device);
            if (pcap_loop(pd, cnt, raw_print, pcap_userdata) < 0) {
                    (void)fprintf(stderr, "%s: pcap_loop: %s\n",
                        program_name, pcap_geterr(pd));
                    exit(1);
            }
            pcap_close(pd);
            exit(0);
    }
    
    /* routine is executed on exit */
    void program_ending(int signo)
    {
            struct pcap_stat stat;
    
            if (pd != NULL && pcap_file(pd) == NULL) {
                    (void)fflush(stdout);
                    putc('\n', stderr);
                    if (pcap_stats(pd, &stat) < 0)
                            (void)fprintf(stderr, "pcap_stats: %s\n",
                                pcap_geterr(pd));
                    else {
    					printf("Statistics:\n_________________________________________________\n");
    					printf("Packet Counts:\n");
    					printf("ARP......%d\n",nARP); 
    					printf("IP.......%d\n",nIP);
    					printf("BRDCST...%d\n\n",nBroadcast); 
    					printf("\n\n");
    					(void)fprintf(stderr, "%d packets received by filter\n",stat.ps_recv);
    					(void)fprintf(stderr, "%d packets dropped by kernel\n",stat.ps_drop);
    				}
    			}
            exit(0);
    }
    
    /* Like default_print() but data need not be aligned */
    void
    default_print_unaligned(register const u_char *cp, register u_int length)
    {
            register u_int i, s;
            register int nshorts;
    
            nshorts = (u_int) length / sizeof(u_short);
            i = 0;
            while (--nshorts >= 0) {
                    if ((i++ % 8) == 0)
                            (void)printf("\n\t\t\t");
                    s = *cp++;
                    (void)printf(" %02x%02x", s, *cp++);
            }
            if (length & 1) {
                    if ((i % 8) == 0)
                            (void)printf("\n\t\t\t");
                    (void)printf(" %02x", *cp);
            }
    }
    
    /*
     * By default, print the packet out in hex.
     */
    void
    default_print(register const u_char *bp, register u_int length)
    {
            register const u_short *sp;
            register u_int i;
            register int nshorts;
    
            if ((long)bp & 1) {
                    default_print_unaligned(bp, length);
                    return;
            }
            sp = (u_short *)bp;
            nshorts = (u_int) length / sizeof(u_short);
            i = 0;
            while (--nshorts >= 0) {
                    if ((i++ % 8) == 0)
                            (void)printf("\n\t");
                    (void)printf(" %04x", ntohs(*sp++));
            }
            if (length & 1) {
                    if ((i % 8) == 0)
                            (void)printf("\n\t");
                    (void)printf(" %02x", *(u_char *)sp);
            }
    }
    
    /*
    insert your code in this routine
    
    */
    
    void raw_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
    {
    	
    	
    	/* declare pointers to packet headers */
    	const struct sniff_ethernet *ethernet;  /* The ethernet header */
    	const struct sniff_arp *arp;			/* The arp packet */
    	const struct sniff_ip *ip;				/* The IP header */
    	char *payload;							/* Packet payload */
    	char data[1480];
    	int shoPayload = 0;	
    	
    	ethernet = (struct sniff_ethernet*)(p);
    	
    	//decode ethernet packet header
    	u_short type;
    	int i=0, bcst=1;
    	u_char test;
    	short bcast = "ff";
    	printf("Ethernet Header\n---------------------------\n");
    	printf("Src: %02x:%02x:%02x:%02x:%02x:%02x\n", ethernet->ether_shost[0],ethernet->ether_shost[1],ethernet->ether_shost[2],ethernet->ether_shost[3],ethernet->ether_shost[4],ethernet->ether_shost[5]);
    	printf("Dst: %02x:%02x:%02x:%02x:%02x:%02x\n", ethernet->ether_dhost[0],ethernet->ether_dhost[1],ethernet->ether_dhost[2],ethernet->ether_dhost[3],ethernet->ether_dhost[4],ethernet->ether_dhost[5]);
    	
    	
    	 while (i < 6) {
    		printf("%x:",(u_char *)ethernet->ether_dhost[i]);
    		if 	(bcast != ethernet->ether_dhost[i]) {
    			printf("%x:",ethernet->ether_dhost[i]);
    			bcst = 0;
    			//bcst ++;
    			//nBroadcast++;
    			//printf("Broadcast\n");
    		}
    		i++;
    	}
    	if (bcst == 1) {
    		nBroadcast++;
    		printf("Broadcast\n");
    	}
    		
    	type = ntohs(ethernet->ether_type);
    	printf("\nType: 0x%x \n", type);
    	
    	switch (type) {
    		case 0x806:
    			//decode ARP packet header
    			arp = (struct sniff_arp*)(p + SIZE_ETHERNET);
    			printf("Payload = ARP\n");
    			printf("\n\tARP Decode\n\t-------------------\n");
     			printf("\tHW type: %04x\n", arp->arp_hwtype);
    			printf("\tProto type: %04x\n", arp->arp_proto);
    			printf("\tHW Addr Len: %02x\n", arp->arp_addrlen);
    			printf("\tProto Len: %02x\n", arp->arp_protolen);
    			printf("\tSrc: %02x:%02x:%02x:%02x:%02x:%02x\n", arp->arp_src[0],arp->arp_src[1],arp->arp_src[2],arp->arp_src[3],arp->arp_src[4],arp->arp_src[5]);
    			printf("\tDst: %02x:%02x:%02x:%02x:%02x:%02x\n", arp->arp_dst[0],arp->arp_dst[1],arp->arp_dst[2],arp->arp_dst[3],arp->arp_dst[4],arp->arp_dst[5]);
    			//printf("\tSrc IP: %d.%d.%d.%d\n", arp->arp_src_proto_addr[0],arp->arp_src_proto_addr[1],arp->arp_src_proto_addr[2],arp->arp_src_proto_addr[3]);
    			//printf("\tDst IP: %d.%d.%d.%d\n", arp->arp_dst_proto_addr[0],arp->arp_dst_proto_addr[1],arp->arp_dst_proto_addr[2],arp->arp_dst_proto_addr[3]);
     			nARP++;
    			break;
    		case 0x800:
    			//decode IP packet header
    			ip = (struct sniff_ip*)(p + SIZE_ETHERNET);
    			printf("Payload = IP\n");
    			printf("\n\tIP Header\n\t-------------------\n");
    			printf("\tSrc: %d.%d.%d.%d\n", ip->ip_src[0],ip->ip_src[1],ip->ip_src[2],ip->ip_src[3]);
    			printf("\tDst: %d.%d.%d.%d\n", ip->ip_dst[0],ip->ip_dst[1],ip->ip_dst[2],ip->ip_dst[3]);
    			printf("\tIP Version: %x\n", (ip->ip_vhl) >> 4);
    			//printf("\tHeader Len: %x\n",(ip->ip_vhl) & 0x0F);
    			//printf("\tTOS: %x\n", ip->ip_tos);
    			printf("\tLength: %d\n", ntohs(ip->ip_len));
    			//printf("\tPacket ID: %d\n", ntohs(ip->ip_id));
    			//printf("\tOffset: %d\n", ntohs(ip->ip_off) & 0x1fff);
    			//printf("\tTTL: %d\n", ip->ip_ttl);
    			//printf("\tChecksum: %d\n", ntohs(ip->ip_sum));
    			nIP++;
    			break;
    			}
            u_int length = h->len;
            u_int caplen = h->caplen;
    		default_print(p, caplen);
            putchar('\n');
    }
    Any assistance is greatly appreciated as I'm banging my head against a wall at this point.

    Thanks
    Last edited by jww1232002; September 21st, 2012 at 08:20 PM. Reason: Added compile warning msg
  2. #2
  3. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244
    If you are on a 64 bit machine casting packets as structures is almost certainly going to fail (I have sometimes had problems on 32 bit machines as well). In principle you can declare the struct as 'packed' (details vary based on compiler) though I have occasionally found this is still problematic. The only guaranteed way I have found to access packet bits is to index into the packet buffer on a char basis, then cast that location into the relevant data type. There is essentially no performance penalty for doing so, it is strictly a compile-time issue; basically you are emulating what the compiler is supposed to do for you but sometimes screws up, particularly on 64 bit.

    Also, critical on little-endian machines (most x86-based machines), it is _very_ important to realise that packets are all big-endian and set up your bit masks appropriately.

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2012
    Posts
    2
    Rep Power
    0

    Thanks for the info


    mitakeet,
    Thanks for the information, I'll have to keep that in mind as I didn't even think about that.

    Thanks Again,
    JW

    Originally Posted by mitakeet
    If you are on a 64 bit machine casting packets as structures is almost certainly going to fail (I have sometimes had problems on 32 bit machines as well). In principle you can declare the struct as 'packed' (details vary based on compiler) though I have occasionally found this is still problematic. The only guaranteed way I have found to access packet bits is to index into the packet buffer on a char basis, then cast that location into the relevant data type. There is essentially no performance penalty for doing so, it is strictly a compile-time issue; basically you are emulating what the compiler is supposed to do for you but sometimes screws up, particularly on 64 bit.

    Also, critical on little-endian machines (most x86-based machines), it is _very_ important to realise that packets are all big-endian and set up your bit masks appropriately.

IMN logo majestic logo threadwatch logo seochat tools logo