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
);
194 if (session
.debug
== SESSION_DEBUG_HIGH
) {
195 printf("Out WriteIPPacket...\n");
200 void ReadIPPacket(struct IPPacket
*p
,
215 /* TODO: Add reading of IP options, if any */
217 struct IpHeader
*ip
= p
->ip
;
218 struct TcpHeader
*tcp
= p
->tcp
;
224 /* XXX do checksum check? */
225 if (ip
->ip_p
!= IPPROTOCOL_TCP
&& ip
->ip_p
!= IPPROTOCOL_ICMP
) {
226 printf("Unexpected protocol packet: %u\n", ip
->ip_p
);
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
);
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
);
249 void PrintICMPUnreachableErrorPacket(struct ICMPUnreachableErrorPacket
*p
)
252 struct IpHeader
*ip
= &p
->ip
;
253 struct IcmpHeader
*icmp
= &p
->icmp
;
254 struct IpHeader
*off_ip
= &p
->off_ip
;
257 printf("%s > ", InetAddress(ip
->ip_src
));
258 printf("%s ", InetAddress(ip
->ip_dst
));
259 printf(" datalen: %u\n", ip
->ip_len
);
261 printf("Type: %u Code: %u MTU next hop: %u xsum: %x\n",
264 ntohs(icmp
->icmp_mtu
),
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
));
276 void PrintTcpPacket(struct IPPacket
*p
)
279 struct IpHeader
*ip
= p
->ip
;
280 struct TcpHeader
*tcp
= p
->tcp
;
288 printf("%s.%u > ", InetAddress(ip
->ip_src
), ntohs(tcp
->tcp_sport
));
289 printf("%s.%u ", InetAddress(ip
->ip_dst
), ntohs(tcp
->tcp_dport
));
291 if (tcp
->tcp_flags
& TCPFLAGS_SYN
) {
295 if (tcp
->tcp_flags
& TCPFLAGS_ACK
) {
299 if (tcp
->tcp_flags
& TCPFLAGS_FIN
) {
303 if (tcp
->tcp_flags
& TCPFLAGS_ECN_ECHO
) {
307 if (tcp
->tcp_flags
& TCPFLAGS_CWR
) {
311 if (tcp
->tcp_flags
& TCPFLAGS_RST
) {
314 if (tcp
->tcp_flags
& TCPFLAGS_PSH
) {
318 if (tcp
->tcp_flags
& TCPFLAGS_URG
) {
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
);
325 printf(" seq: %u, ack: %u", (uint32
)ntohl(tcp
->tcp_seq
) - session
.irs
, (uint32
)ntohl(tcp
->tcp_ack
) - session
.iss
);
329 ip_optlen
= ((ip
->ip_vhl
& 0x0f) << 2) - sizeof(struct IpHeader
);
330 ip_opt
= (char *)ip
+ sizeof(struct IpHeader
);
333 while (i
< ip_optlen
) {
335 switch ((unsigned char)ip_opt
[i
]) {
337 printf(" ipopt%d: %s ", i
+ 1, "IPOPT_NOP");
342 printf(" ipopt%d: %s ", i
+ 1, "IPOPT_EOL");
347 printf(" ipopt%d: %s ", i
+ 1, "IPOPT_RR");
352 printf("ip_opt%d: UNKNOWN ", i
+ 1);
353 i
= i
+ (uint8
)ip_opt
[i
+1] ;
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
));
364 optlen
= (tcp
->tcp_hl
>> 2) - (unsigned int)sizeof (struct TcpHeader
) ;
365 opt
= (char *)tcp
+ sizeof(struct TcpHeader
);
371 switch ((unsigned char)opt
[i
]) {
374 printf (" opt%d: %s ", i
+ 1, "TCPOPT_EOL");
379 printf (" opt%d: %s ", i
+ 1, "TCPOPT_NOP");
384 printf (" opt%d: %s: %d ", i
+ 1, "TCPOPT_MAXSEG", ntohs(*(uint16
*)((char *)opt
+2)));
385 i
= i
+ TCPOLEN_MAXSEG
;
389 printf (" opt%d: %s ", i
+ 1, "TCPOPT_WINDOW");
390 i
= i
+ TCPOLEN_WINDOW
;
393 case TCPOPT_SACK_PERMITTED
:
394 printf (" opt%d: %s ", i
+ 1, "TCPOPT_SACK_PERMITTED");
395 i
= i
+ TCPOLEN_SACK_PERMITTED
;
398 case TCPOPT_TIMESTAMP
:
399 printf (" opt%d: %s ", i
+ 1, "TCPOPT_TIMESTAMP");
400 i
= i
+ TCPOLEN_TIMESTAMP
;
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] ;
417 struct IPPacket
*FindHeaderBoundaries(char *p
) {
419 struct IPPacket
*packet
;
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
);
427 packet
->ip
= (struct IpHeader
*)p
;
429 if (packet
->ip
->ip_p
!= IPPROTOCOL_TCP
&&
430 packet
->ip
->ip_p
!= IPPROTOCOL_ICMP
) {
431 printf("Error: Unexpected protocol packet: %u \n", packet
->ip
->ip_p
);
435 ip_hl
= (packet
->ip
->ip_vhl
& 0x0f) << 2;
437 packet
->tcp
= (struct TcpHeader
*)((char *)p
+ ip_hl
);
444 AllocateIPPacket(int ip_optlen
, int tcp_optlen
, int datalen
, char *str
)
448 if (session
.debug
== SESSION_DEBUG_HIGH
) {
449 printf("In AllocateIPPacket: %s...\n", str
);
452 if ((p
= (struct IPPacket
*)calloc(1, sizeof(struct IPPacket
)))
454 printf("%s ERROR: No space for packet\nRETURN CODE: %d",
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
);
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
);
473 if (session
.debug
== SESSION_DEBUG_HIGH
) {
474 printf("Out of AllocateIPPacket: %s...\n", str
);
480 FreeIPPacket(struct IPPacket
**pkt_p
)
482 struct IPPacket
*pkt
;
485 if ((pkt
= *pkt_p
) == NULL
)
487 if (pkt
->ip
!= NULL
) {
491 if (pkt
->tcp
!= NULL
) {