1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
$NetBSD: patch-ak,v 1.1 2006/01/08 11:02:10 wiz Exp $
--- sn_packets.c.orig 1997-04-18 11:33:58.000000000 +0200
+++ sn_packets.c
@@ -43,6 +43,7 @@ int unwrap_packet (unsigned char *sp, st
struct UDP_header UDPhead;
int i;
+ short int dummy; /* 2 bytes, important */
memcpy(&IPhead,(sp+PROTO_HEAD),sizeof(struct IP_header));
/* IP header Conversion */
@@ -51,6 +52,7 @@ int unwrap_packet (unsigned char *sp, st
unwrapped->TCP_len = 0; /* Reset structure NEEDED!!! */
unwrapped->UDP_len = 0;
unwrapped->DATA_len = 0;
+ unwrapped->FRAG_nf = 0;
if(NO_CHKSUM == 0)
{
@@ -75,32 +77,74 @@ int unwrap_packet (unsigned char *sp, st
/* restore orig buffer */
/* general programming rule */
}
+
+#ifdef DEBUG_ONSCREEN
+ printf("IPheadlen: %d total length: %d\n", unwrapped->IP_len,
+ ntohs(IPhead.length));
+#endif
+
+ dummy=ntohs(IPhead.flag_offset); dummy<<=3;
+ if( dummy!=0 ) /* we have offset */
+ {
+ unwrapped->FRAG_nf = 1;
+ }
+
if(IPhead.protocol == TCP ) /* TCP */
{
- memcpy(&TCPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
+ if(unwrapped->FRAG_nf == 0)
+ {
+ if( (ntohs(IPhead.length)-(unwrapped->IP_len))<20 )
+ {return CORRUPT_IP;};
+
+ memcpy(&TCPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
sizeof(struct TCP_header));
- unwrapped->TCP_len = ntohs(TCPhead.offset_flag) & 0xF000;
- unwrapped->TCP_len >>= 10;
- unwrapped->DATA_len = ntohs(IPhead.length) -
+ unwrapped->TCP_len = ntohs(TCPhead.offset_flag) & 0xF000;
+ unwrapped->TCP_len >>= 10;
+ unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len) - (unwrapped->TCP_len);
+ }
+ else
+ {
+ unwrapped->DATA_len = ntohs(IPhead.length) - (unwrapped->IP_len);
+ }
return TCP;
}
if(IPhead.protocol == ICMP ) /* ICMP */
{
- memcpy(&ICMPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
+ if(unwrapped->FRAG_nf == 0)
+ {
+ if( (ntohs(IPhead.length)-(unwrapped->IP_len))<4 )
+ {return CORRUPT_IP;};
+
+ memcpy(&ICMPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
sizeof(struct ICMP_header));
- unwrapped->ICMP_len = ICMP_HEADLENGTH;
- unwrapped->DATA_len = ntohs(IPhead.length) -
+ unwrapped->ICMP_len = ICMP_HEADLENGTH;
+ unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len) - (unwrapped->ICMP_len);
- return ICMP;
+ return ICMP;
+ }
+ else
+ {
+ return -1; /* don't handle fragmented ICMP */
+ }
}
if(IPhead.protocol == UDP ) /* UDP */
{
- memcpy(&UDPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
+ if(unwrapped->FRAG_nf == 0)
+ {
+ if( (ntohs(IPhead.length)-(unwrapped->IP_len))<8 )
+ {return CORRUPT_IP;};
+
+ memcpy(&UDPhead,(sp+PROTO_HEAD+(unwrapped->IP_len)),
sizeof(struct UDP_header));
- unwrapped->UDP_len = UDP_HEADLENGTH;
- unwrapped->DATA_len = ntohs(IPhead.length) -
+ unwrapped->UDP_len = UDP_HEADLENGTH;
+ unwrapped->DATA_len = ntohs(IPhead.length) -
(unwrapped->IP_len) - (unwrapped->UDP_len);
+ }
+ else
+ {
+ unwrapped->DATA_len = ntohs(IPhead.length)-(unwrapped->IP_len);
+ }
return UDP;
}
return -1;
|