25 #define advance_pkt(pkt, len, sz) do { \
36 return (_nmsg_ipdg_parse_reasm(dg, etype, len, pkt,
37 NULL, NULL, NULL, NULL, 0));
42 struct pcap_pkthdr *pkt_hdr,
const u_char *pkt)
45 size_t len = pkt_hdr->caplen;
51 if (pkt_hdr->caplen != pkt_hdr->len)
55 switch (pcap->datalink) {
59 if (len <
sizeof(*eth))
64 load_net16(ð->ether_type, &etype);
65 if (etype == ETHERTYPE_VLAN) {
68 advance_pkt(pkt, len, 2);
69 load_net16(pkt, &etype);
70 advance_pkt(pkt, len, 2);
77 if (len <
sizeof(*ip))
83 }
else if (ip->ip_v == 6) {
84 etype = ETHERTYPE_IPV6;
94 advance_pkt(pkt, len, ETHER_HDR_LEN);
95 load_net16(pkt, &etype);
96 advance_pkt(pkt, len, 2);
102 res = _nmsg_ipdg_parse_reasm(dg, etype, len, pkt, pcap->reasm,
103 &new_len, pcap->new_pkt, &defrag,
107 struct bpf_insn *fcode = pcap->userbpf.bf_insns;
120 _nmsg_ipdg_parse_reasm(
struct nmsg_ipdg *dg,
unsigned etype,
size_t len,
121 const u_char *pkt,
struct _nmsg_ipreasm *reasm,
122 unsigned *new_len, u_char *new_pkt,
int *defrag,
125 bool is_fragment =
false;
126 unsigned frag_hdr_offset = 0;
127 unsigned tp_payload_len = 0;
139 advance_pkt(pkt, len, ip->ip_hl << 2);
141 load_net16(&ip->ip_off, &ip_off);
142 if ((ip_off & IP_OFFMASK) != 0 ||
143 (ip_off & IP_MF) != 0)
151 case ETHERTYPE_IPV6: {
152 const struct ip6_hdr *ip6;
153 uint16_t payload_len;
157 if (len <
sizeof(*ip6))
159 ip6 = (
const struct ip6_hdr *) dg->
network;
160 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION)
163 nexthdr = ip6->ip6_nxt;
164 thusfar =
sizeof(
struct ip6_hdr);
165 load_net16(&ip6->ip6_plen, &payload_len);
167 while (nexthdr == IPPROTO_ROUTING ||
168 nexthdr == IPPROTO_HOPOPTS ||
169 nexthdr == IPPROTO_FRAGMENT ||
170 nexthdr == IPPROTO_DSTOPTS ||
171 nexthdr == IPPROTO_AH ||
172 nexthdr == IPPROTO_ESP)
178 uint16_t ext_hdr_len;
181 if ((thusfar +
sizeof(ext_hdr)) > len)
184 if (nexthdr == IPPROTO_FRAGMENT) {
185 frag_hdr_offset = thusfar;
190 memcpy(&ext_hdr, (
const u_char *) ip6 + thusfar,
192 nexthdr = ext_hdr.nexthdr;
193 ext_hdr_len = (8 * (ntohs(ext_hdr.length) + 1));
195 if (ext_hdr_len > payload_len)
198 thusfar += ext_hdr_len;
199 payload_len -= ext_hdr_len;
202 if ((thusfar + payload_len) > len || payload_len == 0)
205 advance_pkt(pkt, len, thusfar);
217 if (is_fragment ==
true && reasm != NULL) {
221 frag_hdr_offset, timestamp,
223 if (rres ==
false || *new_len == 0) {
232 if (is_fragment ==
true && reasm == NULL)
246 load_net16(&udp->uh_ulen, &tp_payload_len);
247 if (tp_payload_len >= 8)
268 bool is_initial_fragment =
false;
269 bool is_fragment =
false;
271 unsigned tp_payload_len = 0;
278 if (len <
sizeof(*eth))
283 load_net16(ð->ether_type, &etype);
284 if (etype == ETHERTYPE_VLAN) {
287 advance_pkt(pkt, len, 2);
288 load_net16(pkt, &etype);
289 advance_pkt(pkt, len, 2);
296 if (len <
sizeof(*ip))
301 etype = ETHERTYPE_IP;
302 }
else if (ip->ip_v == 6) {
303 etype = ETHERTYPE_IPV6;
310 case DLT_LINUX_SLL: {
313 advance_pkt(pkt, len, ETHER_HDR_LEN);
314 load_net16(pkt, &etype);
315 advance_pkt(pkt, len, 2);
331 advance_pkt(pkt, len, ip->ip_hl << 2);
333 load_net16(&ip->ip_off, &ip_off);
334 if ((ip_off & IP_OFFMASK) != 0 ||
335 (ip_off & IP_MF) != 0)
339 if ((ip_off & IP_OFFMASK) == 0)
340 is_initial_fragment =
true;
345 case ETHERTYPE_IPV6: {
346 const struct ip6_hdr *ip6;
347 const struct ip6_frag *frag;
348 uint16_t payload_len;
352 if (len <
sizeof(*ip6))
354 ip6 = (
const struct ip6_hdr *) dg->
network;
355 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION)
358 nexthdr = ip6->ip6_nxt;
359 thusfar =
sizeof(
struct ip6_hdr);
360 load_net16(&ip6->ip6_plen, &payload_len);
362 while (nexthdr == IPPROTO_ROUTING ||
363 nexthdr == IPPROTO_HOPOPTS ||
364 nexthdr == IPPROTO_FRAGMENT ||
365 nexthdr == IPPROTO_DSTOPTS ||
366 nexthdr == IPPROTO_AH ||
367 nexthdr == IPPROTO_ESP)
373 uint16_t ext_hdr_len;
376 if ((thusfar +
sizeof(ext_hdr)) > len)
379 if (nexthdr == IPPROTO_FRAGMENT) {
381 frag = (
const struct ip6_frag *) (dg->
network + thusfar);
382 if ((frag->ip6f_offlg & IP6F_OFF_MASK) == 0)
383 is_initial_fragment =
true;
386 memcpy(&ext_hdr, (
const u_char *) ip6 + thusfar,
388 nexthdr = ext_hdr.nexthdr;
389 ext_hdr_len = (8 * (ntohs(ext_hdr.length) + 1));
391 if (ext_hdr_len > payload_len)
394 thusfar += ext_hdr_len;
395 payload_len -= ext_hdr_len;
401 if ((thusfar + payload_len) > len || payload_len == 0)
404 advance_pkt(pkt, len, thusfar);
416 if (is_initial_fragment) {
439 load_net16(&udp->uh_ulen, &tp_payload_len);
440 if (tp_payload_len >= 8)
456 tp_payload_len = dg->
len_network - 4 * tcp->th_off;
457 advance_pkt(pkt, len, 4 * tcp->th_off);
nmsg_res nmsg_ipdg_parse_pcap_raw(struct nmsg_ipdg *dg, int datalink, const uint8_t *pkt, size_t len)
Like nmsg_ipdg_parse_pcap(), but performs no fragment handling.
unsigned len_network
length starting from network
int proto_transport
transport protocol
unsigned len_payload
length starting from payload
#define NMSG_IPSZ_MAX
Maximize size of an IP datagram.
nmsg_res nmsg_ipdg_parse(struct nmsg_ipdg *dg, unsigned etype, size_t len, const u_char *pkt)
Parse IP packets from the network layer, discarding fragments.
const u_char * payload
pointer to application payload
const u_char * transport
pointer to transport header
unsigned len_transport
length starting from transport
const u_char * network
pointer to network header
int proto_network
PF_* value.
nmsg_res nmsg_ipdg_parse_pcap(struct nmsg_ipdg *dg, nmsg_pcap_t pcap, struct pcap_pkthdr *pkt_hdr, const u_char *pkt)
Parse IP datagrams from the data link layer, performing reassembly if necessary.