3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <net/packet.h>
26 static char buf_prealloc
[NET_PACKET_MTU
+ 64];
28 unsigned short checksum16_ones (unsigned sum
, const void *_buf
, int len
)
30 const unsigned short *buf
= _buf
;
36 sum
= (sum
& 0xffff) + (sum
>> 16);
42 unsigned char temp
[2];
44 temp
[0] = *(unsigned char *) buf
;
47 sum
+= *(unsigned short *) temp
;
51 sum
= (sum
& 0xffff) + (sum
>> 16);
56 unsigned short checksum16 (void *_buf
, int len
)
58 return ~checksum16_ones (0, _buf
, len
);
61 unsigned short checksum16_2 (void *buf1
, int len1
, void *buf2
, int len2
)
65 sum
= checksum16_ones (0, buf1
, len1
);
67 return ~checksum16_ones (sum
, buf2
, len2
);
70 /* pseudo-header for tcp checksum */
71 typedef struct proto_tcp_pseudo_t
{
76 unsigned short tcp_len
;
79 unsigned short checksum16_tcp (unsigned ip_source
, unsigned ip_dest
, char *buf
, unsigned short len
)
81 char *buf_pseudo
= (char *) &buf_prealloc
;
86 proto_tcp_pseudo_t
*pseudo
= (proto_tcp_pseudo_t
*) buf_pseudo
;
88 pseudo
->ip_source
= ip_source
;
89 pseudo
->ip_dest
= ip_dest
;
90 pseudo
->tcp_len
= swap16 (len
);
94 memcpy (buf_pseudo
+12, buf
, len
);
96 buf_pseudo
[len
+12] = '\0';
98 unsigned short ret
= checksum16 (buf_pseudo
, len
+12);
103 unsigned short checksum16_udp (unsigned ip_source
, unsigned ip_dest
, char *buf
, unsigned short len
)
105 char *buf_pseudo
= (char *) &buf_prealloc
;
110 proto_tcp_pseudo_t
*pseudo
= (proto_tcp_pseudo_t
*) buf_pseudo
;
112 pseudo
->ip_source
= ip_source
;
113 pseudo
->ip_dest
= ip_dest
;
114 pseudo
->tcp_len
= swap16 (len
);
115 pseudo
->proto
= 0x11;
118 memcpy (buf_pseudo
+12, buf
, len
);
120 buf_pseudo
[len
+12] = '\0';
122 unsigned short ret
= checksum16 (buf_pseudo
, len
+12);
127 /* pseudo-header for icmp6 checksum */
128 typedef struct proto_ipv6_pseudo_t
{
129 unsigned short ip_source
[8];
130 unsigned short ip_dest
[8];
133 unsigned char next_head
;
134 } proto_ipv6_pseudo_t
;
136 unsigned short checksum16_ipv6 (unsigned short ip_source
[8], unsigned short ip_dest
[8], char *buf
, unsigned len
, unsigned char proto
)
138 char *buf_pseudo
= (char *) &buf_prealloc
;
143 proto_ipv6_pseudo_t
*pseudo
= (proto_ipv6_pseudo_t
*) buf_pseudo
;
145 memcpy (pseudo
->ip_source
, ip_source
, 16);
146 memcpy (pseudo
->ip_dest
, ip_dest
, 16);
148 pseudo
->pl_len
= swap32 (len
);
150 pseudo
->next_head
= proto
;
152 //printf ("ipv6 source -> %x:%x:::\n", swap16 (pseudo->ip_source[0]), swap16 (pseudo->ip_source[1]));
153 //printf ("ipv6 dest -> %x:%x:::\n", swap16 (pseudo->ip_dest[0]), swap16 (pseudo->ip_dest[1]));
154 //printf ("proto_ipv6_pseudo_t size: %d\n", sizeof (proto_ipv6_pseudo_t));
156 memcpy (buf_pseudo
+40, buf
, len
);
158 buf_pseudo
[len
+40] = '\0';
160 unsigned short ret
= checksum16 (buf_pseudo
, len
+40);