#include #include #include #include #include #include #include #include #include #include #include "tcpview.h" #include "addrtoname.h" #ifdef __STDC__ static void ip_printroute(u_char *, int); static void ip_optprint(u_char *, int); static void do_addr(int, int, u_char *); #else static void ip_printroute(); static void ip_optprint(); static void do_addr(); #endif char *Precedence[] = { "", "Priority", "Immediate", "Flash", "Flash Override", "CRITIC/ECP", "Internetwork Control", "Network Control" }; extern char D_Src_Host[64], D_Dst_Host[64], D_Proto[8]; extern u_short D_Src_Port, D_Dst_Port; void detail_ip(ip) register struct ip *ip; { u_short hlen; register unsigned char *cp; u_short off, id, len; char buf[64]; #ifdef TCPDUMP_ALIGN static u_char *abuf=NULL; /* * The IP header is not word aligned, so copy into abuf. * This will never happen with BPF. It does happen raw packet * dumps from -r. */ if ((int)ip & (sizeof(long)-1)) { if (abuf == NULL) abuf = (u_char *)malloc(MAX_SNAPLEN); bcopy((char *)ip, (char *)abuf, Phdr->caplen-Offset); ip = (struct ip *)abuf; } #endif len = Phdr->caplen - Offset; if (len < sizeof (struct ip)) { printf("***** IP (truncated) *****"); hex(0,Phdr->caplen - Offset - 1); return; } hlen = ip->ip_hl * 4; /* header length */ off = ntohs(ip->ip_off); /* fragment offset */ id = ntohs(ip->ip_id); len = ntohs(ip->ip_len) - hlen; /* total size of datagram minus header */ printf("----- IP Header -----\n\n"); hex( 0, hlen - 1 ); /* header */ hex( -1, -1 ); /* blank line */ printf("Version = %d, header length = %d\n",ip->ip_v,hlen); hex( 0, 0 ); /* Version and Header Length */ if( ip->ip_tos ) { u_char prec = (ip->ip_tos & 0xe0)>>5; strcpy(buf,Precedence[prec]); if( ip->ip_tos & 0x10) { if( *buf ) strcat(buf,", "); strcat(buf,"Low Delay"); } if( ip->ip_tos & 0x08) { if( *buf ) strcat(buf,", "); strcat(buf,"High Throughput"); } if( ip->ip_tos & 0x04) { if( *buf ) strcat(buf,", "); strcat(buf,"High Relibility"); } printf("Type of service = 0x%02x ( %s )\n",ip->ip_tos,buf); } else printf("Type of service = 0\n"); printf("Total length = %d bytes\n",ntohs(ip->ip_len)); printf("Identification = %d\n",id); hex( 1, 1 ); /* TOS */ hex( 2, 3 ); /* Total Length */ hex( 4, 5 ); /* ID */ buf[0]='\0'; if( off & IP_DF) strcat(buf,"Don't Fragment "); if( off & IP_MF) strcat(buf,"More Fragments"); printf("Flags = 0x%02x ( %s )\n",(off&(IP_MF|IP_DF))>>13,buf); hex( 6, 6 ); /* Flags */ printf("Fragment offset = %d bytes\n",off&0x1fff); hex( 6, 7 ); /* Fragment offset */ printf("Time to live = %d hops or seconds\n",ip->ip_ttl); hex( 8, 8 ); /* TTL */ strcpy(D_Proto,ipproto_string(ip->ip_p)); printf("Protocol = %d ( %s )\n",ip->ip_p,D_Proto); hex( 9, 9 ); /* protocol */ printf("Header checksum = 0x%x\n",ntohs(ip->ip_sum)); hex( 10, 11 ); /* header checksum */ strcpy(D_Src_Host,ipaddr_str(&ip->ip_src,ADDR_NUMERICAL)); printf("Source address = [%s], %s\n", D_Src_Host,ipaddr_str(&ip->ip_src,ADDR_DOMAIN)); strcpy(D_Dst_Host,ipaddr_str(&ip->ip_dst,ADDR_NUMERICAL)); printf("Destination address = [%s], %s\n", D_Dst_Host,ipaddr_str(&ip->ip_dst,ADDR_DOMAIN)); hex( 12, 15 ); /* source */ hex( 16, 19 ); /* destination */ if( hlen > sizeof(struct ip) ) { /* must be options here */ u_short old_offset = Offset; printf("IP OPTIONS\n"); hex(20,hlen-1); Offset += sizeof(struct ip); ip_optprint((u_char *)(ip+1),hlen-sizeof(struct ip)); Offset = old_offset; } /* if this is a fragment, there is no higher layer so just return now */ if( off & 0x1fff ) return; putchar('\n'); hex( -1, -1 ); /* blank line */ cp = (unsigned char *)ip + hlen; /* pointer to next protocol header */ Offset += hlen; switch (ip->ip_p) { case IPPROTO_TCP: detail_tcp((struct tcphdr *)cp, len); break; case IPPROTO_UDP: detail_udp((struct udphdr *)cp, len); break; /*** case IPPROTO_EGP: detail_egp((u_char *)cp); break; ***/ case IPPROTO_ICMP: detail_icmp((struct icmp *)cp, len); break; default: break; } } /* * print IP options. */ static void ip_optprint(cp, length) u_char *cp; int length; { u_short len; for (; length > 0; cp += len, length -= len) { u_char tt = *cp; len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1]; /* check to see if there is space for code, len, and all data */ if( Phdr->caplen - Offset - 2 < len ) { printf("*** truncated ***"); hex(0,Phdr->caplen-Offset-1); return; } switch (tt) { case IPOPT_EOL: printf(" End Of List\n"); hex(0,0); if (length > 1) { printf(" %d bytes remaining", length - 1); hex(-1,-1); } return; case IPOPT_NOP: printf(" NOP\n"); hex(0,0); Offset++; break; case IPOPT_TS: printf(" Timestamp\n"); hex(0,len+1); Offset += len+2; break; case IPOPT_SECURITY: printf(" Security{%d}\n", len); hex(0,len+1); Offset += len+2; break; case IPOPT_RR: printf(" Record Route\n"); hex(0,len); ip_printroute(cp, len); Offset += len; break; case IPOPT_SSRR: printf(" Strict Source Route\n"); hex(0,len); ip_printroute(cp, len); Offset += len; break; case IPOPT_LSRR: printf(" Loose Source Route\n"); hex(0,len); ip_printroute(cp, len); Offset += len; break; default: printf(" Unknown IP option %d\n", cp[0]); hex(0,len); Offset += len; break; } } } /* * print the recorded route in an IP RR, LSRR or SSRR option. */ static void ip_printroute(cp, length) u_char *cp; int length; { int ptr = cp[2] - 1; int len; if ((length + 1) & 3) printf(" [bad length %d]\n", length); else printf(" length %d\n",length); hex(1,1); if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) printf(" [bad ptr %d]\n", cp[2]); else printf(" ptr %d\n",cp[2]); hex(2,2); for (len = 3; len < length; len += 4) { #ifdef TCPDUMP_ALIGN { struct in_addr addr; bcopy((char *)&cp[len], (char *)&addr, sizeof(addr)); do_addr(ptr,len,(u_char *)&addr); } #else do_addr(ptr,len,&cp[len]); #endif hex(len,len+3); } } static void do_addr( ptr, len, addr) int ptr,len; u_char *addr; { char *str1, *str2; if( len >= ptr ) printf(" # %s\n",ipaddr_str(addr,ADDR_NUMERICAL)); else { str1 = ipaddr_str(addr,ADDR_NUMERICAL); str2 = ipaddr_str(addr,0); if( strcmp(str1,str2) ) printf(" %s [%s]\n", str2, str1); else printf(" %s\n",str2); } }