static uint8_t * tcpeek_disassemble_ip(const uint8_t *packet, uint16_t plen, int datalink, struct tcpeek_segment_ip *dst) { struct ip *ip; uint16_t hlen, sum; ip = (struct ip *)tcpeek_disassemble_datalink(packet, plen, datalink, &dst->datalink); if(!ip) { return NULL; } plen -= (caddr_t)ip - (caddr_t)packet; if(plen < sizeof(struct ip)) { return NULL; } hlen = ip->ip_hl << 2; if(plen < hlen || plen < ntohs(ip->ip_len)) { return NULL; } if(g.option.checksum & TCPEEK_CKSUM_IP) { sum = cksum16((uint16_t *)ip, hlen, 0); if(sum != 0) { lprintf(LOG_WARNING, "%s [warning] IP checksum error. %04X (%04X)", __func__, sum, ip->ip_sum); return NULL; } } if(ip->ip_p != IPPROTO_TCP && (g.option.icmp ? ip->ip_p != IPPROTO_ICMP : 1)) { return NULL; } memcpy(&dst->hdr, ip, sizeof(struct ip)); return (uint8_t *)((caddr_t)ip + hlen); }
void IPv4Checksum::update_(Packet *pkt) const { char buffer[60]; PHV *phv = pkt->get_phv(); Header &ipv4_hdr = phv->get_header(header_id); if (!ipv4_hdr.is_valid()) return; Field &ipv4_cksum = ipv4_hdr[field_offset]; ipv4_hdr.deparse(buffer); buffer[IPV4_CKSUM_OFFSET] = 0; buffer[IPV4_CKSUM_OFFSET + 1] = 0; uint16_t cksum = cksum16(buffer, ipv4_hdr.get_nbytes_packet()); // cksum is in network byte order ipv4_cksum.set_bytes(reinterpret_cast<char *>(&cksum), 2); }
bool IPv4Checksum::verify_(const Packet &pkt) const { char buffer[60]; const PHV &phv = *(pkt.get_phv()); const Header &ipv4_hdr = phv.get_header(header_id); if (!ipv4_hdr.is_valid()) return true; // return true if no header... TODO ? const Field &ipv4_cksum = ipv4_hdr[field_offset]; ipv4_hdr.deparse(buffer); buffer[IPV4_CKSUM_OFFSET] = 0; buffer[IPV4_CKSUM_OFFSET + 1] = 0; uint16_t cksum = cksum16(buffer, ipv4_hdr.get_nbytes_packet()); // TODO(antonin): improve this? return !memcmp(reinterpret_cast<char *>(&cksum), ipv4_cksum.get_bytes().data(), 2); }
static uint8_t * tcpeek_disassemble_tcp(const uint8_t *packet, uint16_t plen, int datalink, struct tcpeek_segment_tcp *dst) { uint8_t *payload; struct tcphdr *tcphdr; uint16_t hlen, tcplen, sum; struct ip *ip; uint32_t pseudo = 0; payload = tcpeek_disassemble_ip(packet, plen, datalink, &dst->ip); if(!payload) { return NULL; } if(dst->ip.hdr.ip_p == IPPROTO_ICMP) { return payload; } tcphdr = (struct tcphdr *)payload; if(!tcphdr) { return NULL; } plen -= (caddr_t)tcphdr - (caddr_t)packet; if(plen < sizeof(struct tcphdr)) { return NULL; } hlen = tcphdr->th_off << 2; if(plen < hlen) { return NULL; } ip = &dst->ip.hdr; tcplen = ntohs(ip->ip_len) - (ip->ip_hl << 2); if(g.option.checksum & TCPEEK_CKSUM_TCP) { pseudo += ip->ip_src.s_addr >> 16; pseudo += ip->ip_src.s_addr & 0xffff; pseudo += ip->ip_dst.s_addr >> 16; pseudo += ip->ip_dst.s_addr & 0xffff; pseudo += htons(IPPROTO_TCP); pseudo += htons(tcplen); sum = cksum16((uint16_t *)tcphdr, tcplen, pseudo); if(sum != 0) { lprintf(LOG_WARNING, "%s [warning] TCP checksum error. %04X (%04X)", __func__, sum, tcphdr->th_sum); return NULL; } }