protos: remove wrong inlining
[netsniff-ng.git] / src / proto_ipv4.c
blobf552c05bf5dd333ba15636ec5aeba612935181da
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>.
4 * Copyright (C) 2009, 2010 Daniel Borkmann
5 * Copyright (C) 2012 Christoph Jaeger <christoph@netsniff-ng.org>
6 * Subject to the GPL, version 2.
7 */
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <netinet/in.h> /* for ntohs() */
12 #include <arpa/inet.h> /* for inet_ntop() */
13 #include <asm/byteorder.h>
15 #include "proto.h"
16 #include "protos.h"
17 #include "csum.h"
18 #include "dissector_eth.h"
19 #include "pkt_buff.h"
20 #include "built_in.h"
22 struct ipv4hdr {
23 #if defined(__LITTLE_ENDIAN_BITFIELD)
24 __extension__ uint8_t h_ihl:4,
25 h_version:4;
26 #elif defined (__BIG_ENDIAN_BITFIELD)
27 __extension__ uint8_t h_version:4,
28 h_ihl:4;
29 #else
30 # error "Please fix <asm/byteorder.h>"
31 #endif
32 uint8_t h_tos;
33 uint16_t h_tot_len;
34 uint16_t h_id;
35 uint16_t h_frag_off;
36 uint8_t h_ttl;
37 uint8_t h_protocol;
38 uint16_t h_check;
39 uint32_t h_saddr;
40 uint32_t h_daddr;
41 } __packed;
43 #define FRAG_OFF_RESERVED_FLAG(x) ((x) & 0x8000)
44 #define FRAG_OFF_NO_FRAGMENT_FLAG(x) ((x) & 0x4000)
45 #define FRAG_OFF_MORE_FRAGMENT_FLAG(x) ((x) & 0x2000)
46 #define FRAG_OFF_FRAGMENT_OFFSET(x) ((x) & 0x1fff)
48 /* IP Option Numbers (http://www.iana.org/assignments/ip-parameters) */
49 #define IP_OPT_EOOL 0x00
50 #define IP_OPT_NOP 0x01
52 #define IP_OPT_COPIED_FLAG(x) ((x) & 0x80)
53 #define IP_OPT_CLASS(x) (((x) & 0x60) >> 5)
54 #define IP_OPT_NUMBER(x) ((x) & 0x1F)
56 static void ipv4(struct pkt_buff *pkt)
58 uint16_t csum, frag_off;
59 char src_ip[INET_ADDRSTRLEN];
60 char dst_ip[INET_ADDRSTRLEN];
61 struct ipv4hdr *ip = (struct ipv4hdr *) pkt_pull(pkt, sizeof(*ip));
62 uint8_t *opt;
63 ssize_t opts_len, opt_len;
65 if (!ip)
66 return;
68 frag_off = ntohs(ip->h_frag_off);
69 csum = calc_csum(ip, ip->h_ihl * 4, 0);
71 inet_ntop(AF_INET, &ip->h_saddr, src_ip, sizeof(src_ip));
72 inet_ntop(AF_INET, &ip->h_daddr, dst_ip, sizeof(dst_ip));
74 tprintf(" [ IPv4 ");
75 tprintf("Addr (%s => %s), ", src_ip, dst_ip);
76 tprintf("Proto (%u), ", ip->h_protocol);
77 tprintf("TTL (%u), ", ip->h_ttl);
78 tprintf("TOS (%u), ", ip->h_tos);
79 tprintf("Ver (%u), ", ip->h_version);
80 tprintf("IHL (%u), ", ip->h_ihl);
81 tprintf("Tlen (%u), ", ntohs(ip->h_tot_len));
82 tprintf("ID (%u), ", ntohs(ip->h_id));
83 tprintf("Res (%u), NoFrag (%u), MoreFrag (%u), FragOff (%u), ",
84 FRAG_OFF_RESERVED_FLAG(frag_off) ? 1 : 0,
85 FRAG_OFF_NO_FRAGMENT_FLAG(frag_off) ? 1 : 0,
86 FRAG_OFF_MORE_FRAGMENT_FLAG(frag_off) ? 1 : 0,
87 FRAG_OFF_FRAGMENT_OFFSET(frag_off));
88 tprintf("CSum (0x%.4x) is %s", ntohs(ip->h_check),
89 csum ? colorize_start_full(black, red) "bogus (!)"
90 colorize_end() : "ok");
91 if (csum)
92 tprintf("%s should be 0x%.4x%s", colorize_start_full(black, red),
93 csum_expected(ip->h_check, csum), colorize_end());
94 tprintf(" ]\n");
96 opts_len = max((uint8_t) ip->h_ihl, sizeof(*ip) / sizeof(uint32_t)) *
97 sizeof(uint32_t) - sizeof(*ip);
99 for (opt = pkt_pull(pkt, opts_len); opt && opts_len > 0; opt++) {
100 tprintf(" [ Option Copied (%u), Class (%u), Number (%u)",
101 IP_OPT_COPIED_FLAG(*opt) ? 1 : 0, IP_OPT_CLASS(*opt),
102 IP_OPT_NUMBER(*opt));
104 switch (*opt) {
105 case IP_OPT_EOOL:
106 case IP_OPT_NOP:
107 tprintf(" ]\n");
108 opts_len--;
109 break;
110 default:
112 * Assuming that EOOL and NOP are the only single-byte
113 * options, treat all other options as variable in
114 * length with a minimum of 2.
116 * TODO: option length might be incorrect in malformed packets,
117 * check and handle that
119 opt_len = *(++opt);
120 if (opt_len > opts_len) {
121 tprintf(", Len (%u, invalid) ]\n", opt_len);
122 goto out;
123 } else
124 tprintf(", Len (%u) ]\n", opt_len);
125 opts_len -= opt_len;
126 tprintf(" [ Data hex ");
127 for (opt_len -= 2; opt_len > 0; opt_len--)
128 tprintf(" %.2x", *(++opt));
129 tprintf(" ]\n");
130 break;
133 out:
134 /* cut off everything that is not part of IPv4 payload */
135 pkt_trim(pkt, pkt_len(pkt) - min(pkt_len(pkt), (ntohs(ip->h_tot_len) - ip->h_ihl * sizeof(uint32_t))));
136 pkt_set_proto(pkt, &eth_lay3, ip->h_protocol);
139 static void ipv4_less(struct pkt_buff *pkt)
141 char src_ip[INET_ADDRSTRLEN];
142 char dst_ip[INET_ADDRSTRLEN];
143 struct ipv4hdr *ip = (struct ipv4hdr *) pkt_pull(pkt, sizeof(*ip));
145 if (!ip)
146 return;
148 inet_ntop(AF_INET, &ip->h_saddr, src_ip, sizeof(src_ip));
149 inet_ntop(AF_INET, &ip->h_daddr, dst_ip, sizeof(dst_ip));
151 tprintf(" %s/%s Len %u", src_ip, dst_ip,
152 ntohs(ip->h_tot_len));
154 /* cut off IP options and everything that is not part of IPv4 payload */
155 pkt_pull(pkt, max((uint8_t) ip->h_ihl, sizeof(*ip) / sizeof(uint32_t))
156 * sizeof(uint32_t) - sizeof(*ip));
157 pkt_trim(pkt, pkt_len(pkt) - min(pkt_len(pkt), (ntohs(ip->h_tot_len) - ip->h_ihl * sizeof(uint32_t))));
158 pkt_set_proto(pkt, &eth_lay3, ip->h_protocol);
161 struct protocol ipv4_ops = {
162 .key = 0x0800,
163 .print_full = ipv4,
164 .print_less = ipv4_less,
167 EXPORT_SYMBOL(ipv4_ops);