]> git.saurik.com Git - apple/network_cmds.git/blame - ecnprobe/inet.c
network_cmds-480.tar.gz
[apple/network_cmds.git] / ecnprobe / inet.c
CommitLineData
89c4ed63
A
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
56extern struct TcpSession session;
57extern struct History history[];
58
59/*
60 * Deal with struct in_addr type agreement once and for all
61 */
62char *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
79uint16 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
127void 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 if (session.debug == SESSION_DEBUG_HIGH) {
195 printf("Out WriteIPPacket...\n");
196 }
197
198}
199
200void ReadIPPacket(struct IPPacket *p,
201 uint32 *src,
202 uint32 *dst,
203 uint16 *sport,
204 uint16 *dport,
205 uint32 *seq,
206 uint32 *ack,
207 uint8 *flags,
208 uint16 *win,
209 uint16 *urp,
210 uint16 *datalen,
211 uint16 *ip_optlen,
212 uint16 *optlen)
213{
214
215 /* TODO: Add reading of IP options, if any */
216
217 struct IpHeader *ip = p->ip;
218 struct TcpHeader *tcp = p->tcp;
219
220 uint16 ip_len;
221 uint16 ip_hl;
222 uint16 tcp_hl;
223
224 /* XXX do checksum check? */
225 if (ip->ip_p != IPPROTOCOL_TCP) {
226 printf("Error: not a TCP packet\n");
227 Quit(ERR_CHECKSUM);
228 }
229
230 *src = ip->ip_src;
231 *dst = ip->ip_dst;
232 *sport = ntohs(tcp->tcp_sport);
233 *dport = ntohs(tcp->tcp_dport);
234 *seq = ntohl(tcp->tcp_seq);
235 *ack = ntohl(tcp->tcp_ack);
236 *flags = tcp->tcp_flags;
237 *win = ntohs(tcp->tcp_win);
238 *urp = ntohs(tcp->tcp_urp);
239
240 tcp_hl = tcp->tcp_hl >> 2;
241 ip_len = ntohs(ip->ip_len);
242 ip_hl = (ip->ip_vhl & 0x0f) << 2;
243 *datalen = (ip_len - ip_hl) - tcp_hl;
244 *ip_optlen = ip_hl - (unsigned int)sizeof(struct IpHeader); /* added to support IP Options */
245 *optlen = tcp_hl - (unsigned int)sizeof(struct TcpHeader);
246
247}
248
249void PrintICMPUnreachableErrorPacket(struct ICMPUnreachableErrorPacket *p)
250{
251
252 struct IpHeader *ip = &p->ip;
253 struct IcmpHeader *icmp = &p->icmp;
254 struct IpHeader *off_ip = &p->off_ip;
255
256 printf("IPHdr: ");
257 printf("%s > ", InetAddress(ip->ip_src));
258 printf("%s ", InetAddress(ip->ip_dst));
259 printf(" datalen: %u\n", ip->ip_len);
260 printf("ICMPHdr: ");
261 printf("Type: %u Code: %u MTU next hop: %u xsum: %x\n",
262 icmp->icmp_type,
263 icmp->icmp_code,
264 ntohs(icmp->icmp_mtu),
265 icmp->icmp_xsum);
266 printf("Off IPHdr: ");
267 printf("%s > ", InetAddress(off_ip->ip_src));
268 printf("%s ", InetAddress(off_ip->ip_dst));
269 printf(" datalen: %u ", off_ip->ip_len);
270 printf("tcp sport: %u ", ntohs(p->tcp_sport));
271 printf("tcp dport: %u ", ntohs(p->tcp_dport));
272 printf("tcp seqno: %u\n", (uint32)ntohl(p->tcp_seqno));
273
274}
275
276void PrintTcpPacket(struct IPPacket *p)
277{
278
279 struct IpHeader *ip = p->ip;
280 struct TcpHeader *tcp = p->tcp;
281
282 char *opt;
283 int optlen;
284 char *ip_opt;
285 int ip_optlen;
286 int i;
287
288 printf("%s.%u > ", InetAddress(ip->ip_src), ntohs(tcp->tcp_sport));
289 printf("%s.%u ", InetAddress(ip->ip_dst), ntohs(tcp->tcp_dport));
290
291 if (tcp->tcp_flags & TCPFLAGS_SYN) {
292 printf("S");
293 }
294
295 if (tcp->tcp_flags & TCPFLAGS_ACK) {
296 printf("A");
297 }
298
299 if (tcp->tcp_flags & TCPFLAGS_FIN) {
300 printf("F");
301 }
302
303 if (tcp->tcp_flags & TCPFLAGS_ECN_ECHO) {
304 printf("E");
305 }
306
307 if (tcp->tcp_flags & TCPFLAGS_CWR) {
308 printf("W");
309 }
310
311 if (tcp->tcp_flags & TCPFLAGS_RST) {
312 printf("R");
313 }
314 if (tcp->tcp_flags & TCPFLAGS_PSH) {
315 printf("P");
316 }
317
318 if (tcp->tcp_flags & TCPFLAGS_URG) {
319 printf("U");
320 }
321
322 if (INSESSION(p,session.src,session.sport,session.dst,session.dport)) {
323 printf(" seq: %u, ack: %u", (uint32)ntohl(tcp->tcp_seq) - session.iss, (uint32)ntohl(tcp->tcp_ack) - session.irs);
324 } else {
325 printf(" seq: %u, ack: %u", (uint32)ntohl(tcp->tcp_seq) - session.irs, (uint32)ntohl(tcp->tcp_ack) - session.iss);
326 }
327
328 /* IP Options */
329 ip_optlen = ((ip->ip_vhl & 0x0f) << 2) - sizeof(struct IpHeader);
330 ip_opt = (char *)ip + sizeof(struct IpHeader);
331
332 i = 0;
333 while (i < ip_optlen) {
334
335 switch ((unsigned char)ip_opt[i]) {
336 case IPOPT_NOP:
337 printf(" ipopt%d: %s ", i + 1, "IPOPT_NOP");
338 i = i + 1;
339 break;
340
341 case IPOPT_EOL:
342 printf(" ipopt%d: %s ", i + 1, "IPOPT_EOL");
343 i = ip_optlen + 1;
344 break;
345
346 case IPOPT_RR:
347 printf(" ipopt%d: %s ", i + 1, "IPOPT_RR");
348 i = i + IPOLEN_RR;
349 break;
350
351 default:
352 printf("ip_opt%d: UNKNOWN ", i + 1);
353 i = i + (uint8)ip_opt[i+1] ;
354 }
355 }
356
357 printf(" win: %u, urg: %u, ttl: %d", ntohs(tcp->tcp_win), ntohs(tcp->tcp_urp), ip->ip_ttl);
358 printf(" datalen: %u, optlen: %u ",
359 ip->ip_len - ((ip->ip_vhl &0x0f) << 2) - (tcp->tcp_hl >> 2),
360 (tcp->tcp_hl >> 2) - (unsigned int)sizeof(struct TcpHeader));
361
362
363 /* TCP Options */
364 optlen = (tcp->tcp_hl >> 2) - (unsigned int)sizeof (struct TcpHeader) ;
365 opt = (char *)tcp + sizeof(struct TcpHeader);
366
367 i = 0 ;
368
369 while (i < optlen) {
370
371 switch ((unsigned char)opt[i]) {
372
373 case TCPOPT_EOL:
374 printf (" opt%d: %s ", i + 1, "TCPOPT_EOL");
375 i = optlen + 1;
376 break ;
377
378 case TCPOPT_NOP:
379 printf (" opt%d: %s ", i + 1, "TCPOPT_NOP");
380 i++ ;
381 break ;
382
383 case TCPOPT_MAXSEG:
384 printf (" opt%d: %s: %d ", i + 1, "TCPOPT_MAXSEG", ntohs(*(uint16 *)((char *)opt+2)));
385 i = i + TCPOLEN_MAXSEG ;
386 break ;
387
388 case TCPOPT_WINDOW:
389 printf (" opt%d: %s ", i + 1, "TCPOPT_WINDOW");
390 i = i + TCPOLEN_WINDOW ;
391 break ;
392
393 case TCPOPT_SACK_PERMITTED:
394 printf (" opt%d: %s ", i + 1, "TCPOPT_SACK_PERMITTED");
395 i = i + TCPOLEN_SACK_PERMITTED ;
396 break ;
397
398 case TCPOPT_TIMESTAMP:
399 printf (" opt%d: %s ", i + 1, "TCPOPT_TIMESTAMP");
400 i = i + TCPOLEN_TIMESTAMP ;
401 break ;
402
403 default:
404 printf (" opt%d c:%d l:%d: UNKNOWN ", i + 1, (uint8)opt[i], (uint8)opt[i+1]);
405 if ((uint8)opt[i+1] > 0) {
406 i = i + (uint8)opt[i+1] ;
407 } else {
408 Quit(20);
409 }
410 break ;
411 }
412 }
413 printf ("\n");
414}
415
416
417struct IPPacket *FindHeaderBoundaries(char *p) {
418
419 struct IPPacket *packet;
420 uint16 ip_hl;
421
422 if ((packet = (struct IPPacket *)calloc(1, sizeof(struct IPPacket))) == NULL) {
423 printf("FindHeaderBoundaries: Cannot allocate memory for read packet\nRETURN CODE: %d\n", ERR_MEM_ALLOC);
424 Quit(ERR_MEM_ALLOC);
425 }
426
427 packet->ip = (struct IpHeader *)p;
428
429 if (packet->ip->ip_p != IPPROTOCOL_TCP) {
430 printf("Error: not a TCP packet\n");
431 Quit(ERR_CHECKSUM);
432 }
433
434 ip_hl = (packet->ip->ip_vhl & 0x0f) << 2;
435
436 packet->tcp = (struct TcpHeader *)((char *)p + ip_hl);
437
438 return packet;
439
440}
441
442
443struct IPPacket *
444AllocateIPPacket(int ip_optlen, int tcp_optlen, int datalen, char *str)
445{
446 struct IPPacket *p;
447
448 if (session.debug == SESSION_DEBUG_HIGH) {
449 printf("In AllocateIPPacket: %s...\n", str);
450 }
451
452 if ((p = (struct IPPacket *)calloc(1, sizeof(struct IPPacket)))
453 == NULL) {
454 printf("%s ERROR: No space for packet\nRETURN CODE: %d",
455 str, ERR_MEM_ALLOC);
456 Quit(ERR_MEM_ALLOC);
457 }
458
459 if ((p->ip = (struct IpHeader *)calloc(1,
460 sizeof(struct IpHeader) + ip_optlen)) == NULL) {
461 printf("%s ERROR: No IpHeader space for packet\n"
462 "RETURN CODE: %d", str, ERR_MEM_ALLOC);
463 Quit(ERR_MEM_ALLOC);
464 }
465
466 if ((p->tcp = (struct TcpHeader *)calloc(1,
467 sizeof(struct TcpHeader) + tcp_optlen + datalen)) == NULL) {
468 printf("%s ERROR: No TcpHeader space for packet\n"
469 "RETURN CODE: %d", str, ERR_MEM_ALLOC);
470 Quit(ERR_MEM_ALLOC);
471 }
472
473 if (session.debug == SESSION_DEBUG_HIGH) {
474 printf("Out of AllocateIPPacket: %s...\n", str);
475 }
476 return(p);
477}
478
479void
480FreeIPPacket(struct IPPacket **pkt_p)
481{
482 struct IPPacket *pkt;
483 if (pkt_p == NULL)
484 return;
485 if ((pkt = *pkt_p) == NULL)
486 return;
487 if (pkt->ip != NULL) {
488 free(pkt->ip);
489 pkt->ip = NULL;
490 }
491 if (pkt->tcp != NULL) {
492 free(pkt->tcp);
493 pkt->tcp = NULL;
494 }
495 free(pkt);
496 *pkt_p = NULL;
497}
498