Branch data Line data Source code
1 : : // $Id: net_util.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #ifdef BROv6
8 : : #include <sys/types.h>
9 : : #include <sys/socket.h>
10 : :
11 : : #include <netinet/in.h>
12 : :
13 : : #include <arpa/inet.h>
14 : : #endif
15 : :
16 : : #include "net_util.h"
17 : :
18 : : // - adapted from tcpdump
19 : : // Returns the ones-complement checksum of a chunk of b short-aligned bytes.
20 : 50965 : int ones_complement_checksum(const void* p, int b, uint32 sum)
21 : : {
22 : 50965 : const u_short* sp = (u_short*) p; // better be aligned!
23 : :
24 : 50965 : b /= 2; // convert to count of short's
25 : :
26 : : /* No need for endian conversions. */
27 [ + + ]: 5210027 : while ( --b >= 0 )
28 : 5159062 : sum += *sp++;
29 : :
30 [ + + ]: 96381 : while ( sum > 0xffff )
31 : 45416 : sum = (sum & 0xffff) + (sum >> 16);
32 : :
33 : 50965 : return sum;
34 : : }
35 : :
36 : 524 : int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len)
37 : : {
38 : : // ### Note, this is only correct for IPv4. This routine is only
39 : : // used by the connection compressor (which we turn off for IPv6
40 : : // traffic) and trace rewriting (which currently doesn't support
41 : : // IPv6 either).
42 : :
43 : 524 : int tcp_len = tp->th_off * 4 + len;
44 : : uint32 sum;
45 : :
46 [ - + ]: 524 : if ( len % 2 == 1 )
47 : : // Add in pad byte.
48 : 0 : sum = htons(((const u_char*) tp)[tcp_len - 1] << 8);
49 : : else
50 : 524 : sum = 0;
51 : :
52 : 524 : sum = ones_complement_checksum((void*) &ip->ip_src.s_addr, 4, sum);
53 : 524 : sum = ones_complement_checksum((void*) &ip->ip_dst.s_addr, 4, sum);
54 : :
55 : : uint32 addl_pseudo =
56 : 524 : (htons(IPPROTO_TCP) << 16) | htons((unsigned short) tcp_len);
57 : :
58 : 524 : sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
59 : 524 : sum = ones_complement_checksum((void*) tp, tcp_len, sum);
60 : :
61 : 524 : return sum;
62 : : }
63 : :
64 : 1683 : int udp_checksum(const struct ip* ip, const struct udphdr* up, int len)
65 : : {
66 : : uint32 sum;
67 : :
68 [ + + ]: 1683 : if ( len % 2 == 1 )
69 : : // Add in pad byte.
70 : 511 : sum = htons(((const u_char*) up)[len - 1] << 8);
71 : : else
72 : 1172 : sum = 0;
73 : :
74 : 1683 : sum = ones_complement_checksum((void*) &ip->ip_src.s_addr, 4, sum);
75 : 1683 : sum = ones_complement_checksum((void*) &ip->ip_dst.s_addr, 4, sum);
76 : :
77 : : uint32 addl_pseudo =
78 : 1683 : (htons(IPPROTO_UDP) << 16) | htons((unsigned short) len);
79 : :
80 : 1683 : sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
81 : 1683 : sum = ones_complement_checksum((void*) up, len, sum);
82 : :
83 : 1683 : return sum;
84 : : }
85 : :
86 : : #ifdef BROv6
87 : : int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len)
88 : : {
89 : : uint32 sum;
90 : :
91 : : if ( len % 2 == 1 )
92 : : // Add in pad byte.
93 : : sum = htons(((const u_char*) up)[len - 1] << 8);
94 : : else
95 : : sum = 0;
96 : :
97 : : sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum);
98 : : sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum);
99 : :
100 : : sum = ones_complement_checksum((void*) &len, 4, sum);
101 : : uint32 addl_pseudo = htons(IPPROTO_UDP);
102 : : sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
103 : : sum = ones_complement_checksum((void*) up, len, sum);
104 : :
105 : : return sum;
106 : : }
107 : : #endif
108 : :
109 : 31 : int icmp_checksum(const struct icmp* icmpp, int len)
110 : : {
111 : : uint32 sum;
112 : :
113 [ + + ]: 31 : if ( len % 2 == 1 )
114 : : // Add in pad byte.
115 : 1 : sum = htons(((const u_char*) icmpp)[len - 1] << 8);
116 : : else
117 : 30 : sum = 0;
118 : :
119 : 31 : sum = ones_complement_checksum((void*) icmpp, len, sum);
120 : :
121 : 31 : return sum;
122 : : }
123 : :
124 : :
125 : : #define CLASS_A 0x00000000
126 : : #define CLASS_B 0x80000000
127 : : #define CLASS_C 0xc0000000
128 : : #define CLASS_D 0xe0000000
129 : : #define CLASS_E 0xf0000000
130 : :
131 : : #define CHECK_CLASS(addr,class) (((addr) & (class)) == (class))
132 : 0 : char addr_to_class(uint32 addr)
133 : : {
134 [ # # ]: 0 : if ( CHECK_CLASS(addr, CLASS_E) )
135 : 0 : return 'E';
136 [ # # ]: 0 : else if ( CHECK_CLASS(addr, CLASS_D) )
137 : 0 : return 'D';
138 [ # # ]: 0 : else if ( CHECK_CLASS(addr, CLASS_C) )
139 : 0 : return 'C';
140 [ # # ]: 0 : else if ( CHECK_CLASS(addr, CLASS_B) )
141 : 0 : return 'B';
142 : : else
143 : 0 : return 'A';
144 : : }
145 : :
146 : 0 : uint32 addr_to_net(uint32 addr)
147 : : {
148 [ # # ]: 0 : if ( CHECK_CLASS(addr, CLASS_D) )
149 : : ; // class D's are left alone ###
150 [ # # ]: 0 : else if ( CHECK_CLASS(addr, CLASS_C) )
151 : 0 : addr = addr & 0xffffff00;
152 [ # # ]: 0 : else if ( CHECK_CLASS(addr, CLASS_B) )
153 : 0 : addr = addr & 0xffff0000;
154 : : else
155 : 0 : addr = addr & 0xff000000;
156 : :
157 : 0 : return addr;
158 : : }
159 : :
160 : 55146 : const char* dotted_addr(uint32 addr, int alternative)
161 : : {
162 : 55146 : addr = ntohl(addr);
163 [ - + ]: 55146 : const char* fmt = alternative ? "%d,%d.%d.%d" : "%d.%d.%d.%d";
164 : :
165 : : static char buf[32];
166 : : snprintf(buf, sizeof(buf), fmt,
167 : : addr >> 24, (addr >> 16) & 0xff,
168 : 55146 : (addr >> 8) & 0xff, addr & 0xff);
169 : :
170 : 55146 : return buf;
171 : : }
172 : :
173 : 45192 : const char* dotted_addr(const uint32* addr, int alternative)
174 : : {
175 : : #ifdef BROv6
176 : : if ( is_v4_addr(addr) )
177 : : return dotted_addr(addr[3], alternative);
178 : :
179 : : static char buf[256];
180 : :
181 : : if ( inet_ntop(AF_INET6, addr, buf, sizeof buf) == NULL )
182 : : return "<bad IPv6 address conversion>";
183 : :
184 : : return buf;
185 : :
186 : : #else
187 : 45192 : return dotted_addr(to_v4_addr(addr), alternative);
188 : : #endif
189 : : }
190 : :
191 : 0 : const char* dotted_net(uint32 addr)
192 : : {
193 : 0 : addr = ntohl(addr);
194 : :
195 : : static char buf[32];
196 : :
197 [ # # ]: 0 : if ( CHECK_CLASS(addr, CLASS_D) )
198 : : sprintf(buf, "%d.%d.%d.%d",
199 : : addr >> 24, (addr >> 16) & 0xff,
200 : 0 : (addr >> 8) & 0xff, addr & 0xff);
201 : :
202 [ # # ]: 0 : else if ( CHECK_CLASS(addr, CLASS_C) )
203 : : sprintf(buf, "%d.%d.%d",
204 : 0 : addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff);
205 : :
206 : : else
207 : : // Same for class A's and B's.
208 : 0 : sprintf(buf, "%d.%d", addr >> 24, (addr >> 16) & 0xff);
209 : :
210 : 0 : return buf;
211 : : }
212 : :
213 : : #ifdef BROv6
214 : : const char* dotted_net6(const uint32* addr)
215 : : {
216 : : if ( is_v4_addr(addr) )
217 : : return dotted_net(to_v4_addr(addr));
218 : : else
219 : : // ### this isn't right, but net's should go away eventually ...
220 : : return dotted_addr(addr);
221 : : }
222 : : #endif
223 : :
224 : 43 : uint32 dotted_to_addr(const char* addr_text)
225 : : {
226 : : int addr[4];
227 : :
228 [ - + ]: 43 : if ( sscanf(addr_text,
229 : : "%d.%d.%d.%d", addr+0, addr+1, addr+2, addr+3) != 4 )
230 : : {
231 : 0 : error("bad dotted address:", addr_text );
232 : 0 : return 0;
233 : : }
234 : :
235 [ + - ][ + - ]: 43 : if ( addr[0] < 0 || addr[1] < 0 || addr[2] < 0 || addr[3] < 0 ||
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
236 : : addr[0] > 255 || addr[1] > 255 || addr[2] > 255 || addr[3] > 255 )
237 : : {
238 : 0 : error("bad dotted address:", addr_text);
239 : 0 : return 0;
240 : : }
241 : :
242 : 43 : uint32 a = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
243 : :
244 : : // ### perhaps do gethostbyaddr here?
245 : :
246 : 43 : return uint32(htonl(a));
247 : : }
248 : :
249 : : #ifdef BROv6
250 : : uint32* dotted_to_addr6(const char* addr_text)
251 : : {
252 : : uint32* addr = new uint32[4];
253 : : if ( inet_pton(AF_INET6, addr_text, addr) <= 0 )
254 : : {
255 : : error("bad IPv6 address:", addr_text );
256 : : addr[0] = addr[1] = addr[2] = addr[3] = 0;
257 : : }
258 : :
259 : : return addr;
260 : : }
261 : :
262 : : #endif
263 : :
264 : : #ifdef BROv6
265 : : int is_v4_addr(const uint32 addr[4])
266 : : {
267 : : return addr[0] == 0 && addr[1] == 0 && addr[2] == 0;
268 : : }
269 : : #endif
270 : :
271 : 46240 : uint32 to_v4_addr(const uint32* addr)
272 : : {
273 : : #ifdef BROv6
274 : : if ( ! is_v4_addr(addr) )
275 : : internal_error("conversion of non-IPv4 address to IPv4 address");
276 : : return addr[3];
277 : : #else
278 : 46240 : return addr[0];
279 : : #endif
280 : : }
281 : :
282 : 14 : uint32 mask_addr(uint32 a, uint32 top_bits_to_keep)
283 : : {
284 [ - + ]: 14 : if ( top_bits_to_keep > 32 )
285 : : {
286 : 0 : error("bad address mask value", top_bits_to_keep);
287 : 0 : return a;
288 : : }
289 : :
290 [ + + ]: 14 : if ( top_bits_to_keep == 0 )
291 : : // The shifts below don't have any effect with 0, i.e.,
292 : : // 1 << 32 does not yield 0; either due to compiler
293 : : // misoptimization or language semantics.
294 : 1 : return 0;
295 : :
296 : 13 : uint32 addr = ntohl(a);
297 : :
298 : 13 : int shift = 32 - top_bits_to_keep;
299 : 13 : addr >>= shift;
300 : 13 : addr <<= shift;
301 : :
302 : 14 : return htonl(addr);
303 : : }
304 : :
305 : 0 : const uint32* mask_addr(const uint32* a, uint32 top_bits_to_keep)
306 : : {
307 : : #ifdef BROv6
308 : : static uint32 addr[4];
309 : :
310 : : addr[0] = a[0];
311 : : addr[1] = a[1];
312 : : addr[2] = a[2];
313 : : addr[3] = a[3];
314 : :
315 : : // This is a bit dicey: if it's a v4 address, then we interpret
316 : : // the mask as being with respect to 32 bits total, even though
317 : : // strictly speaking, the v4 address comprises the least-significant
318 : : // bits out of 128, rather than the most significant. However,
319 : : // we only do this if the mask itself is consistent for a 32-bit
320 : : // address.
321 : : uint32 max_bits = (is_v4_addr(a) && top_bits_to_keep <= 32) ? 32 : 128;
322 : :
323 : : if ( top_bits_to_keep == 0 || top_bits_to_keep > max_bits )
324 : : {
325 : : error("bad address mask value", top_bits_to_keep);
326 : : return addr;
327 : : }
328 : :
329 : : int word = 3; // start zeroing out with word #3
330 : : int bits_to_chop = max_bits - top_bits_to_keep; // bits to discard
331 : : while ( bits_to_chop >= 32 )
332 : : { // there's an entire word to discard
333 : : addr[word] = 0;
334 : : --word; // move on to next, more significant word
335 : : bits_to_chop -= 32; // we just go rid of 32 bits
336 : : }
337 : :
338 : : // All that's left to work with now is the word pointed to by "word".
339 : : uint32 addr32 = ntohl(addr[word]);
340 : : addr32 >>= bits_to_chop;
341 : : addr32 <<= bits_to_chop;
342 : : addr[word] = htonl(addr32);
343 : :
344 : : return addr;
345 : : #else
346 : 0 : return a;
347 : : #endif
348 : : }
349 : :
350 : : const char* fmt_conn_id(const uint32* src_addr, uint32 src_port,
351 : 22596 : const uint32* dst_addr, uint32 dst_port)
352 : : {
353 : : char addr1[128], addr2[128];
354 : : static char buffer[512];
355 : :
356 : 22596 : strcpy(addr1, dotted_addr(src_addr));
357 : 22596 : strcpy(addr2, dotted_addr(dst_addr));
358 : :
359 : : safe_snprintf(buffer, sizeof(buffer), "%s:%d > %s:%d",
360 : 22596 : addr1, src_port, addr2, dst_port);
361 : :
362 : 22596 : return buffer;
363 : : }
364 : :
365 : 0 : uint32 extract_uint32(const u_char* data)
366 : : {
367 : : uint32 val;
368 : :
369 : 0 : val = data[0] << 24;
370 : 0 : val |= data[1] << 16;
371 : 0 : val |= data[2] << 8;
372 : 0 : val |= data[3];
373 : :
374 : 0 : return val;
375 : : }
|