static ENC_STATUS IP4_Update (Packet* p, Layer* lyr, uint32_t* len) { IPHdr* h = (IPHdr*)(lyr->start); int i = lyr - p->layers; *len += GET_IP_HDR_LEN(h); if ( i + 1 == p->next_layer ) { *len += p->dsize; } h->ip_len = htons((uint16_t)*len); if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) ) { h->ip_csum = 0; h->ip_csum = in_chksum_ip((const uint16_t *)h, GET_IP_HDR_LEN(h)); } return ENC_OK; }
static ENC_STATUS IP4_Encode (EncState* enc, Buffer* in, Buffer* out) { int len; uint32_t start = out->end; IPHdr* hi = (IPHdr*)enc->p->layers[enc->layer-1].start; IPHdr* ho = (IPHdr*)(out->base + out->end); PROTO_ID next = NextEncoder(enc); UPDATE_BOUND(out, sizeof(*ho)); len = GET_IP_HDR_LEN(hi) - sizeof(*hi); ho->ip_verhl = 0x45; ho->ip_off = 0; ho->ip_id = IpId_Next(); ho->ip_tos = hi->ip_tos; ho->ip_proto = hi->ip_proto; if ( FORWARD(enc) ) { uint8_t ttl = AdjTTL(hi->ip_ttl); ho->ip_src.s_addr = hi->ip_src.s_addr; ho->ip_dst.s_addr = hi->ip_dst.s_addr; if ( enc->p->ssnptr ) ttl = GetTTL(enc); #ifdef NORMALIZER if ( ttl < ScMinTTL() && ScNewTTL() ) ttl = ScNewTTL(); #endif ho->ip_ttl = ttl; } else { uint8_t ttl = MAX_TTL; ho->ip_src.s_addr = hi->ip_dst.s_addr; ho->ip_dst.s_addr = hi->ip_src.s_addr; if ( enc->p->ssnptr ) ttl = GetTTL(enc); #ifdef NORMALIZER if ( ttl < ScMinTTL() && ScNewTTL() ) ttl = ScNewTTL(); #endif ho->ip_ttl = ttl; } enc->ip_hdr = (uint8_t*)hi; enc->ip_len = IP_HLEN(hi) << 2; if ( next < PROTO_MAX ) { int err = encoders[next].fencode(enc, in, out); if ( err ) return err; } if ( enc->proto ) { ho->ip_proto = enc->proto; enc->proto = 0; } len = out->end - start; ho->ip_len = htons((u_int16_t)len); ip_checksum(ho, len); return ENC_OK; }