/** * @brief Parse a network packet * * @param[out] packet The parsed packet * @param data The data to parse * @param trace_cb The function to call for printing traces * @param trace_cb_priv An optional private context, may be NULL * @param trace_entity The entity that emits the traces * @return true if the packet was successfully parsed, * false if a problem occurred (a malformed packet is * not considered as an error) */ bool net_pkt_parse(struct net_pkt *const packet, const struct rohc_buf data, rohc_trace_callback2_t trace_cb, void *const trace_cb_priv, rohc_trace_entity_t trace_entity) { packet->data = rohc_buf_data(data); packet->len = data.len; packet->ip_hdr_nr = 0; packet->key = 0; /* traces */ packet->trace_callback = trace_cb; packet->trace_callback_priv = trace_cb_priv; /* create the outer IP packet from raw data */ if(!ip_create(&packet->outer_ip, rohc_buf_data(data), data.len)) { rohc_warning(packet, trace_entity, ROHC_PROFILE_GENERAL, "cannot create the outer IP header"); goto error; } packet->ip_hdr_nr++; rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "outer IP header: %u bytes", ip_get_totlen(&packet->outer_ip)); rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "outer IP header: version %d", ip_get_version(&packet->outer_ip)); if(packet->outer_ip.nh.data != NULL) { rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "outer IP header: next header is of type %d", packet->outer_ip.nh.proto); if(packet->outer_ip.nl.data != NULL) { rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "outer IP header: next layer is of type %d", packet->outer_ip.nl.proto); } } /* build the hash key for the packet */ if(ip_get_version(&packet->outer_ip) == IPV4) { packet->key ^= ipv4_get_saddr(&packet->outer_ip); packet->key ^= ipv4_get_daddr(&packet->outer_ip); } else if(ip_get_version(&packet->outer_ip) == IPV6) { const struct ipv6_addr *const saddr = ipv6_get_saddr(&packet->outer_ip); const struct ipv6_addr *const daddr = ipv6_get_daddr(&packet->outer_ip); packet->key ^= saddr->addr.u32[0]; packet->key ^= saddr->addr.u32[1]; packet->key ^= saddr->addr.u32[2]; packet->key ^= saddr->addr.u32[3]; packet->key ^= daddr->addr.u32[0]; packet->key ^= daddr->addr.u32[1]; packet->key ^= daddr->addr.u32[2]; packet->key ^= daddr->addr.u32[3]; } /* get the transport protocol */ packet->transport = &packet->outer_ip.nl; /* is there any inner IP header? */ if(rohc_is_tunneling(packet->transport->proto)) { /* create the second IP header */ if(!ip_get_inner_packet(&packet->outer_ip, &packet->inner_ip)) { rohc_warning(packet, trace_entity, ROHC_PROFILE_GENERAL, "cannot create the inner IP header"); goto error; } packet->ip_hdr_nr++; rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "inner IP header: %u bytes", ip_get_totlen(&packet->inner_ip)); rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "inner IP header: version %d", ip_get_version(&packet->inner_ip)); if(packet->inner_ip.nh.data != NULL) { rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "inner IP header: next header is of type %d", packet->inner_ip.nh.proto); if(packet->inner_ip.nl.data != NULL) { rohc_debug(packet, trace_entity, ROHC_PROFILE_GENERAL, "inner IP header: next layer is of type %d", packet->inner_ip.nl.proto); } } /* get the transport protocol */ packet->transport = &packet->inner_ip.nl; } return true; error: return false; }
/** * @brief Parse the static chain of the IR packet * * @param context The decompression context * @param rohc_packet The remaining part of the ROHC packet * @param rohc_length The remaining length (in bytes) of the ROHC packet * @param[out] bits The bits extracted from the static chain * @param[out] parsed_len The length (in bytes) of static chain in case of success * @return true in the static chain was successfully parsed, * false if the ROHC packet was malformed */ bool tcp_parse_static_chain(const struct rohc_decomp_ctxt *const context, const uint8_t *const rohc_packet, const size_t rohc_length, struct rohc_tcp_extr_bits *const bits, size_t *const parsed_len) { const uint8_t *remain_data = rohc_packet; size_t remain_len = rohc_length; size_t ip_hdrs_nr; uint8_t protocol; int ret; (*parsed_len) = 0; /* parse static IP part (IPv4/IPv6 headers and extension headers) */ ip_hdrs_nr = 0; do { struct rohc_tcp_extr_ip_bits *const ip_bits = &(bits->ip[ip_hdrs_nr]); ret = tcp_parse_static_ip(context, remain_data, remain_len, ip_bits, &protocol); if(ret < 0) { rohc_decomp_warn(context, "malformed ROHC packet: malformed IP " "static part"); goto error; } rohc_decomp_debug(context, "IPv%u static part is %d-byte length", ip_bits->version, ret); assert(remain_len >= ((size_t) ret)); remain_data += ret; remain_len -= ret; (*parsed_len) += ret; ip_hdrs_nr++; } while(rohc_is_tunneling(protocol) && ip_hdrs_nr < ROHC_TCP_MAX_IP_HDRS); if(rohc_is_tunneling(protocol) && ip_hdrs_nr >= ROHC_TCP_MAX_IP_HDRS) { rohc_decomp_warn(context, "too many IP headers to decompress"); goto error; } bits->ip_nr = ip_hdrs_nr; /* parse TCP static part */ ret = tcp_parse_static_tcp(context, remain_data, remain_len, bits); if(ret < 0) { rohc_decomp_warn(context, "malformed ROHC packet: malformed TCP static " "part"); goto error; } rohc_decomp_debug(context, "TCP static part is %d-byte length", ret); assert(remain_len >= ((size_t) ret)); #ifndef __clang_analyzer__ /* silent warning about dead in/decrement */ remain_data += ret; remain_len -= ret; #endif (*parsed_len) += ret; return true; error: return false; }