2 * netsniff-ng - the packet sniffing beast
3 * Copyright (C) 2009, 2010 Daniel Borkmann
4 * Copyright (C) 2012 Christoph Jaeger <christoph@netsniff-ng.org>
5 * Subject to the GPL, version 2.
10 #include <netinet/in.h> /* for ntohs() */
11 #include <arpa/inet.h> /* for inet_ntop() */
15 #include "dissector_eth.h"
21 #define FRAG_OFF_RESERVED_FLAG(x) ((x) & 0x8000)
22 #define FRAG_OFF_NO_FRAGMENT_FLAG(x) ((x) & 0x4000)
23 #define FRAG_OFF_MORE_FRAGMENT_FLAG(x) ((x) & 0x2000)
24 #define FRAG_OFF_FRAGMENT_OFFSET(x) ((x) & 0x1fff)
26 /* IP Option Numbers (http://www.iana.org/assignments/ip-parameters) */
27 #define IP_OPT_EOOL 0x00
28 #define IP_OPT_NOP 0x01
30 #define IP_OPT_COPIED_FLAG(x) ((x) & 0x80)
31 #define IP_OPT_CLASS(x) (((x) & 0x60) >> 5)
32 #define IP_OPT_NUMBER(x) ((x) & 0x1F)
34 static void ipv4(struct pkt_buff
*pkt
)
36 uint16_t csum
, frag_off
, h_tot_len
;
37 char src_ip
[INET_ADDRSTRLEN
];
38 char dst_ip
[INET_ADDRSTRLEN
];
39 struct ipv4hdr
*ip
= (struct ipv4hdr
*) pkt_pull(pkt
, sizeof(*ip
));
40 uint8_t *opt
, *trailer
;
41 unsigned int trailer_len
= 0;
42 ssize_t opts_len
, opt_len
;
43 struct sockaddr_in sas
, sad
;
44 const char *city
, *region
, *country
;
49 frag_off
= ntohs(ip
->h_frag_off
);
50 h_tot_len
= ntohs(ip
->h_tot_len
);
51 csum
= calc_csum(ip
, ip
->h_ihl
* 4);
53 inet_ntop(AF_INET
, &ip
->h_saddr
, src_ip
, sizeof(src_ip
));
54 inet_ntop(AF_INET
, &ip
->h_daddr
, dst_ip
, sizeof(dst_ip
));
56 if ((pkt_len(pkt
) + sizeof(*ip
)) > h_tot_len
) {
57 trailer_len
= pkt_len(pkt
) + sizeof(*ip
) - h_tot_len
;
58 trailer
= pkt
->data
+ h_tot_len
+ trailer_len
;
62 tprintf(" [ Eth trailer ");
63 while (trailer_len
--) {
64 tprintf("%x", *(trailer
- trailer_len
));
70 tprintf("Addr (%s => %s), ", src_ip
, dst_ip
);
71 tprintf("Proto (%u), ", ip
->h_protocol
);
72 tprintf("TTL (%u), ", ip
->h_ttl
);
73 tprintf("TOS (%u), ", ip
->h_tos
);
74 tprintf("Ver (%u), ", ip
->h_version
);
75 tprintf("IHL (%u), ", ip
->h_ihl
);
76 tprintf("Tlen (%u), ", ntohs(ip
->h_tot_len
));
77 tprintf("ID (%u), ", ntohs(ip
->h_id
));
78 tprintf("Res (%u), NoFrag (%u), MoreFrag (%u), FragOff (%u), ",
79 FRAG_OFF_RESERVED_FLAG(frag_off
) ? 1 : 0,
80 FRAG_OFF_NO_FRAGMENT_FLAG(frag_off
) ? 1 : 0,
81 FRAG_OFF_MORE_FRAGMENT_FLAG(frag_off
) ? 1 : 0,
82 FRAG_OFF_FRAGMENT_OFFSET(frag_off
));
83 tprintf("CSum (0x%.4x) is %s", ntohs(ip
->h_check
),
84 csum
? colorize_start_full(black
, red
) "bogus (!)"
85 colorize_end() : "ok");
87 tprintf("%s should be 0x%.4x%s", colorize_start_full(black
, red
),
88 csum_expected(ip
->h_check
, csum
), colorize_end());
91 memset(&sas
, 0, sizeof(sas
));
92 sas
.sin_family
= PF_INET
;
93 sas
.sin_addr
.s_addr
= ip
->h_saddr
;
95 memset(&sad
, 0, sizeof(sad
));
96 sad
.sin_family
= PF_INET
;
97 sad
.sin_addr
.s_addr
= ip
->h_daddr
;
99 if (geoip_working()) {
100 tprintf("\t[ Geo (");
101 if ((country
= geoip4_country_name(&sas
))) {
102 tprintf("%s", country
);
103 if ((region
= geoip4_region_name(&sas
)))
104 tprintf(" / %s", region
);
105 if ((city
= geoip4_city_name(&sas
)))
106 tprintf(" / %s", city
);
111 if ((country
= geoip4_country_name(&sad
))) {
112 tprintf("%s", country
);
113 if ((region
= geoip4_region_name(&sad
)))
114 tprintf(" / %s", region
);
115 if ((city
= geoip4_city_name(&sad
)))
116 tprintf(" / %s", city
);
123 opts_len
= max_t(uint8_t, ip
->h_ihl
, sizeof(*ip
) / sizeof(uint32_t)) *
124 sizeof(uint32_t) - sizeof(*ip
);
126 for (opt
= pkt_pull(pkt
, opts_len
); opt
&& opts_len
> 0; opt
++) {
127 tprintf(" [ Option Copied (%u), Class (%u), Number (%u)",
128 IP_OPT_COPIED_FLAG(*opt
) ? 1 : 0, IP_OPT_CLASS(*opt
),
129 IP_OPT_NUMBER(*opt
));
139 * Assuming that EOOL and NOP are the only single-byte
140 * options, treat all other options as variable in
141 * length with a minimum of 2.
143 * TODO: option length might be incorrect in malformed packets,
144 * check and handle that
147 if (opt_len
> opts_len
) {
148 tprintf(", Len (%zd, invalid) ]\n", opt_len
);
151 tprintf(", Len (%zd) ]\n", opt_len
);
153 tprintf(" [ Data hex ");
154 for (opt_len
-= 2; opt_len
> 0; opt_len
--)
155 tprintf(" %.2x", *(++opt
));
161 /* cut off everything that is not part of IPv4 payload */
162 /* XXX there could still be an Ethernet trailer included or others */
164 pkt_trim(pkt
, pkt_len(pkt
) - min(pkt_len(pkt
),
165 (ntohs(ip
->h_tot_len
) - ip
->h_ihl
* sizeof(uint32_t))));
167 pkt_set_dissector(pkt
, ð_lay3
, ip
->h_protocol
);
170 static void ipv4_less(struct pkt_buff
*pkt
)
172 char src_ip
[INET_ADDRSTRLEN
];
173 char dst_ip
[INET_ADDRSTRLEN
];
174 struct ipv4hdr
*ip
= (struct ipv4hdr
*) pkt_pull(pkt
, sizeof(*ip
));
179 inet_ntop(AF_INET
, &ip
->h_saddr
, src_ip
, sizeof(src_ip
));
180 inet_ntop(AF_INET
, &ip
->h_daddr
, dst_ip
, sizeof(dst_ip
));
182 tprintf(" %s/%s Len %u", src_ip
, dst_ip
,
183 ntohs(ip
->h_tot_len
));
185 /* cut off IP options and everything that is not part of IPv4 payload */
186 pkt_pull(pkt
, max_t(uint8_t, ip
->h_ihl
, sizeof(*ip
) / sizeof(uint32_t))
187 * sizeof(uint32_t) - sizeof(*ip
));
188 /* XXX there could still be an Ethernet trailer included or others */
190 pkt_trim(pkt
, pkt_len(pkt
) - min(pkt_len(pkt
),
191 (ntohs(ip
->h_tot_len
) - ip
->h_ihl
* sizeof(uint32_t))));
193 pkt_set_dissector(pkt
, ð_lay3
, ip
->h_protocol
);
196 struct protocol ipv4_ops
= {
199 .print_less
= ipv4_less
,