static const uint8_t* Encode_Packet( EncState* enc, const Packet* p, uint32_t* len) { Buffer ibuf, obuf; ENC_STATUS status = ENC_BAD_PROTO; PROTO_ID next; ibuf.base = (uint8_t*)p->pkt; ibuf.off = ibuf.end = 0; ibuf.size = p->pkth->caplen; obuf.base = s_pkt; obuf.off = obuf.end = 0; obuf.size = sizeof(s_pkt); enc->layer = 0; enc->p = p; next = NextEncoder(enc); if ( next < PROTO_MAX ) { Encoder e = encoders[next].fencode; status = (*e)(enc, &ibuf, &obuf); } if ( status != ENC_OK || enc->layer != p->next_layer ) { *len = 0; return NULL; } *len = (uint32_t)obuf.end; return obuf.base + obuf.off; }
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)); /* IPv4 encoded header is hardcoded 20 bytes */ 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) ) { ho->ip_src.s_addr = hi->ip_src.s_addr; ho->ip_dst.s_addr = hi->ip_dst.s_addr; ho->ip_ttl = FwdTTL(enc, hi->ip_ttl); } else { ho->ip_src.s_addr = hi->ip_dst.s_addr; ho->ip_dst.s_addr = hi->ip_src.s_addr; ho->ip_ttl = RevTTL(enc, hi->ip_ttl); } enc->ip_hdr = (uint8_t*)hi; enc->ip_len = IP_HLEN(hi) << 2; if ( next < PROTO_MAX ) { ENC_STATUS err = encoders[next].fencode(enc, in, out); if ( ENC_OK != err ) return err; } if ( enc->proto ) { ho->ip_proto = enc->proto; enc->proto = 0; } len = out->end - start; ho->ip_len = htons((uint16_t)len); ho->ip_csum = 0; /* IPv4 encoded header is hardcoded 20 bytes, we save some * cycles and use the literal header size for checksum */ ho->ip_csum = in_chksum_ip((const uint16_t *)ho, sizeof *ho); return ENC_OK; }
static ENC_STATUS Eth_Encode (EncState* enc, Buffer* in, Buffer* out) { // not raw ip -> encode layer 2 int raw = ( enc->flags & ENC_FLAG_RAW ); EtherHdr* hi = (EtherHdr*)enc->p->layers[enc->layer-1].start; PROTO_ID next = NextEncoder(enc); // if not raw ip AND out buf is empty if ( !raw && (out->off == out->end) ) { // for alignment out->off = out->end = SPARC_TWIDDLE; } // if not raw ip OR out buf is not empty if ( !raw || (out->off != out->end) ) { // we get here for outer-most layer when not raw ip // we also get here for any encapsulated ethernet layer. EtherHdr* ho = (EtherHdr*)(out->base + out->end); UPDATE_BOUND(out, sizeof(*ho)); ho->ether_type = hi->ether_type; if ( FORWARD(enc) ) { memcpy(ho->ether_src, hi->ether_src, sizeof(ho->ether_src)); /*If user configured remote MAC address, use it*/ if (NULL != dst_mac) memcpy(ho->ether_dst, dst_mac, sizeof(ho->ether_dst)); else memcpy(ho->ether_dst, hi->ether_dst, sizeof(ho->ether_dst)); } else { memcpy(ho->ether_src, hi->ether_dst, sizeof(ho->ether_src)); /*If user configured remote MAC address, use it*/ if (NULL != dst_mac) memcpy(ho->ether_dst, dst_mac, sizeof(ho->ether_dst)); else memcpy(ho->ether_dst, hi->ether_src, sizeof(ho->ether_dst)); } } if ( next < PROTO_MAX ) return encoders[next].fencode(enc, in, out); return ENC_OK; }
static ENC_STATUS FPath_Encode (EncState* enc, Buffer* in, Buffer* out) { // not raw ip -> encode layer 2 int raw = ( enc->flags & ENC_FLAG_RAW ); FPathHdr* hi = (FPathHdr*)enc->p->layers[enc->layer-1].start; PROTO_ID next = NextEncoder(enc); // if not raw ip AND out buf is empty if ( !raw && (out->off == out->end) ) { // for alignment out->off = out->end = 0; } // if not raw ip OR out buf is not empty if ( !raw || (out->off != out->end) ) { // we get here for outer-most layer when not raw ip // we also get here for any encapsulated ethernet layer. FPathHdr* ho = (FPathHdr*)(out->base + out->end); UPDATE_BOUND(out, sizeof(*ho)); ho->fpath_type = hi->fpath_type; if ( FORWARD(enc) ) { memcpy(ho->fpath_src, hi->fpath_src, sizeof(ho->fpath_src)); memcpy(ho->fpath_dst, hi->fpath_dst, sizeof(ho->fpath_dst)); } else { memcpy(ho->fpath_src, hi->fpath_dst, sizeof(ho->fpath_src)); memcpy(ho->fpath_dst, hi->fpath_src, sizeof(ho->fpath_dst)); } } if ( next < PROTO_MAX ) return encoders[next].fencode(enc, in, out); return ENC_OK; }
static ENC_STATUS Eth_Encode (EncState* enc, Buffer* in, Buffer* out) { int outer = 0; int raw = enc->flags & ENC_FLAG_RAW; EtherHdr* hi = (EtherHdr*)enc->p->layers[enc->layer-1].start; PROTO_ID next = NextEncoder(enc); if ( raw && (out->off == out->end) ) { // for alignment out->off = out->end = SPARC_TWIDDLE; outer = 1; // encoding outermost eth } if ( raw || !outer ) { // we get here for outer-most layer when raw is true; // we also get here for any encapsulated ethernet layer. EtherHdr* ho = (EtherHdr*)(out->base + out->end); UPDATE_BOUND(out, sizeof(*ho)); if ( FORWARD(enc) ) { memcpy(ho, hi, sizeof(*ho)); } else { ho->ether_type = hi->ether_type; memcpy(ho->ether_src, hi->ether_dst, sizeof(ho->ether_src)); memcpy(ho->ether_dst, hi->ether_src, sizeof(ho->ether_dst)); } } if ( next < PROTO_MAX ) return encoders[next].fencode(enc, in, out); 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; }