]> git.saurik.com Git - apple/network_cmds.git/blob - ecnprobe/inet.c
network_cmds-606.100.3.tar.gz
[apple/network_cmds.git] / ecnprobe / inet.c
1 /*
2 Copyright (c) 2000
3 International Computer Science Institute
4 All rights reserved.
5
6 This file may contain software code originally developed for the
7 Sting project. The Sting software carries the following copyright:
8
9 Copyright (c) 1998, 1999
10 Stefan Savage and the University of Washington.
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
21 3. All advertising materials mentioning features or use of this software
22 must display the following acknowledgment:
23 This product includes software developed by ACIRI, the AT&T
24 Center for Internet Research at ICSI (the International Computer
25 Science Institute). This product may also include software developed
26 by Stefan Savage at the University of Washington.
27 4. The names of ACIRI, ICSI, Stefan Savage and University of Washington
28 may not be used to endorse or promote products derived from this software
29 without specific prior written permission.
30
31 THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND
32 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ARE DISCLAIMED. IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE
35 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 SUCH DAMAGE.
42 */
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #include <string.h>
47 #include <stdio.h>
48 #include <unistd.h>
49 #include "base.h"
50 #include "inet.h"
51 #include "session.h"
52 #include "capture.h"
53 #include "support.h"
54 #include "history.h"
55
56 extern struct TcpSession session;
57 extern struct History history[];
58
59 /*
60 * Deal with struct in_addr type agreement once and for all
61 */
62 char *InetAddress(uint32 addr)
63 {
64
65 struct in_addr s;
66 s.s_addr = addr;
67
68 //printf("In InetAddress:\n");
69 //printf("addr = %s (%0x)\n", inet_ntoa(s), addr);
70
71 return (inet_ntoa(s));
72 }
73
74 /*
75 * Really slow implementation of ip checksum
76 * ripped off from rfc1071
77 */
78
79 uint16 InetChecksum(uint16 *ip, uint16 *tcp, uint16 ip_len, uint16 tcp_len) {
80
81 uint32 sum = 0;
82
83 uint32 ip_count = ip_len;
84 uint32 tcp_count = tcp_len;
85 uint16 *ip_addr = ip;
86 uint16 *tcp_addr = tcp;
87
88 if (session.debug >= SESSION_DEBUG_HIGH) {
89 printf("In InetChecksum...\n");
90 printf("iplen: %d, tcplen: %d\n", ip_len, tcp_len);
91 }
92
93
94 while(ip_count > 1) {
95 //printf("ip[%d]: %x\n", ip_len - ip_count, htons(*ip_addr));
96 sum += *ip_addr++;
97 ip_count -= 2;
98 }
99
100 while(tcp_count > 1) {
101 //printf("tcp[%d]: %x\n", tcp_len - tcp_count, htons(*tcp_addr));
102 sum += *tcp_addr++;
103 tcp_count -= 2;
104 }
105
106 if(ip_count > 0) {
107 sum += *(uint8 *)ip_addr;
108 }
109
110 if(tcp_count > 0) {
111 sum += *(uint8 *)tcp_addr;
112 }
113
114 while (sum >> 16) {
115 sum = (sum & 0xffff) + (sum >> 16);
116 }
117
118 if (session.debug >= SESSION_DEBUG_HIGH) {
119 printf("Out InetChecksum...\n");
120 }
121
122 return(~sum);
123
124 }
125
126
127 void WriteIPPacket(struct IPPacket *p,
128 uint32 src,
129 uint32 dst,
130 uint16 sport,
131 uint16 dport,
132 uint32 seq,
133 uint32 ack,
134 uint8 flags,
135 uint16 win,
136 uint16 urp,
137 uint16 datalen,
138 uint16 ip_optlen,
139 uint16 optlen,
140 uint8 iptos,
141 uint8 u4tf)
142 {
143
144 struct IpHeader *ip = p->ip;
145 struct TcpHeader *tcp = p->tcp;
146
147 if (session.debug >= SESSION_DEBUG_HIGH) {
148 printf("In WriteIPPacket...\n");
149 }
150
151 /* Zero out IpHeader to ensure proper checksum computation */
152 bzero((char *)(p->ip), sizeof(struct IpHeader));
153
154 ip->ip_src = src;
155 ip->ip_dst = dst;
156 ip->ip_p = IPPROTOCOL_TCP;
157 ip->ip_xsum =
158 htons((uint16)(sizeof(struct TcpHeader) + datalen + optlen)); /* pseudo hdr */
159
160 tcp->tcp_sport = htons(sport);
161 tcp->tcp_dport = htons(dport);
162 tcp->tcp_seq = htonl(seq);
163 tcp->tcp_ack = htonl(ack);
164 tcp->tcp_hl = (sizeof(struct TcpHeader) + optlen) << 2;
165 tcp->tcp_hl = tcp->tcp_hl | u4tf;
166 tcp->tcp_flags = flags;
167
168 tcp->tcp_win = htons(win);
169 tcp->tcp_urp = htons(urp);
170
171 tcp->tcp_xsum = 0;
172 tcp->tcp_xsum = InetChecksum((uint16 *)ip, (uint16 *)tcp,
173 (uint16)sizeof(struct IpHeader), /* IP Options should aren't included */
174 (uint16)(sizeof(struct TcpHeader) + datalen + optlen));
175
176 /* Fill in real ip header */
177 if (session.curr_ttl != 0) {
178 ip->ip_ttl = session.curr_ttl;
179 }else {
180 ip->ip_ttl = 60;
181 }
182
183 //printf("TTL: %d\n", ip->ip_ttl);
184
185 ip->ip_tos = iptos;
186
187 /* IP Version and Header len field */
188 ip->ip_vhl = 0x40 + 0x5 + (int)(ip_optlen/4);
189 ip->ip_p = IPPROTOCOL_TCP;
190
191 ip->ip_off = IP_DF;
192 ip->ip_len = (uint16)(sizeof(struct IpHeader) + ip_optlen + sizeof(struct TcpHeader) + optlen + datalen);
193
194 ip->ip_xsum = 0;
195 ip->ip_xsum = InetChecksum((uint16 *)ip, NULL,
196 (uint16)sizeof(struct IpHeader) + ip_optlen, /* IP Options should aren't included */
197 0);
198
199 if (session.debug >= SESSION_DEBUG_HIGH) {
200 printf("Out WriteIPPacket...\n");
201 }
202
203 }
204
205 void ReadIPPacket(struct IPPacket *p,
206 uint32 *src,
207 uint32 *dst,
208 uint16 *sport,
209 uint16 *dport,
210 uint32 *seq,
211 uint32 *ack,
212 uint8 *flags,
213 uint16 *win,
214 uint16 *urp,
215 uint16 *datalen,
216 uint16 *ip_optlen,
217 uint16 *optlen)
218 {
219
220 /* TODO: Add reading of IP options, if any */
221
222 struct IpHeader *ip = p->ip;
223 struct TcpHeader *tcp = p->tcp;
224
225 uint16 ip_len;
226 uint16 ip_hl;
227 uint16 tcp_hl;
228
229 /* XXX do checksum check? */
230 if (ip->ip_p != IPPROTOCOL_TCP && ip->ip_p != IPPROTOCOL_ICMP) {
231 printf("Unexpected protocol packet: %u\n", ip->ip_p);
232 Quit(ERR_CHECKSUM);
233 }
234
235 *src = ip->ip_src;
236 *dst = ip->ip_dst;
237 *sport = ntohs(tcp->tcp_sport);
238 *dport = ntohs(tcp->tcp_dport);
239 *seq = ntohl(tcp->tcp_seq);
240 *ack = ntohl(tcp->tcp_ack);
241 *flags = tcp->tcp_flags;
242 *win = ntohs(tcp->tcp_win);
243 *urp = ntohs(tcp->tcp_urp);
244
245 tcp_hl = tcp->tcp_hl >> 2;
246 ip_len = ntohs(ip->ip_len);
247 ip_hl = (ip->ip_vhl & 0x0f) << 2;
248 *datalen = (ip_len - ip_hl) - tcp_hl;
249 *ip_optlen = ip_hl - (unsigned int)sizeof(struct IpHeader); /* added to support IP Options */
250 *optlen = tcp_hl - (unsigned int)sizeof(struct TcpHeader);
251
252 }
253
254 void PrintICMPUnreachableErrorPacket(struct ICMPUnreachableErrorPacket *p)
255 {
256
257 struct IpHeader *ip = &p->ip;
258 struct IcmpHeader *icmp = &p->icmp;
259 struct IpHeader *off_ip = &p->off_ip;
260
261 printf("IPHdr: ");
262 printf("%s > ", InetAddress(ip->ip_src));
263 printf("%s ", InetAddress(ip->ip_dst));
264 printf(" datalen: %u\n", ip->ip_len);
265 printf("ICMPHdr: ");
266 printf("Type: %u Code: %u MTU next hop: %u xsum: %x\n",
267 icmp->icmp_type,
268 icmp->icmp_code,
269 ntohs(icmp->icmp_mtu),
270 icmp->icmp_xsum);
271 printf("Off IPHdr: ");
272 printf("%s > ", InetAddress(off_ip->ip_src));
273 printf("%s ", InetAddress(off_ip->ip_dst));
274 printf(" datalen: %u ", off_ip->ip_len);
275 printf("tcp sport: %u ", ntohs(p->tcp_sport));
276 printf("tcp dport: %u ", ntohs(p->tcp_dport));
277 printf("tcp seqno: %u\n", (uint32)ntohl(p->tcp_seqno));
278
279 }
280
281 void PrintTcpPacket(struct IPPacket *p)
282 {
283
284 struct IpHeader *ip = p->ip;
285 struct TcpHeader *tcp = p->tcp;
286
287 char *opt;
288 int optlen;
289 char *ip_opt;
290 int ip_optlen;
291 int i;
292
293 printf("%s.%u > ", InetAddress(ip->ip_src), ntohs(tcp->tcp_sport));
294 printf("%s.%u ", InetAddress(ip->ip_dst), ntohs(tcp->tcp_dport));
295
296 if (tcp->tcp_flags & TCPFLAGS_SYN) {
297 printf("S");
298 }
299
300 if (tcp->tcp_flags & TCPFLAGS_ACK) {
301 printf("A");
302 }
303
304 if (tcp->tcp_flags & TCPFLAGS_FIN) {
305 printf("F");
306 }
307
308 if (tcp->tcp_flags & TCPFLAGS_ECN_ECHO) {
309 printf("E");
310 }
311
312 if (tcp->tcp_flags & TCPFLAGS_CWR) {
313 printf("W");
314 }
315
316 if (tcp->tcp_flags & TCPFLAGS_RST) {
317 printf("R");
318 }
319 if (tcp->tcp_flags & TCPFLAGS_PSH) {
320 printf("P");
321 }
322
323 if (tcp->tcp_flags & TCPFLAGS_URG) {
324 printf("U");
325 }
326
327 if (INSESSION(p,session.src,session.sport,session.dst,session.dport)) {
328 printf(" seq: %u, ack: %u", (uint32)ntohl(tcp->tcp_seq) - session.iss, (uint32)ntohl(tcp->tcp_ack) - session.irs);
329 } else {
330 printf(" seq: %u, ack: %u", (uint32)ntohl(tcp->tcp_seq) - session.irs, (uint32)ntohl(tcp->tcp_ack) - session.iss);
331 }
332
333 /* IP Options */
334 ip_optlen = ((ip->ip_vhl & 0x0f) << 2) - sizeof(struct IpHeader);
335 ip_opt = (char *)ip + sizeof(struct IpHeader);
336
337 i = 0;
338 while (i < ip_optlen) {
339
340 switch ((unsigned char)ip_opt[i]) {
341 case IPOPT_NOP:
342 printf(" ipopt%d: %s ", i + 1, "IPOPT_NOP");
343 i = i + 1;
344 break;
345
346 case IPOPT_EOL:
347 printf(" ipopt%d: %s ", i + 1, "IPOPT_EOL");
348 i = ip_optlen + 1;
349 break;
350
351 case IPOPT_RR:
352 printf(" ipopt%d: %s ", i + 1, "IPOPT_RR");
353 i = i + IPOLEN_RR;
354 break;
355
356 default:
357 printf("ip_opt%d: UNKNOWN ", i + 1);
358 i = i + (uint8)ip_opt[i+1] ;
359 }
360 }
361
362 printf(" win: %u, urg: %u, ttl: %d", ntohs(tcp->tcp_win), ntohs(tcp->tcp_urp), ip->ip_ttl);
363 printf(" datalen: %u, optlen: %u ",
364 ip->ip_len - ((ip->ip_vhl &0x0f) << 2) - (tcp->tcp_hl >> 2),
365 (tcp->tcp_hl >> 2) - (unsigned int)sizeof(struct TcpHeader));
366
367
368 /* TCP Options */
369 optlen = (tcp->tcp_hl >> 2) - (unsigned int)sizeof (struct TcpHeader) ;
370 opt = (char *)tcp + sizeof(struct TcpHeader);
371
372 i = 0 ;
373
374 while (i < optlen) {
375
376 switch ((unsigned char)opt[i]) {
377
378 case TCPOPT_EOL:
379 printf (" opt%d: %s ", i + 1, "TCPOPT_EOL");
380 i = optlen + 1;
381 break ;
382
383 case TCPOPT_NOP:
384 printf (" opt%d: %s ", i + 1, "TCPOPT_NOP");
385 i++ ;
386 break ;
387
388 case TCPOPT_MAXSEG:
389 printf (" opt%d: %s: %d ", i + 1, "TCPOPT_MAXSEG", ntohs(*(uint16 *)((char *)opt+2)));
390 i = i + TCPOLEN_MAXSEG ;
391 break ;
392
393 case TCPOPT_WINDOW:
394 printf (" opt%d: %s ", i + 1, "TCPOPT_WINDOW");
395 i = i + TCPOLEN_WINDOW ;
396 break ;
397
398 case TCPOPT_SACK_PERMITTED:
399 printf (" opt%d: %s ", i + 1, "TCPOPT_SACK_PERMITTED");
400 i = i + TCPOLEN_SACK_PERMITTED ;
401 break ;
402
403 case TCPOPT_TIMESTAMP:
404 printf (" opt%d: %s ", i + 1, "TCPOPT_TIMESTAMP");
405 i = i + TCPOLEN_TIMESTAMP ;
406 break ;
407
408 default:
409 printf (" opt%d c:%d l:%d: UNKNOWN ", i + 1, (uint8)opt[i], (uint8)opt[i+1]);
410 if ((uint8)opt[i+1] > 0) {
411 i = i + (uint8)opt[i+1] ;
412 } else {
413 Quit(20);
414 }
415 break ;
416 }
417 }
418 printf ("\n");
419 }
420
421
422 struct IPPacket *FindHeaderBoundaries(char *p) {
423
424 struct IPPacket *packet;
425 uint16 ip_hl;
426
427 if ((packet = (struct IPPacket *)calloc(1, sizeof(struct IPPacket))) == NULL) {
428 printf("FindHeaderBoundaries: Cannot allocate memory for read packet\nRETURN CODE: %d\n", ERR_MEM_ALLOC);
429 Quit(ERR_MEM_ALLOC);
430 }
431
432 packet->ip = (struct IpHeader *)p;
433
434 if (packet->ip->ip_p != IPPROTOCOL_TCP &&
435 packet->ip->ip_p != IPPROTOCOL_ICMP) {
436 printf("Error: Unexpected protocol packet: %u \n", packet->ip->ip_p);
437 Quit(ERR_CHECKSUM);
438 }
439
440 ip_hl = (packet->ip->ip_vhl & 0x0f) << 2;
441
442 packet->tcp = (struct TcpHeader *)((char *)p + ip_hl);
443 return packet;
444
445 }
446
447
448 struct IPPacket *
449 AllocateIPPacket(int ip_optlen, int tcp_optlen, int datalen, char *str)
450 {
451 struct IPPacket *p;
452
453 if (session.debug >= SESSION_DEBUG_HIGH) {
454 printf("In AllocateIPPacket: %s...\n", str);
455 }
456
457 if ((p = (struct IPPacket *)calloc(1, sizeof(struct IPPacket)))
458 == NULL) {
459 printf("%s ERROR: No space for packet\nRETURN CODE: %d",
460 str, ERR_MEM_ALLOC);
461 Quit(ERR_MEM_ALLOC);
462 }
463
464 if ((p->ip = (struct IpHeader *)calloc(1,
465 sizeof(struct IpHeader) + ip_optlen)) == NULL) {
466 printf("%s ERROR: No IpHeader space for packet\n"
467 "RETURN CODE: %d", str, ERR_MEM_ALLOC);
468 Quit(ERR_MEM_ALLOC);
469 }
470
471 if ((p->tcp = (struct TcpHeader *)calloc(1,
472 sizeof(struct TcpHeader) + tcp_optlen + datalen)) == NULL) {
473 printf("%s ERROR: No TcpHeader space for packet\n"
474 "RETURN CODE: %d", str, ERR_MEM_ALLOC);
475 Quit(ERR_MEM_ALLOC);
476 }
477
478 if (session.debug >= SESSION_DEBUG_HIGH) {
479 printf("Out of AllocateIPPacket: %s...\n", str);
480 }
481 return(p);
482 }
483
484 void
485 FreeIPPacket(struct IPPacket **pkt_p)
486 {
487 struct IPPacket *pkt;
488 if (pkt_p == NULL)
489 return;
490 if ((pkt = *pkt_p) == NULL)
491 return;
492 if (pkt->ip != NULL) {
493 free(pkt->ip);
494 pkt->ip = NULL;
495 }
496 if (pkt->tcp != NULL) {
497 free(pkt->tcp);
498 pkt->tcp = NULL;
499 }
500 free(pkt);
501 *pkt_p = NULL;
502 }
503