This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NyLPC_NetIf_ip_types.c Source File

NyLPC_NetIf_ip_types.c

00001 /*********************************************************************************
00002  * PROJECT: MiMic
00003  * --------------------------------------------------------------------------------
00004  *
00005  * This file is part of MiMic
00006  * Copyright (C)2011 Ryo Iizuka
00007  *
00008  * MiMic is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU Lesser General Public License as published
00010  * by the Free Software Foundation, either version 3 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public License
00019  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020  *
00021  * For further information please contact.
00022  *  http://nyatla.jp/
00023  *  <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
00024  *
00025  *
00026  * Parts of this file were leveraged from uIP:
00027  *
00028  * Copyright (c) 2001-2003, Adam Dunkels.
00029  * All rights reserved.
00030  *
00031  * Redistribution and use in source and binary forms, with or without
00032  * modification, are permitted provided that the following conditions
00033  * are met:
00034  * 1. Redistributions of source code must retain the above copyright
00035  *    notice, this list of conditions and the following disclaimer.
00036  * 2. Redistributions in binary form must reproduce the above copyright
00037  *    notice, this list of conditions and the following disclaimer in the
00038  *    documentation and/or other materials provided with the distribution.
00039  * 3. The name of the author may not be used to endorse or promote
00040  *    products derived from this software without specific prior
00041  *    written permission.
00042  *
00043  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00044  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00045  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00046  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00047  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00048  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00049  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00050  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00051  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00052  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00053  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00054  */
00055 #include "NyLPC_NetIf_ip_types.h"
00056 
00057 
00058 
00059 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_ZERO={0x00000000};
00060 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_ALL ={0xffffffff};
00061 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_BROADCAST = { 0xffffffff };
00062 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_MULTICAST = NyLPC_TIPv4Addr_pack(224,0,0,0);
00063 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_MULTICAST_MASK = NyLPC_TIPv4Addr_pack(224,0,0,0);
00064 const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_APIPA_MASK = NyLPC_TIPv4Addr_pack(255,255,0,0);
00065 
00066 NyLPC_TInt16 NyLPC_TIPv4Addr_toString(const struct NyLPC_TIPv4Addr* i_ip,NyLPC_TChar* i_buf)
00067 {
00068     NyLPC_TUInt32 ip;
00069     NyLPC_TChar* p=i_buf;
00070     NyLPC_TUInt8 v;
00071     NyLPC_TInt8 l;
00072     //IPをホストオーダーにする。
00073     ip=NyLPC_NTOHL(i_ip->v);
00074     for(l=3;l>=0;l--){
00075         v=(ip>>(8*l))&0xff;
00076         if(v>=100){
00077             *p=(v/100)+'0';
00078             p++;
00079         }
00080         if(v>=10){
00081             *p=((v%100)/10)+'0';
00082             p++;
00083         }
00084         *p=(v%10)+'0';
00085         *(p+1)='.';
00086         p+=2;
00087     }
00088     *(p-1)='\0';
00089     return p-i_buf-1;
00090 }
00091 
00092 
00093 NyLPC_TUInt16 NyLPC_uip_chksum(NyLPC_TUInt16 sum, const NyLPC_TUInt8 *data, NyLPC_TUInt16 len)
00094 {
00095     NyLPC_TUInt16 t;
00096     const NyLPC_TUInt8 *dataptr;
00097     const NyLPC_TUInt8 *last_byte;
00098 
00099     dataptr = data;
00100     last_byte = data + len - 1;
00101 
00102     while (dataptr < last_byte) { /* At least two more bytes */
00103         t = (dataptr[0] << 8) + dataptr[1];
00104         sum += t;
00105         if (sum < t) {
00106             sum++; /* carry */
00107         }
00108         dataptr += 2;
00109     }
00110 
00111     if (dataptr == last_byte) {
00112         t = (dataptr[0] << 8) + 0;
00113         sum += t;
00114         if (sum < t) {
00115             sum++; /* carry */
00116         }
00117     }
00118 
00119     /* Return sum in host byte order. */
00120     return sum;
00121 }
00122 
00123 /*--------------------------------------------------------------------------------
00124  *
00125  * struct NyLPC_TEthernetIIHeader
00126  *
00127  *------------------------------------------------------------------------------*/
00128 
00129 /**
00130  * Ethernetヘッダの内容を、ARPパケットの内容に一致するように書き換えます。
00131  * i_structの後方にあるものと仮定します。
00132  * 戻り値は、フレームの長さです。
00133  */
00134 NyLPC_TUInt16 NyLPC_TEthernetIIHeader_setArpTx(
00135     struct NyLPC_TEthernetIIHeader* i_struct,
00136     const struct NyLPC_TEthAddr* i_my_eth_addr)
00137 {
00138     struct NyLPC_TArpHeader* arph=(struct NyLPC_TArpHeader*)(((NyLPC_TUInt8*)i_struct)+sizeof(struct NyLPC_TEthernetIIHeader));
00139 
00140     i_struct->type = NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_ARP);
00141     switch(arph->opcode){
00142     case NyLPC_HTONS(ARP_REPLY):
00143         memcpy(i_struct->src.addr, i_my_eth_addr->addr, 6);
00144         memcpy(i_struct->dest.addr, arph->dhwaddr.addr, 6);
00145         break;
00146     case NyLPC_HTONS(ARP_REQUEST):
00147         memset(i_struct->dest.addr, 0xff, 6);
00148         memcpy(i_struct->src.addr, i_my_eth_addr->addr, 6);
00149         break;
00150     }
00151     return sizeof(struct NyLPC_TEthernetIIHeader)+sizeof(struct NyLPC_TArpHeader);
00152 }
00153 
00154 /**
00155  * イーサネットヘッダをIPv4向けにセットアップする。
00156  * 関数は、ペイロードをIPv4ヘッダとして、フレームサイズを計算する。
00157  */
00158 NyLPC_TUInt16 NyLPC_TEthernetIIHeader_setIPv4Tx(
00159     struct NyLPC_TEthernetIIHeader* i_eth,
00160     const struct NyLPC_TEthAddr* i_src_eth_addr,
00161     const struct NyLPC_TEthAddr* i_dest_eth_addr)
00162 {
00163     struct NyLPC_TIPv4Header* iph=(struct NyLPC_TIPv4Header*)(((NyLPC_TUInt8*)i_eth)+sizeof(struct NyLPC_TEthernetIIHeader));
00164 
00165     i_eth->type = NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IP);
00166     /* Build an ethernet header. */
00167     memcpy(i_eth->dest.addr,i_dest_eth_addr, 6);
00168     memcpy(i_eth->src.addr, i_src_eth_addr->addr, 6);
00169 
00170 
00171     //IPフラグメントに応じたサイズ計算
00172     switch(iph->proto){
00173     case UIP_PROTO_TCP:
00174         return sizeof(struct NyLPC_TEthernetIIHeader)+NyLPC_htons(iph->len16);
00175     case UIP_PROTO_UDP:
00176         return sizeof(struct NyLPC_TEthernetIIHeader)+NyLPC_htons(iph->len16);
00177     case UIP_PROTO_ICMP:
00178         return sizeof(struct NyLPC_TEthernetIIHeader)+NyLPC_htons(iph->len16);
00179     }
00180     return 0;
00181 }
00182 /*--------------------------------------------------------------------------------
00183  *
00184  * struct NyLPC_TIPv4Header
00185  *
00186  *------------------------------------------------------------------------------*/
00187 
00188 /**
00189  * based on uip_ipchksum
00190  */
00191 NyLPC_TUInt16 NyLPC_TIPv4Header_makeIpChecksum(const struct NyLPC_TIPv4Header* ip_header)
00192 {
00193     NyLPC_TUInt16 sum;
00194     sum = NyLPC_uip_chksum(0, (const NyLPC_TUInt8 *)ip_header,NyLPC_TIPv4Header_getHeaderLength(ip_header));
00195     return (sum == 0) ? 0xffff : NyLPC_htons(sum);
00196 }
00197 
00198 
00199 
00200 NyLPC_TBool NyLPC_TIPv4Header_isCorrectIpCheckSum(const struct NyLPC_TIPv4Header* ip_header)
00201 {
00202     return (NyLPC_TIPv4Header_makeIpChecksum(ip_header)==0xffff);
00203 }
00204 
00205 NyLPC_TBool NyLPC_cIPv4Packet_isCorrectTcpCheckSum(const struct NyLPC_TIPv4Header* ip_header)
00206 {
00207     return (NyLPC_TIPv4Header_makeTcpChecksum(ip_header) == 0xffff);
00208 }
00209 
00210 
00211 
00212 
00213 /**
00214  * TCPチェックサムを計算します。
00215  * ペイロードはIPヘッダの後方に連続して存在する物と仮定します。
00216  * i_lenは、ペイロード長さ
00217  */
00218 NyLPC_TUInt16 NyLPC_TIPv4Header_makeTcpChecksum(
00219     const struct NyLPC_TIPv4Header* i_iph)
00220 {
00221     NyLPC_TUInt16 sum;
00222     NyLPC_TUInt16 iph_len=NyLPC_TIPv4Header_getHeaderLength(i_iph);
00223     NyLPC_TUInt16 len = NyLPC_ntohs((i_iph)->len16)- iph_len;
00224     NyLPC_ArgAssert(i_iph!=NULL);
00225     /*TCP疑似ヘッダ部分*/
00226     /* IP protocol and length fields. This addition cannot carry. */
00227     sum = len + i_iph->proto;
00228     /* Sum IP source and destination addresses. */
00229     sum = NyLPC_uip_chksum(sum, (NyLPC_TUInt8 *) &(i_iph->srcipaddr), 2 * sizeof(struct NyLPC_TIPv4Addr));
00230     /* Sum TCP header and data. */
00231     sum = NyLPC_uip_chksum(sum, (((NyLPC_TUInt8 *)(i_iph))+iph_len),len);
00232     //  sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], i_len_of_data);
00233     return (sum == 0) ? 0xffff : NyLPC_htons(sum);
00234 }
00235 
00236 static  NyLPC_TUInt16 pid=0x3939;
00237 /**
00238  * IPヘッダを送信パケット用に設定する。
00239  * ipid16にはコールされるたびに新しい値を設定する。
00240  * ipcecksumには0を設定する。
00241  * この関数は、パケットサイズ,ローカルIP/リモートIPの設定はしない。
00242  */
00243 void NyLPC_TIPv4Header_writeTxIpHeader(
00244     struct NyLPC_TIPv4Header* i_struct,
00245     NyLPC_TUInt8 i_proto)
00246 {
00247     //IPパケットのセット
00248     i_struct->proto=i_proto;
00249     i_struct->ttl = UIP_DEFAULT_IP_TTL;
00250     i_struct->tos = 0;
00251     i_struct->ipid16=(pid++);
00252     i_struct->ipoffset=0;//NyLPC_HTONS(0|0x4000);
00253     i_struct->ipchksum = 0;
00254 }
00255 /*--------------------------------------------------------------------------------
00256  *
00257  * struct NyLPC_TIPv6Header
00258  *
00259  *------------------------------------------------------------------------------*/
00260 #define IPV6_HEADER_SIZE 40
00261 /**
00262  * IPヘッダーを作って埋める関数
00263  */
00264 void NyLPC_TIPv6Header_setSendHeader(
00265     struct NyLPC_TIPv6Header* i_iph,
00266     uip_ip6addr_t i_src,
00267     uip_ip6addr_t i_dest,
00268     NyLPC_TUInt8 i_proto,
00269     NyLPC_TUInt8 i_ttl,
00270     NyLPC_TUInt16 i_len)
00271 {
00272     i_iph->srcipaddr=i_src;
00273     i_iph->destipaddr=i_dest;
00274     i_iph->proto=i_proto;
00275     i_iph->ttl = i_ttl;
00276     i_iph->vtc = 0x60;
00277     i_iph->tcflow = 0x00;
00278     i_iph->flow = 0x00;
00279     i_iph->len16= NyLPC_htons(i_len - IPV6_HEADER_SIZE);
00280     return;
00281 }
00282 
00283 
00284 /**
00285  * チェックサムは、TCP疑似ヘッダから計算。
00286  * i_tcpiphの送信/受信アドレス、ProtocolID,DATAフィールドは有効であること。
00287  */
00288 NyLPC_TUInt16 NyLPC_TIPv6Header_makeTcpChecksum(
00289     struct NyLPC_TIPv6Header* i_iph,
00290     NyLPC_TUInt16 i_len)
00291 {
00292     NyLPC_TUInt16 sum;
00293     NyLPC_TUInt16 len;
00294     len = i_len;
00295     /*TCP疑似ヘッダ部分*/
00296     /* IP protocol and length fields. This addition cannot carry. */
00297     sum = len + i_iph->proto;
00298     /* Sum IP source and destination addresses. */
00299     sum = NyLPC_uip_chksum(sum, (NyLPC_TUInt8 *) &(i_iph->srcipaddr), 2 * sizeof(uip_ip6addr_t));
00300     /* Sum TCP header and data. */
00301     sum = NyLPC_uip_chksum(sum, (((NyLPC_TUInt8 *)(i_iph))+IPV6_HEADER_SIZE),len);
00302     //  sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], i_len_of_data);
00303     return (sum == 0) ? 0xffff : NyLPC_htons(sum);
00304 }
00305 
00306 
00307 
00308 /*--------------------------------------------------------------------------------
00309  *
00310  * struct NyLPC_TTcpHeader
00311  *
00312  *------------------------------------------------------------------------------*/
00313 
00314 
00315 /**
00316  * MMSオプションの値を返す。
00317  */
00318 NyLPC_TBool NyLPC_TTcpHeader_getTcpMmsOpt(
00319     const struct NyLPC_TTcpHeader* i_struct,NyLPC_TUInt16* o_val)
00320 {
00321     NyLPC_TUInt8* opt;
00322     opt=NyLPC_TTcpHeader_getTcpOptFragmentPtr(i_struct,TCP_OPT_MSS);
00323     if(opt!=NULL){
00324         if (*(opt+1) == TCP_OPT_MSS_LEN)
00325         {
00326             // An MSS option with the right option length.
00327             *o_val = ((NyLPC_TUInt16) (*(opt+2)) << 8) | (NyLPC_TUInt16) (*(opt + 3));
00328             //And we are done processing options.
00329             return NyLPC_TBool_TRUE;
00330         }
00331     }
00332     return NyLPC_TBool_FALSE;
00333 }
00334 
00335 #define DEFAULT_TCP_HEADER_LEN 20
00336 /**
00337  * TCPフラグメントのポインタを返す。
00338  */
00339 NyLPC_TUInt8* NyLPC_TTcpHeader_getTcpOptFragmentPtr(
00340     const struct NyLPC_TTcpHeader* i_struct,
00341     NyLPC_TUInt8 i_opt_id)
00342 {
00343     NyLPC_TUInt8 opt;
00344     int c;
00345     NyLPC_TUInt8* opt_buf=((NyLPC_TUInt8*)(i_struct+1));
00346 
00347     /* Parse the TCP MSS option, if present. */
00348     if ((i_struct->tcpoffset & 0xf0) > 0x50){
00349         for (c = 0; c < ((i_struct->tcpoffset >> 4) - 5) << 2;)
00350         {
00351             opt=opt_buf[c];
00352             if(opt==i_opt_id){
00353                 return opt_buf+c;//found!
00354             }
00355             switch(opt)
00356             {
00357             case TCP_OPT_NOOP:
00358                 continue;//NOP option.
00359             case TCP_OPT_END:
00360                 return NULL;//End of options.
00361             default:
00362                 // All other options have a length field, so that we easily can skip past them.
00363                 if (opt_buf[1 + c] == 0) {
00364                     // If the length field is zero, the options are malformed and we don't process them further.
00365                     NyLPC_OnErrorGoto(ERROR_INVALID_OPTION);
00366                 }
00367                 c += opt_buf[1 + c];
00368             }
00369         }
00370     }
00371 ERROR_INVALID_OPTION:
00372     return NULL;
00373 }
00374 /*
00375  * Optionパラメタを書きだす。
00376  */
00377 void NyLPC_TTcpHeader_setMmsOpt(NyLPC_TUInt8* i_opt_addr,NyLPC_TUInt16 i_mms)
00378 {
00379     i_opt_addr[0] = TCP_OPT_MSS;
00380     i_opt_addr[1] = TCP_OPT_MSS_LEN;
00381     i_opt_addr[2] = (i_mms) / 256;
00382     i_opt_addr[3] = (i_mms) & 255;
00383     return;
00384 }
00385 
00386 
00387 NyLPC_TUInt16 NyLPC_TTcpHeader_getHeaderLength(const struct NyLPC_TTcpHeader* ip_header)
00388 {
00389     return (ip_header->tcpoffset>>4)*4;
00390 }
00391 /*--------------------------------------------------------------------------------
00392  *
00393  * struct NyLPC_TUdpHeader
00394  *
00395  *------------------------------------------------------------------------------*/
00396 
00397 
00398 
00399 /*--------------------------------------------------------------------------------
00400  *
00401  * struct NyLPC_TArpHeader
00402  *
00403  *------------------------------------------------------------------------------*/
00404 /**
00405  * i_req_addrを問い合わせるARP_REQUESTを生成します。
00406  */
00407 void NyLPC_TArpHeader_setArpRequest(
00408     struct NyLPC_TArpHeader* i_struct,
00409     const struct NyLPC_TIPv4Addr i_saddr,
00410     const struct NyLPC_TEthAddr* i_srceth,
00411     const struct NyLPC_TIPv4Addr* i_req_addr)
00412 {
00413     memset(i_struct->dhwaddr.addr, 0x00, 6);
00414     memcpy(i_struct->shwaddr.addr, i_srceth, 6);
00415     i_struct->dipaddr=*i_req_addr;
00416     i_struct->sipaddr=i_saddr;
00417     i_struct->opcode = NyLPC_HTONS(ARP_REQUEST); /* ARP request. */
00418     i_struct->hwtype = NyLPC_HTONS(ARP_HWTYPE_ETH);
00419     i_struct->protocol = NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IP);
00420     i_struct->hwlen = 6;
00421     i_struct->protolen = 4;
00422     return;
00423 }
00424 
00425 /*--------------------------------------------------------------------------------
00426  *
00427  * class IPv4Route
00428  *
00429  *------------------------------------------------------------------------------*/
00430 
00431 
00432