xio: add nacl's randombyte function
[netsniff-ng.git] / proto_ipv4.c
blob99a9d7c0a6c7d668b3da697b4d0b885ee6e6c5e6
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() */
14 #include "proto.h"
15 #include "protos.h"
16 #include "csum.h"
17 #include "dissector_eth.h"
18 #include "ipv4.h"
19 #include "pkt_buff.h"
20 #include "built_in.h"
22 #define FRAG_OFF_RESERVED_FLAG(x) ((x) & 0x8000)
23 #define FRAG_OFF_NO_FRAGMENT_FLAG(x) ((x) & 0x4000)
24 #define FRAG_OFF_MORE_FRAGMENT_FLAG(x) ((x) & 0x2000)
25 #define FRAG_OFF_FRAGMENT_OFFSET(x) ((x) & 0x1fff)
27 /* IP Option Numbers (http://www.iana.org/assignments/ip-parameters) */
28 #define IP_OPT_EOOL 0x00
29 #define IP_OPT_NOP 0x01
31 #define IP_OPT_COPIED_FLAG(x) ((x) & 0x80)
32 #define IP_OPT_CLASS(x) (((x) & 0x60) >> 5)
33 #define IP_OPT_NUMBER(x) ((x) & 0x1F)
35 static void ipv4(struct pkt_buff *pkt)
37 uint16_t csum, frag_off, h_tot_len;
38 char src_ip[INET_ADDRSTRLEN];
39 char dst_ip[INET_ADDRSTRLEN];
40 struct ipv4hdr *ip = (struct ipv4hdr *) pkt_pull(pkt, sizeof(*ip));
41 uint8_t *opt, *trailer;
42 unsigned int trailer_len = 0;
43 ssize_t opts_len, opt_len;
45 if (!ip)
46 return;
48 frag_off = ntohs(ip->h_frag_off);
49 h_tot_len = ntohs(ip->h_tot_len);
50 csum = calc_csum(ip, ip->h_ihl * 4, 0);
52 inet_ntop(AF_INET, &ip->h_saddr, src_ip, sizeof(src_ip));
53 inet_ntop(AF_INET, &ip->h_daddr, dst_ip, sizeof(dst_ip));
55 if ((pkt_len(pkt) + sizeof(*ip)) > h_tot_len) {
56 trailer_len = pkt_len(pkt) + sizeof(*ip) - h_tot_len;
57 trailer = pkt->data + h_tot_len + trailer_len;
60 if (trailer_len) {
61 tprintf(" [ Eth trailer ");
62 while (trailer_len--) {
63 tprintf("%x", *(trailer - trailer_len));
65 tprintf(" ]\n");
68 tprintf(" [ IPv4 ");
69 tprintf("Addr (%s => %s), ", src_ip, dst_ip);
70 tprintf("Proto (%u), ", ip->h_protocol);
71 tprintf("TTL (%u), ", ip->h_ttl);
72 tprintf("TOS (%u), ", ip->h_tos);
73 tprintf("Ver (%u), ", ip->h_version);
74 tprintf("IHL (%u), ", ip->h_ihl);
75 tprintf("Tlen (%u), ", ntohs(ip->h_tot_len));
76 tprintf("ID (%u), ", ntohs(ip->h_id));
77 tprintf("Res (%u), NoFrag (%u), MoreFrag (%u), FragOff (%u), ",
78 FRAG_OFF_RESERVED_FLAG(frag_off) ? 1 : 0,
79 FRAG_OFF_NO_FRAGMENT_FLAG(frag_off) ? 1 : 0,
80 FRAG_OFF_MORE_FRAGMENT_FLAG(frag_off) ? 1 : 0,
81 FRAG_OFF_FRAGMENT_OFFSET(frag_off));
82 tprintf("CSum (0x%.4x) is %s", ntohs(ip->h_check),
83 csum ? colorize_start_full(black, red) "bogus (!)"
84 colorize_end() : "ok");
85 if (csum)
86 tprintf("%s should be 0x%.4x%s", colorize_start_full(black, red),
87 csum_expected(ip->h_check, csum), colorize_end());
88 tprintf(" ]\n");
90 opts_len = max((uint8_t) ip->h_ihl, sizeof(*ip) / sizeof(uint32_t)) *
91 sizeof(uint32_t) - sizeof(*ip);
93 for (opt = pkt_pull(pkt, opts_len); opt && opts_len > 0; opt++) {
94 tprintf(" [ Option Copied (%u), Class (%u), Number (%u)",
95 IP_OPT_COPIED_FLAG(*opt) ? 1 : 0, IP_OPT_CLASS(*opt),
96 IP_OPT_NUMBER(*opt));
98 switch (*opt) {
99 case IP_OPT_EOOL:
100 case IP_OPT_NOP:
101 tprintf(" ]\n");
102 opts_len--;
103 break;
104 default:
106 * Assuming that EOOL and NOP are the only single-byte
107 * options, treat all other options as variable in
108 * length with a minimum of 2.
110 * TODO: option length might be incorrect in malformed packets,
111 * check and handle that
113 opt_len = *(++opt);
114 if (opt_len > opts_len) {
115 tprintf(", Len (%zd, invalid) ]\n", opt_len);
116 goto out;
117 } else
118 tprintf(", Len (%zd) ]\n", opt_len);
119 opts_len -= opt_len;
120 tprintf(" [ Data hex ");
121 for (opt_len -= 2; opt_len > 0; opt_len--)
122 tprintf(" %.2x", *(++opt));
123 tprintf(" ]\n");
124 break;
127 out:
128 /* cut off everything that is not part of IPv4 payload */
129 /* XXX there could still be an Ethernet trailer included or others */
131 pkt_trim(pkt, pkt_len(pkt) - min(pkt_len(pkt),
132 (ntohs(ip->h_tot_len) - ip->h_ihl * sizeof(uint32_t))));
134 pkt_set_proto(pkt, &eth_lay3, ip->h_protocol);
137 static void ipv4_less(struct pkt_buff *pkt)
139 char src_ip[INET_ADDRSTRLEN];
140 char dst_ip[INET_ADDRSTRLEN];
141 struct ipv4hdr *ip = (struct ipv4hdr *) pkt_pull(pkt, sizeof(*ip));
143 if (!ip)
144 return;
146 inet_ntop(AF_INET, &ip->h_saddr, src_ip, sizeof(src_ip));
147 inet_ntop(AF_INET, &ip->h_daddr, dst_ip, sizeof(dst_ip));
149 tprintf(" %s/%s Len %u", src_ip, dst_ip,
150 ntohs(ip->h_tot_len));
152 /* cut off IP options and everything that is not part of IPv4 payload */
153 pkt_pull(pkt, max((uint8_t) ip->h_ihl, sizeof(*ip) / sizeof(uint32_t))
154 * sizeof(uint32_t) - sizeof(*ip));
155 /* XXX there coul still be an Ethernet trailer included or others */
156 #if 0
157 pkt_trim(pkt, pkt_len(pkt) - min(pkt_len(pkt),
158 (ntohs(ip->h_tot_len) - ip->h_ihl * sizeof(uint32_t))));
159 #endif
160 pkt_set_proto(pkt, &eth_lay3, ip->h_protocol);
163 struct protocol ipv4_ops = {
164 .key = 0x0800,
165 .print_full = ipv4,
166 .print_less = ipv4_less,