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.
11 #include <netinet/in.h> /* for ntohs() */
12 #include <arpa/inet.h> /* for inet_ntop() */
13 #include <asm/byteorder.h>
18 #include "dissector_eth.h"
23 #if defined(__LITTLE_ENDIAN_BITFIELD)
24 __extension__
uint8_t h_ihl
:4,
26 #elif defined (__BIG_ENDIAN_BITFIELD)
27 __extension__
uint8_t h_version
:4,
30 # error "Please fix <asm/byteorder.h>"
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
));
63 ssize_t opts_len
, opt_len
;
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
));
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");
92 tprintf("%s should be 0x%.4x%s", colorize_start_full(black
, red
),
93 csum_expected(ip
->h_check
, csum
), colorize_end());
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
));
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
120 if (opt_len
> opts_len
) {
121 tprintf(", Len (%u, invalid) ]\n", opt_len
);
124 tprintf(", Len (%u) ]\n", opt_len
);
126 tprintf(" [ Data hex ");
127 for (opt_len
-= 2; opt_len
> 0; opt_len
--)
128 tprintf(" %.2x", *(++opt
));
134 /* cut off everything that is not part of IPv4 payload */
135 /* XXX there coul still be an Ethernet trailer included or others */
137 pkt_trim(pkt
, pkt_len(pkt
) - min(pkt_len(pkt
),
138 (ntohs(ip
->h_tot_len
) - ip
->h_ihl
* sizeof(uint32_t))));
140 pkt_set_proto(pkt
, ð_lay3
, ip
->h_protocol
);
143 static void ipv4_less(struct pkt_buff
*pkt
)
145 char src_ip
[INET_ADDRSTRLEN
];
146 char dst_ip
[INET_ADDRSTRLEN
];
147 struct ipv4hdr
*ip
= (struct ipv4hdr
*) pkt_pull(pkt
, sizeof(*ip
));
152 inet_ntop(AF_INET
, &ip
->h_saddr
, src_ip
, sizeof(src_ip
));
153 inet_ntop(AF_INET
, &ip
->h_daddr
, dst_ip
, sizeof(dst_ip
));
155 tprintf(" %s/%s Len %u", src_ip
, dst_ip
,
156 ntohs(ip
->h_tot_len
));
158 /* cut off IP options and everything that is not part of IPv4 payload */
159 pkt_pull(pkt
, max((uint8_t) ip
->h_ihl
, sizeof(*ip
) / sizeof(uint32_t))
160 * sizeof(uint32_t) - sizeof(*ip
));
161 /* XXX there coul still be an Ethernet trailer included or others */
163 pkt_trim(pkt
, pkt_len(pkt
) - min(pkt_len(pkt
),
164 (ntohs(ip
->h_tot_len
) - ip
->h_ihl
* sizeof(uint32_t))));
166 pkt_set_proto(pkt
, ð_lay3
, ip
->h_protocol
);
169 struct protocol ipv4_ops
= {
172 .print_less
= ipv4_less
,
175 EXPORT_SYMBOL(ipv4_ops
);