3 International Computer Science Institute
6 This file may contain software code originally developed for the
7 Sting project. The Sting software carries the following copyright:
9 Copyright (c) 1998, 1999
10 Stefan Savage and the University of Washington.
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
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.
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
43 #include <sys/types.h>
44 #include <sys/param.h>
56 extern struct TcpSession session
;
57 extern struct History history
[];
60 * Deal with struct in_addr type agreement once and for all
62 char *InetAddress(uint32 addr
)
68 //printf("In InetAddress:\n");
69 //printf("addr = %s (%0x)\n", inet_ntoa(s), addr);
71 return (inet_ntoa(s
));
75 * Really slow implementation of ip checksum
76 * ripped off from rfc1071
79 uint16
InetChecksum(uint16
*ip
, uint16
*tcp
, uint16 ip_len
, uint16 tcp_len
) {
83 uint32 ip_count
= ip_len
;
84 uint32 tcp_count
= tcp_len
;
86 uint16
*tcp_addr
= tcp
;
88 if (session
.debug
>= SESSION_DEBUG_HIGH
) {
89 printf("In InetChecksum...\n");
90 printf("iplen: %d, tcplen: %d\n", ip_len
, tcp_len
);
95 //printf("ip[%d]: %x\n", ip_len - ip_count, htons(*ip_addr));
100 while(tcp_count
> 1) {
101 //printf("tcp[%d]: %x\n", tcp_len - tcp_count, htons(*tcp_addr));
107 sum
+= *(uint8
*)ip_addr
;
111 sum
+= *(uint8
*)tcp_addr
;
115 sum
= (sum
& 0xffff) + (sum
>> 16);
118 if (session
.debug
>= SESSION_DEBUG_HIGH
) {
119 printf("Out InetChecksum...\n");
127 void WriteIPPacket(struct IPPacket
*p
,
144 struct IpHeader
*ip
= p
->ip
;
145 struct TcpHeader
*tcp
= p
->tcp
;
147 if (session
.debug
>= SESSION_DEBUG_HIGH
) {
148 printf("In WriteIPPacket...\n");
151 /* Zero out IpHeader to ensure proper checksum computation */
152 bzero((char *)(p
->ip
), sizeof(struct IpHeader
));
156 ip
->ip_p
= IPPROTOCOL_TCP
;
158 htons((uint16
)(sizeof(struct TcpHeader
) + datalen
+ optlen
)); /* pseudo hdr */
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
;
168 tcp
->tcp_win
= htons(win
);
169 tcp
->tcp_urp
= htons(urp
);
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
));
176 /* Fill in real ip header */
177 if (session
.curr_ttl
!= 0) {
178 ip
->ip_ttl
= session
.curr_ttl
;
183 //printf("TTL: %d\n", ip->ip_ttl);
187 /* IP Version and Header len field */
188 ip
->ip_vhl
= 0x40 + 0x5 + (int)(ip_optlen
/4);
189 ip
->ip_p
= IPPROTOCOL_TCP
;
192 ip
->ip_len
= (uint16
)(sizeof(struct IpHeader
) + ip_optlen
+ sizeof(struct TcpHeader
) + optlen
+ datalen
);
195 ip
->ip_xsum
= InetChecksum((uint16
*)ip
, NULL
,
196 (uint16
)sizeof(struct IpHeader
) + ip_optlen
, /* IP Options should aren't included */
199 if (session
.debug
>= SESSION_DEBUG_HIGH
) {
200 printf("Out WriteIPPacket...\n");
205 void ReadIPPacket(struct IPPacket
*p
,
220 /* TODO: Add reading of IP options, if any */
222 struct IpHeader
*ip
= p
->ip
;
223 struct TcpHeader
*tcp
= p
->tcp
;
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
);
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
);
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
);
254 void PrintICMPUnreachableErrorPacket(struct ICMPUnreachableErrorPacket
*p
)
257 struct IpHeader
*ip
= &p
->ip
;
258 struct IcmpHeader
*icmp
= &p
->icmp
;
259 struct IpHeader
*off_ip
= &p
->off_ip
;
262 printf("%s > ", InetAddress(ip
->ip_src
));
263 printf("%s ", InetAddress(ip
->ip_dst
));
264 printf(" datalen: %u\n", ip
->ip_len
);
266 printf("Type: %u Code: %u MTU next hop: %u xsum: %x\n",
269 ntohs(icmp
->icmp_mtu
),
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
));
281 void PrintTcpPacket(struct IPPacket
*p
)
284 struct IpHeader
*ip
= p
->ip
;
285 struct TcpHeader
*tcp
= p
->tcp
;
293 printf("%s.%u > ", InetAddress(ip
->ip_src
), ntohs(tcp
->tcp_sport
));
294 printf("%s.%u ", InetAddress(ip
->ip_dst
), ntohs(tcp
->tcp_dport
));
296 if (tcp
->tcp_flags
& TCPFLAGS_SYN
) {
300 if (tcp
->tcp_flags
& TCPFLAGS_ACK
) {
304 if (tcp
->tcp_flags
& TCPFLAGS_FIN
) {
308 if (tcp
->tcp_flags
& TCPFLAGS_ECN_ECHO
) {
312 if (tcp
->tcp_flags
& TCPFLAGS_CWR
) {
316 if (tcp
->tcp_flags
& TCPFLAGS_RST
) {
319 if (tcp
->tcp_flags
& TCPFLAGS_PSH
) {
323 if (tcp
->tcp_flags
& TCPFLAGS_URG
) {
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
);
330 printf(" seq: %u, ack: %u", (uint32
)ntohl(tcp
->tcp_seq
) - session
.irs
, (uint32
)ntohl(tcp
->tcp_ack
) - session
.iss
);
334 ip_optlen
= ((ip
->ip_vhl
& 0x0f) << 2) - sizeof(struct IpHeader
);
335 ip_opt
= (char *)ip
+ sizeof(struct IpHeader
);
338 while (i
< ip_optlen
) {
340 switch ((unsigned char)ip_opt
[i
]) {
342 printf(" ipopt%d: %s ", i
+ 1, "IPOPT_NOP");
347 printf(" ipopt%d: %s ", i
+ 1, "IPOPT_EOL");
352 printf(" ipopt%d: %s ", i
+ 1, "IPOPT_RR");
357 printf("ip_opt%d: UNKNOWN ", i
+ 1);
358 i
= i
+ (uint8
)ip_opt
[i
+1] ;
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
));
369 optlen
= (tcp
->tcp_hl
>> 2) - (unsigned int)sizeof (struct TcpHeader
) ;
370 opt
= (char *)tcp
+ sizeof(struct TcpHeader
);
376 switch ((unsigned char)opt
[i
]) {
379 printf (" opt%d: %s ", i
+ 1, "TCPOPT_EOL");
384 printf (" opt%d: %s ", i
+ 1, "TCPOPT_NOP");
389 printf (" opt%d: %s: %d ", i
+ 1, "TCPOPT_MAXSEG", ntohs(*(uint16
*)((char *)opt
+2)));
390 i
= i
+ TCPOLEN_MAXSEG
;
394 printf (" opt%d: %s ", i
+ 1, "TCPOPT_WINDOW");
395 i
= i
+ TCPOLEN_WINDOW
;
398 case TCPOPT_SACK_PERMITTED
:
399 printf (" opt%d: %s ", i
+ 1, "TCPOPT_SACK_PERMITTED");
400 i
= i
+ TCPOLEN_SACK_PERMITTED
;
403 case TCPOPT_TIMESTAMP
:
404 printf (" opt%d: %s ", i
+ 1, "TCPOPT_TIMESTAMP");
405 i
= i
+ TCPOLEN_TIMESTAMP
;
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] ;
422 struct IPPacket
*FindHeaderBoundaries(char *p
) {
424 struct IPPacket
*packet
;
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
);
432 packet
->ip
= (struct IpHeader
*)p
;
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
);
440 ip_hl
= (packet
->ip
->ip_vhl
& 0x0f) << 2;
442 packet
->tcp
= (struct TcpHeader
*)((char *)p
+ ip_hl
);
449 AllocateIPPacket(int ip_optlen
, int tcp_optlen
, int datalen
, char *str
)
453 if (session
.debug
>= SESSION_DEBUG_HIGH
) {
454 printf("In AllocateIPPacket: %s...\n", str
);
457 if ((p
= (struct IPPacket
*)calloc(1, sizeof(struct IPPacket
)))
459 printf("%s ERROR: No space for packet\nRETURN CODE: %d",
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
);
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
);
478 if (session
.debug
>= SESSION_DEBUG_HIGH
) {
479 printf("Out of AllocateIPPacket: %s...\n", str
);
485 FreeIPPacket(struct IPPacket
**pkt_p
)
487 struct IPPacket
*pkt
;
490 if ((pkt
= *pkt_p
) == NULL
)
492 if (pkt
->ip
!= NULL
) {
496 if (pkt
->tcp
!= NULL
) {