Fixed buffer overflow in mserver; fixed type of checkinfo () 2nd parameter; memory
[ZeXOS.git] / kernel / core / net / checksum.c
blob53b22169d6654c930633593e16e2c66d15a6a4aa
1 /*
2 * ZeX/OS
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/>.
20 #include <system.h>
21 #include <string.h>
22 #include <net/if.h>
23 #include <net/eth.h>
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;
32 while (len >= 2) {
33 sum += *buf ++;
35 if (sum & 0x80000000)
36 sum = (sum & 0xffff) + (sum >> 16);
38 len -= 2;
41 if (len) {
42 unsigned char temp[2];
44 temp[0] = *(unsigned char *) buf;
45 temp[1] = 0;
47 sum += *(unsigned short *) temp;
50 while (sum >> 16)
51 sum = (sum & 0xffff) + (sum >> 16);
53 return sum;
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)
63 unsigned sum;
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 {
72 unsigned ip_source;
73 unsigned ip_dest;
74 unsigned char zero;
75 unsigned char proto;
76 unsigned short tcp_len;
77 } proto_tcp_pseudo_t;
79 unsigned short checksum16_tcp (unsigned ip_source, unsigned ip_dest, char *buf, unsigned short len)
81 char *buf_pseudo = (char *) &buf_prealloc;
83 if (!buf_pseudo)
84 return 0;
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);
91 pseudo->proto = 0x6;
92 pseudo->zero = 0x0;
94 memcpy (buf_pseudo+12, buf, len);
96 buf_pseudo[len+12] = '\0';
98 unsigned short ret = checksum16 (buf_pseudo, len+12);
100 return ret;
103 unsigned short checksum16_udp (unsigned ip_source, unsigned ip_dest, char *buf, unsigned short len)
105 char *buf_pseudo = (char *) &buf_prealloc;
107 if (!buf_pseudo)
108 return 0;
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;
116 pseudo->zero = 0x0;
118 memcpy (buf_pseudo+12, buf, len);
120 buf_pseudo[len+12] = '\0';
122 unsigned short ret = checksum16 (buf_pseudo, len+12);
124 return ret;
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];
131 unsigned pl_len;
132 unsigned zero:24;
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;
140 if (!buf_pseudo)
141 return 0;
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);
149 pseudo->zero = 0x0;
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);
162 return ret;