00001 /* 00002 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without modification, 00006 * are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright notice, 00011 * this list of conditions and the following disclaimer in the documentation 00012 * and/or other materials provided with the distribution. 00013 * 3. The name of the author may not be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00017 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00018 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00019 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00020 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00021 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00023 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00024 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00025 * OF SUCH DAMAGE. 00026 * 00027 * This file is part of the lwIP TCP/IP stack. 00028 * 00029 * Author: Adam Dunkels <adam@sics.se> 00030 * 00031 * CHANGELOG: this file has been modified by Sergio Perez Alcañiz <serpeal@disca.upv.es> 00032 * Departamento de Informática de Sistemas y Computadores 00033 * Universidad Politécnica de Valencia 00034 * Valencia (Spain) 00035 * Date: April 2003 00036 * 00037 */ 00038 00039 /*-----------------------------------------------------------------------------------*/ 00040 /* inet6.c 00041 * 00042 * Functions common to all TCP/IP modules, such as the Internet checksum and the 00043 * byte order functions. 00044 * 00045 */ 00046 /*-----------------------------------------------------------------------------------*/ 00047 00048 #include "lwip/opt.h" 00049 00050 #include "lwip/def.h" 00051 #include "lwip/inet.h" 00052 00053 00054 /*-----------------------------------------------------------------------------------*/ 00055 /* chksum: 00056 * 00057 * Sums up all 16 bit words in a memory portion. Also includes any odd byte. 00058 * This function is used by the other checksum functions. 00059 * 00060 * For now, this is not optimized. Must be optimized for the particular processor 00061 * arcitecture on which it is to run. Preferebly coded in assembler. 00062 */ 00063 /*-----------------------------------------------------------------------------------*/ 00064 static u32_t 00065 chksum(void *dataptr, u16_t len) 00066 { 00067 u16_t *sdataptr = dataptr; 00068 u32_t acc; 00069 00070 00071 for(acc = 0; len > 1; len -= 2) { 00072 acc += *sdataptr++; 00073 } 00074 00075 /* add up any odd byte */ 00076 if(len == 1) { 00077 acc += htons((u16_t)(*(u8_t *)dataptr) << 8); 00078 } 00079 00080 return acc; 00081 00082 } 00083 /*-----------------------------------------------------------------------------------*/ 00084 /* inet_chksum_pseudo: 00085 * 00086 * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. 00087 */ 00088 /*-----------------------------------------------------------------------------------*/ 00089 u16_t 00090 inet_chksum_pseudo(struct pbuf *p, 00091 struct ip_addr *src, struct ip_addr *dest, 00092 u8_t proto, u32_t proto_len) 00093 { 00094 u32_t acc; 00095 struct pbuf *q; 00096 u8_t swapped, i; 00097 00098 acc = 0; 00099 swapped = 0; 00100 for(q = p; q != NULL; q = q->next) { 00101 acc += chksum(q->payload, q->len); 00102 while(acc >> 16) { 00103 acc = (acc & 0xffff) + (acc >> 16); 00104 } 00105 if(q->len % 2 != 0) { 00106 swapped = 1 - swapped; 00107 acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); 00108 } 00109 } 00110 00111 if(swapped) { 00112 acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); 00113 } 00114 00115 for(i = 0; i < 8; i++) { 00116 acc += ((u16_t *)src->addr)[i] & 0xffff; 00117 acc += ((u16_t *)dest->addr)[i] & 0xffff; 00118 while(acc >> 16) { 00119 acc = (acc & 0xffff) + (acc >> 16); 00120 } 00121 } 00122 acc += (u16_t)htons((u16_t)proto); 00123 acc += ((u16_t *)&proto_len)[0] & 0xffff; 00124 acc += ((u16_t *)&proto_len)[1] & 0xffff; 00125 00126 while(acc >> 16) { 00127 acc = (acc & 0xffff) + (acc >> 16); 00128 } 00129 return ~(acc & 0xffff); 00130 } 00131 /*-----------------------------------------------------------------------------------*/ 00132 /* inet_chksum: 00133 * 00134 * Calculates the Internet checksum over a portion of memory. Used primarely for IP 00135 * and ICMP. 00136 */ 00137 /*-----------------------------------------------------------------------------------*/ 00138 u16_t 00139 inet_chksum(void *dataptr, u16_t len) 00140 { 00141 u32_t acc, sum; 00142 00143 acc = chksum(dataptr, len); 00144 sum = (acc & 0xffff) + (acc >> 16); 00145 sum += (sum >> 16); 00146 return ~(sum & 0xffff); 00147 } 00148 /*-----------------------------------------------------------------------------------*/ 00149 u16_t 00150 inet_chksum_pbuf(struct pbuf *p) 00151 { 00152 u32_t acc; 00153 struct pbuf *q; 00154 u8_t swapped; 00155 00156 acc = 0; 00157 swapped = 0; 00158 for(q = p; q != NULL; q = q->next) { 00159 acc += chksum(q->payload, q->len); 00160 while(acc >> 16) { 00161 acc = (acc & 0xffff) + (acc >> 16); 00162 } 00163 if(q->len % 2 != 0) { 00164 swapped = 1 - swapped; 00165 acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8); 00166 } 00167 } 00168 00169 if(swapped) { 00170 acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); 00171 } 00172 return ~(acc & 0xffff); 00173 } 00174 /*-----------------------------------------------------------------------------------*/