// IP解包函数 int decode_ip(char *ipbuf, int protocol) { switch(protocol) { case IPPROTO_TCP: // TCP类型数据包 decode_tcp(ipbuf); break; case IPPROTO_UDP: // UDP类型数据包 decode_udp(ipbuf); break; case IPPROTO_ICMP: // ICMP类型数据包 decode_icmp(ipbuf); break; default: break; } return true; }
void decode_ip6(const u_char * packet) { char str_sip[INET6_ADDRSTRLEN]; char str_dip[INET6_ADDRSTRLEN]; char buffer[128]; char * yellow_plen, *yellow_nxt, *b_sip, *b_dip; const struct ip6_hdr * ip_t; ip_t = (struct ip6_hdr *)(packet); inet_ntop(AF_INET6, &(ip_t->ip6_src), str_sip, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &(ip_t->ip6_dst), str_dip, INET6_ADDRSTRLEN); b_sip = bold(str_sip); b_dip = bold(str_dip); sprintf(buffer, "%d", htons(ip_t->ip6_ctlun.ip6_un1.ip6_un1_plen)); yellow_plen = yellow(buffer); sprintf(buffer, "%x", ip_t->ip6_ctlun.ip6_un1.ip6_un1_plen); yellow_nxt = yellow(buffer); V(1, "IPv6 - %s --> %s\n", b_sip, b_dip); uint32_t flow = htonl(ip_t->ip6_ctlun.ip6_un1.ip6_un1_flow); VV(1, "Payload Length : %s - Next Header : %s\n", yellow_plen, yellow_nxt); /* htons(ip_t->ip6_ctlun.ip6_un1.ip6_un1_plen), ip_t->ip6_ctlun.ip6_un1.ip6_un1_nxt); */ VVV(1,"Version : %d - Traffic Class : %x - Flow Label : %x - Hop Limit : %d\n", flow >> 28, (flow & 0x0ff00000) >> 20, flow & 0x000fffff, ip_t->ip6_ctlun.ip6_un1.ip6_un1_hlim); int offset = sizeof(struct ip6_hdr); switch(ip_t->ip6_ctlun.ip6_un1.ip6_un1_nxt) { case 0x06: decode_tcp(packet + offset); break; case 0x11: decode_udp(packet + offset); break; } free(yellow_plen); free(yellow_nxt); free(b_sip); free(b_dip); }
/* main processing function */ void proc_packet(const u_char *data, u_int size) { struct ip_stat istat; u_int data_offs; u_int tcp_hdr_sz; u_int udp_hdr_sz; /* print captured bytes */ printf("\n\nBytes Captured = [ %d ]\n", size); /* print L2 information */ decode_ethernet(data); /* obtain IP protocol number for further decoding */ decode_ip(data + ETHER_HDR_LEN, &istat); switch(istat.ip_prot) { case 1: decode_icmp(data + ETHER_HDR_LEN + istat.ip_len); data_offs = ETHER_HDR_LEN + istat.ip_len; break; case 6: tcp_hdr_sz = decode_tcp(data + ETHER_HDR_LEN + istat.ip_len); data_offs = ETHER_HDR_LEN + istat.ip_len + tcp_hdr_sz; break; case 17: udp_hdr_sz = decode_udp(data + ETHER_HDR_LEN + istat.ip_len); data_offs = ETHER_HDR_LEN + istat.ip_len + udp_hdr_sz; break; default: break; } /* print raw encapsulated data */ praw(data + data_offs, size); }
static void decode_ip (const uint8_t *packet, size_t pk_len, int pk_layer) { union { const struct myiphdr *i; const uint8_t *d; } i_u; uint16_t fragoff=0, totlen=0, ipid=0, chksum=0, c_chksum=0; uint32_t saddr=0, daddr=0; size_t opt_len=0; int bad_cksum=0; i_u.d=packet; r_u.i.flags=0; if (pk_len < sizeof(struct myiphdr)) { ERR("short ip packet"); return; } if (i_u.i->ihl < 5) { ERR("ihl is less than 5, this packet is likely confused/damaged"); return; } ipid=ntohs(i_u.i->id); fragoff=ntohs(i_u.i->frag_off); totlen=ntohs(i_u.i->tot_len); chksum=ntohs(i_u.i->check); /* XXX everything expects addresses in network order */ saddr=i_u.i->saddr; daddr=i_u.i->daddr; /* precalculated ip-pseudo header for transport layer checksumming */ ipph.saddr=saddr; ipph.daddr=daddr; ipph.zero=0; ipph.proto=i_u.i->protocol; ipph.len=0; opt_len=(i_u.i->ihl - (sizeof(struct myiphdr) / 4)) * 4; if (fragoff & IP_OFFMASK) { ERR("likely bad: (is DF set? perhaps we need it) ignoring fragmented packet"); return; } if (totlen > pk_len && pk_layer == 1) { /* this packet has an incorrect ip packet length, stop processing */ ERR("likely bad: packet has incorrect ip length, skipping it [ip total length claims %u and we have " STFMT, totlen, pk_len); return; } else if (pk_layer == 3 && totlen > pk_len) { totlen=pk_len; } if (pk_len > totlen) { /* * there is trailing junk past the end of the ip packet, save a pointer to it, * and its length, then update pk_len */ DBG(M_PKT, "packet has trailing junk, saving a pointer to it and its length " STFMT, pk_len - totlen); trailgarbage=packet + totlen; trailgarbage_len=pk_len - totlen; pk_len=totlen; } if ((opt_len + sizeof(struct myiphdr)) > pk_len) { DBG(M_PKT, "IP options seem to overlap the packet size, truncating and assuming no ip options"); opt_len=0; /* must be a trick, assume no options then, in case this is a damaged ip header is under a icmp reply */ } if ((c_chksum=do_ipchksum(packet, opt_len + sizeof(struct myiphdr))) != 0) { DBG(M_PKT, "bad cksum, ipchksum returned %u", c_chksum); bad_cksum=1; } if (ISDBG(M_PKT) || GET_SNIFF()) { char frag_flags[32]; char src_addr[32], dst_addr[32]; struct in_addr ia; ia.s_addr=saddr; sprintf(src_addr, "%s", inet_ntoa(ia)); ia.s_addr=daddr; sprintf(dst_addr, "%s", inet_ntoa(ia)); CLEAR(frag_flags); if (fragoff & IP_DF) { strcat(frag_flags, "DF "); } if (fragoff & IP_MF) { strcat(frag_flags, "MF "); } if (fragoff & IP_RF) { strcat(frag_flags, "RF "); } INF("IP : ihl %u (opt len " STFMT ") size " STFMT " version %u tos 0x%02x tot_len %u ipid %u frag_off %04x %s", i_u.i->ihl, opt_len, pk_len, i_u.i->version, i_u.i->tos, totlen, ipid, fragoff & IP_OFFMASK, frag_flags); INF("IP : ttl %u protocol `%s' chksum 0x%04x%s IP SRC %s IP DST %s", i_u.i->ttl, str_ipproto(i_u.i->protocol), chksum, (bad_cksum == 1 ? " [bad cksum]" : " [cksum ok]"), src_addr, dst_addr); } if (pk_layer == 1) { r_u.i.proto=i_u.i->protocol; r_u.i.host_addr=saddr; r_u.i.trace_addr=saddr; r_u.i.send_addr=daddr; r_u.i.ttl=i_u.i->ttl; if (bad_cksum) { r_u.i.flags |= REPORT_BADNETWORK_CKSUM; } } else if (pk_layer == 3) { /* this is a ip header within an icmp header normally */ /* * this was the _original host_ we sent to according * to the icmp error reflection */ r_u.i.host_addr=daddr; } else { ERR("decode IP at unknown layer %d", pk_layer); return; } if (opt_len > 0) { decode_ipopts(packet + sizeof(struct myiphdr), opt_len); } pk_len -= sizeof(struct myiphdr) + opt_len; packet += sizeof(struct myiphdr) + opt_len; if (pk_len) { switch (i_u.i->protocol) { case IPPROTO_TCP: decode_tcp(packet, pk_len, ++pk_layer); break; case IPPROTO_UDP: decode_udp(packet, pk_len, ++pk_layer); break; case IPPROTO_ICMP: decode_icmp(packet, pk_len, ++pk_layer); break; default: ERR("filter is broken?"); break; } } return; }