1 /*********************************************************************************
\r
3 * --------------------------------------------------------------------------------
\r
5 * This file is part of MiMic
\r
6 * Copyright (C)2011 Ryo Iizuka
\r
8 * MiMic is free software: you can redistribute it and/or modify
\r
9 * it under the terms of the GNU Lesser General Public License as published
\r
10 * by the Free Software Foundation, either version 3 of the License, or
\r
11 * (at your option) any later version.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 * GNU General Public License for more details.
\r
18 * You should have received a copy of the GNU Lesser General Public License
\r
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
21 * For further information please contact.
\r
23 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
\r
26 * Parts of this file were leveraged from uIP:
\r
28 * Copyright (c) 2001-2003, Adam Dunkels.
\r
29 * All rights reserved.
\r
31 * Redistribution and use in source and binary forms, with or without
\r
32 * modification, are permitted provided that the following conditions
\r
34 * 1. Redistributions of source code must retain the above copyright
\r
35 * notice, this list of conditions and the following disclaimer.
\r
36 * 2. Redistributions in binary form must reproduce the above copyright
\r
37 * notice, this list of conditions and the following disclaimer in the
\r
38 * documentation and/or other materials provided with the distribution.
\r
39 * 3. The name of the author may not be used to endorse or promote
\r
40 * products derived from this software without specific prior
\r
41 * written permission.
\r
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
\r
44 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
45 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\r
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
\r
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
\r
49 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
50 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
\r
51 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
52 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
53 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
55 #include "NyLPC_uip.h"
\r
59 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_ZERO={0x00000000};
\r
60 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_ALL ={0xffffffff};
\r
61 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_BROADCAST = { 0xffffffff };
\r
62 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_MULTICAST = NyLPC_TIPv4Addr_pack(224,0,0,0);
\r
63 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_MULTICAST_MASK = NyLPC_TIPv4Addr_pack(224,0,0,0);
\r
64 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_APIPA_MASK = NyLPC_TIPv4Addr_pack(255,255,0,0);
\r
66 NyLPC_TInt16 NyLPC_TIPv4Addr_toString(const struct NyLPC_TIPv4Addr* i_ip,NyLPC_TChar* i_buf)
\r
69 NyLPC_TChar* p=i_buf;
\r
73 ip=NyLPC_NTOHL(i_ip->v);
\r
95 NyLPC_TUInt16 NyLPC_uip_chksum(NyLPC_TUInt16 sum, const NyLPC_TUInt8 *data, NyLPC_TUInt16 len)
\r
98 const NyLPC_TUInt8 *dataptr;
\r
99 const NyLPC_TUInt8 *last_byte;
\r
102 last_byte = data + len - 1;
\r
104 while (dataptr < last_byte) { /* At least two more bytes */
\r
105 t = (dataptr[0] << 8) + dataptr[1];
\r
113 if (dataptr == last_byte) {
\r
114 t = (dataptr[0] << 8) + 0;
\r
121 /* Return sum in host byte order. */
\r
125 /*--------------------------------------------------------------------------------
\r
127 * struct NyLPC_TEthernetIIHeader
\r
129 *------------------------------------------------------------------------------*/
\r
132 * Ethernetヘッダの内容を、ARPパケットの内容に一致するように書き換えます。
\r
133 * i_structの後方にあるものと仮定します。
\r
136 NyLPC_TUInt16 NyLPC_TEthernetIIHeader_setArpTx(
\r
137 struct NyLPC_TEthernetIIHeader* i_struct,
\r
138 const struct NyLPC_TEthAddr* i_my_eth_addr)
\r
140 struct NyLPC_TArpHeader* arph=(struct NyLPC_TArpHeader*)(((NyLPC_TUInt8*)i_struct)+sizeof(struct NyLPC_TEthernetIIHeader));
\r
142 i_struct->type = NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_ARP);
\r
143 switch(arph->opcode){
\r
144 case NyLPC_HTONS(ARP_REPLY):
\r
145 memcpy(i_struct->src.addr, i_my_eth_addr->addr, 6);
\r
146 memcpy(i_struct->dest.addr, arph->dhwaddr.addr, 6);
\r
148 case NyLPC_HTONS(ARP_REQUEST):
\r
149 memset(i_struct->dest.addr, 0xff, 6);
\r
150 memcpy(i_struct->src.addr, i_my_eth_addr->addr, 6);
\r
153 return sizeof(struct NyLPC_TEthernetIIHeader)+sizeof(struct NyLPC_TArpHeader);
\r
157 * イーサネットヘッダをIPv4向けにセットアップする。
\r
158 * 関数は、ペイロードをIPv4ヘッダとして、フレームサイズを計算する。
\r
160 NyLPC_TUInt16 NyLPC_TEthernetIIHeader_setIPv4Tx(
\r
161 struct NyLPC_TEthernetIIHeader* i_eth,
\r
162 const struct NyLPC_TEthAddr* i_src_eth_addr,
\r
163 const struct NyLPC_TEthAddr* i_dest_eth_addr)
\r
165 struct NyLPC_TIPv4Header* iph=(struct NyLPC_TIPv4Header*)(((NyLPC_TUInt8*)i_eth)+sizeof(struct NyLPC_TEthernetIIHeader));
\r
167 i_eth->type = NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IP);
\r
168 /* Build an ethernet header. */
\r
169 memcpy(i_eth->dest.addr,i_dest_eth_addr, 6);
\r
170 memcpy(i_eth->src.addr, i_src_eth_addr->addr, 6);
\r
173 //IPフラグメントに応じたサイズ計算
\r
174 switch(iph->proto){
\r
175 case UIP_PROTO_TCP:
\r
176 return sizeof(struct NyLPC_TEthernetIIHeader)+NyLPC_htons(iph->len16);
\r
177 case UIP_PROTO_UDP:
\r
178 return sizeof(struct NyLPC_TEthernetIIHeader)+NyLPC_htons(iph->len16);
\r
179 case UIP_PROTO_ICMP:
\r
180 return sizeof(struct NyLPC_TEthernetIIHeader)+NyLPC_htons(iph->len16);
\r
184 /*--------------------------------------------------------------------------------
\r
186 * struct NyLPC_TIPv4Header
\r
188 *------------------------------------------------------------------------------*/
\r
191 * based on uip_ipchksum
\r
193 NyLPC_TUInt16 NyLPC_TIPv4Header_makeIpChecksum(const struct NyLPC_TIPv4Header* ip_header)
\r
196 sum = NyLPC_uip_chksum(0, (const NyLPC_TUInt8 *)ip_header,NyLPC_TIPv4Header_getHeaderLength(ip_header));
\r
197 return (sum == 0) ? 0xffff : NyLPC_htons(sum);
\r
202 NyLPC_TBool NyLPC_TIPv4Header_isCorrectIpCheckSum(const struct NyLPC_TIPv4Header* ip_header)
\r
204 return (NyLPC_TIPv4Header_makeIpChecksum(ip_header)==0xffff);
\r
207 NyLPC_TBool NyLPC_cIPv4Packet_isCorrectTcpCheckSum(const struct NyLPC_TIPv4Header* ip_header)
\r
209 return (NyLPC_TIPv4Header_makeTcpChecksum(ip_header) == 0xffff);
\r
217 * ペイロードはIPヘッダの後方に連続して存在する物と仮定します。
\r
220 NyLPC_TUInt16 NyLPC_TIPv4Header_makeTcpChecksum(
\r
221 const struct NyLPC_TIPv4Header* i_iph)
\r
224 NyLPC_TUInt16 iph_len=NyLPC_TIPv4Header_getHeaderLength(i_iph);
\r
225 NyLPC_TUInt16 len = NyLPC_ntohs((i_iph)->len16)- iph_len;
\r
226 NyLPC_ArgAssert(i_iph!=NULL);
\r
228 /* IP protocol and length fields. This addition cannot carry. */
\r
229 sum = len + i_iph->proto;
\r
230 /* Sum IP source and destination addresses. */
\r
231 sum = NyLPC_uip_chksum(sum, (NyLPC_TUInt8 *) &(i_iph->srcipaddr), 2 * sizeof(struct NyLPC_TIPv4Addr));
\r
232 /* Sum TCP header and data. */
\r
233 sum = NyLPC_uip_chksum(sum, (((NyLPC_TUInt8 *)(i_iph))+iph_len),len);
\r
234 // sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], i_len_of_data);
\r
235 return (sum == 0) ? 0xffff : NyLPC_htons(sum);
\r
238 static NyLPC_TUInt16 pid=0x3939;
\r
240 * IPヘッダを送信パケット用に設定する。
\r
241 * ipid16にはコールされるたびに新しい値を設定する。
\r
242 * ipcecksumには0を設定する。
\r
243 * この関数は、パケットサイズ,ローカルIP/リモートIPの設定はしない。
\r
245 void NyLPC_TIPv4Header_writeTxIpHeader(
\r
246 struct NyLPC_TIPv4Header* i_struct,
\r
247 NyLPC_TUInt8 i_proto)
\r
250 i_struct->proto=i_proto;
\r
251 i_struct->ttl = UIP_DEFAULT_IP_TTL;
\r
253 i_struct->ipid16=(pid++);
\r
254 i_struct->ipoffset=0;//NyLPC_HTONS(0|0x4000);
\r
255 i_struct->ipchksum = 0;
\r
257 /*--------------------------------------------------------------------------------
\r
259 * struct NyLPC_TIPv6Header
\r
261 *------------------------------------------------------------------------------*/
\r
262 #define IPV6_HEADER_SIZE 40
\r
266 void NyLPC_TIPv6Header_setSendHeader(
\r
267 struct NyLPC_TIPv6Header* i_iph,
\r
268 uip_ip6addr_t i_src,
\r
269 uip_ip6addr_t i_dest,
\r
270 NyLPC_TUInt8 i_proto,
\r
271 NyLPC_TUInt8 i_ttl,
\r
272 NyLPC_TUInt16 i_len)
\r
274 i_iph->srcipaddr=i_src;
\r
275 i_iph->destipaddr=i_dest;
\r
276 i_iph->proto=i_proto;
\r
277 i_iph->ttl = i_ttl;
\r
279 i_iph->tcflow = 0x00;
\r
280 i_iph->flow = 0x00;
\r
281 i_iph->len16= NyLPC_htons(i_len - IPV6_HEADER_SIZE);
\r
287 * チェックサムは、TCP疑似ヘッダから計算。
\r
288 * i_tcpiphの送信/受信アドレス、ProtocolID,DATAフィールドは有効であること。
\r
290 NyLPC_TUInt16 NyLPC_TIPv6Header_makeTcpChecksum(
\r
291 struct NyLPC_TIPv6Header* i_iph,
\r
292 NyLPC_TUInt16 i_len)
\r
298 /* IP protocol and length fields. This addition cannot carry. */
\r
299 sum = len + i_iph->proto;
\r
300 /* Sum IP source and destination addresses. */
\r
301 sum = NyLPC_uip_chksum(sum, (NyLPC_TUInt8 *) &(i_iph->srcipaddr), 2 * sizeof(uip_ip6addr_t));
\r
302 /* Sum TCP header and data. */
\r
303 sum = NyLPC_uip_chksum(sum, (((NyLPC_TUInt8 *)(i_iph))+IPV6_HEADER_SIZE),len);
\r
304 // sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], i_len_of_data);
\r
305 return (sum == 0) ? 0xffff : NyLPC_htons(sum);
\r
310 /*--------------------------------------------------------------------------------
\r
312 * struct NyLPC_TTcpHeader
\r
314 *------------------------------------------------------------------------------*/
\r
320 NyLPC_TBool NyLPC_TTcpHeader_getTcpMmsOpt(
\r
321 const struct NyLPC_TTcpHeader* i_struct,NyLPC_TUInt16* o_val)
\r
324 opt=NyLPC_TTcpHeader_getTcpOptFragmentPtr(i_struct,TCP_OPT_MSS);
\r
326 if (*(opt+1) == TCP_OPT_MSS_LEN)
\r
328 // An MSS option with the right option length.
\r
329 *o_val = ((NyLPC_TUInt16) (*(opt+2)) << 8) | (NyLPC_TUInt16) (*(opt + 3));
\r
330 //And we are done processing options.
\r
331 return NyLPC_TBool_TRUE;
\r
334 return NyLPC_TBool_FALSE;
\r
337 #define DEFAULT_TCP_HEADER_LEN 20
\r
339 * TCPフラグメントのポインタを返す。
\r
341 NyLPC_TUInt8* NyLPC_TTcpHeader_getTcpOptFragmentPtr(
\r
342 const struct NyLPC_TTcpHeader* i_struct,
\r
343 NyLPC_TUInt8 i_opt_id)
\r
347 NyLPC_TUInt8* opt_buf=((NyLPC_TUInt8*)(i_struct+1));
\r
349 /* Parse the TCP MSS option, if present. */
\r
350 if ((i_struct->tcpoffset & 0xf0) > 0x50){
\r
351 for (c = 0; c < ((i_struct->tcpoffset >> 4) - 5) << 2;)
\r
355 return opt_buf+c;//found!
\r
360 continue;//NOP option.
\r
362 return NULL;//End of options.
\r
364 // All other options have a length field, so that we easily can skip past them.
\r
365 if (opt_buf[1 + c] == 0) {
\r
366 // If the length field is zero, the options are malformed and we don't process them further.
\r
367 NyLPC_OnErrorGoto(ERROR_INVALID_OPTION);
\r
369 c += opt_buf[1 + c];
\r
373 ERROR_INVALID_OPTION:
\r
379 void NyLPC_TTcpHeader_setMmsOpt(NyLPC_TUInt8* i_opt_addr,NyLPC_TUInt16 i_mms)
\r
381 i_opt_addr[0] = TCP_OPT_MSS;
\r
382 i_opt_addr[1] = TCP_OPT_MSS_LEN;
\r
383 i_opt_addr[2] = (i_mms) / 256;
\r
384 i_opt_addr[3] = (i_mms) & 255;
\r
389 NyLPC_TUInt16 NyLPC_TTcpHeader_getHeaderLength(const struct NyLPC_TTcpHeader* ip_header)
\r
391 return (ip_header->tcpoffset>>4)*4;
\r
393 /*--------------------------------------------------------------------------------
\r
395 * struct NyLPC_TUdpHeader
\r
397 *------------------------------------------------------------------------------*/
\r
401 /*--------------------------------------------------------------------------------
\r
403 * struct NyLPC_TArpHeader
\r
405 *------------------------------------------------------------------------------*/
\r
407 * i_req_addrを問い合わせるARP_REQUESTを生成します。
\r
409 void NyLPC_TArpHeader_setArpRequest(
\r
410 struct NyLPC_TArpHeader* i_struct,
\r
411 const struct NyLPC_TIPv4Addr i_saddr,
\r
412 const struct NyLPC_TEthAddr* i_srceth,
\r
413 const struct NyLPC_TIPv4Addr* i_req_addr)
\r
415 memset(i_struct->dhwaddr.addr, 0x00, 6);
\r
416 memcpy(i_struct->shwaddr.addr, i_srceth, 6);
\r
417 i_struct->dipaddr=*i_req_addr;
\r
418 i_struct->sipaddr=i_saddr;
\r
419 i_struct->opcode = NyLPC_HTONS(ARP_REQUEST); /* ARP request. */
\r
420 i_struct->hwtype = NyLPC_HTONS(ARP_HWTYPE_ETH);
\r
421 i_struct->protocol = NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IP);
\r
422 i_struct->hwlen = 6;
\r
423 i_struct->protolen = 4;
\r
427 /*--------------------------------------------------------------------------------
\r
431 *------------------------------------------------------------------------------*/
\r