00001 /* 00002 * Copyright (c) 2005, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * @(#)$Id: hc.c,v 1.5 2010/10/19 18:29:04 adamdunkels Exp $ 00032 */ 00033 00034 /** 00035 * \file 00036 * TCP/IP header compression implementation 00037 * \author Adam Dunkels <adam@sics.se> 00038 * 00039 */ 00040 00041 #include "net/hc.h" 00042 00043 #include "net/uip.h" 00044 00045 #include <string.h> 00046 00047 #define FLAGS_COMPRESSED 0x8000 00048 #define FLAGS_BROADCASTDATA 0x4000 00049 00050 struct hc_hdr { 00051 u16_t flagsport; 00052 uip_ipaddr_t srcipaddr; 00053 }; 00054 00055 struct udpip_hdr { 00056 /* IP header. */ 00057 u8_t vhl, 00058 tos, 00059 len[2], 00060 ipid[2], 00061 ipoffset[2], 00062 ttl, 00063 proto; 00064 u16_t ipchksum; 00065 uip_ipaddr_t srcipaddr, destipaddr; 00066 00067 /* UDP header. */ 00068 u16_t srcport, 00069 destport; 00070 u16_t udplen; 00071 u16_t udpchksum; 00072 }; 00073 00074 #include <stdio.h> 00075 00076 /*---------------------------------------------------------------------------*/ 00077 /** 00078 * Initialize the header compression module. 00079 */ 00080 /*---------------------------------------------------------------------------*/ 00081 void 00082 hc_init(void) 00083 { 00084 00085 } 00086 /*---------------------------------------------------------------------------*/ 00087 /** 00088 * Compress a header 00089 * 00090 * This function compresses the TCP/IP headers in a buffer and 00091 * should be called just before sending out data on the network. A 00092 * pointer to the compressed header is returned, and len is 00093 * adjusted. 00094 * 00095 * If the header could not be compressed, the function does nothing 00096 * and returns a NULL pointer. 00097 * 00098 * \return A pointer to the start of the compressed header or NULL if 00099 * the header could not be compressed. 00100 */ 00101 /*---------------------------------------------------------------------------*/ 00102 int 00103 hc_compress(u8_t *buf, int len) 00104 { 00105 struct hc_hdr *hdr; 00106 struct udpip_hdr *uhdr; 00107 00108 hdr = (struct hc_hdr *)buf; 00109 uhdr = (struct udpip_hdr *)buf; 00110 00111 /* Check the original TCP/IP header to see if it matches our 00112 pattern, and compress if it does. */ 00113 00114 if(uhdr->vhl == 0x45 && /* Only IPv4 without 00115 options. */ 00116 uhdr->len[0] == 0x00 && /* Only packets < 256 00117 bytes long. */ 00118 uhdr->ipoffset[0] == 0x00 && /* No fragmented IP 00119 packets. */ 00120 uhdr->ipoffset[1] == 0x00 && /* No fragmented IP 00121 packets. */ 00122 uhdr->proto == UIP_PROTO_UDP && /* Only UDP packets. */ 00123 uip_ipaddr_cmp(&uhdr->destipaddr, &uip_broadcast_addr) && /* Only 00124 link-local broadcast 00125 packets. */ 00126 uhdr->destport == uhdr->srcport && /* Only packets with 00127 the same destination 00128 and source port 00129 number. */ 00130 (uhdr->destport & UIP_HTONS(0xc000)) == 0) { /* Only packets with the two 00131 highest bits in the port 00132 number equal to zero. */ 00133 00134 hdr->flagsport = uip_htons( 00135 FLAGS_COMPRESSED | /* Compressed header. */ 00136 FLAGS_BROADCASTDATA | /* Broadcast data. */ 00137 (uip_htons(uhdr->destport) & 0x3fff)); 00138 uip_ipaddr_copy(&hdr->srcipaddr, &uhdr->srcipaddr); 00139 00140 /* Move the packet data to the end of the compressed header. */ 00141 memcpy((char *)hdr + HC_HLEN, 00142 &buf[UIP_IPUDPH_LEN], 00143 len - UIP_IPUDPH_LEN); 00144 00145 /* Return the new packet length. */ 00146 return len - (UIP_IPUDPH_LEN - HC_HLEN); 00147 } 00148 00149 /* No compression possible, return NULL pointer. */ 00150 return len; 00151 00152 } 00153 /*---------------------------------------------------------------------------*/ 00154 /** 00155 * Inflate (decompress) a header 00156 * 00157 * This function should be called to inflate a possibly compressed 00158 * packet header just after a packet has been received from the 00159 * network. The function will copy the packet data so that the 00160 * original header fits and adjusts uip_len. 00161 * 00162 */ 00163 /*---------------------------------------------------------------------------*/ 00164 int 00165 hc_inflate(u8_t *buf, int len) 00166 { 00167 struct udpip_hdr *uhdr; 00168 struct hc_hdr *hdr; 00169 00170 hdr = (struct hc_hdr *)buf; 00171 00172 /* First, check if the header in buf is compressed or not. */ 00173 if((hdr->flagsport & UIP_HTONS(FLAGS_COMPRESSED)) != 0 && 00174 (hdr->flagsport & UIP_HTONS(FLAGS_BROADCASTDATA)) != 0) { 00175 00176 /* Move packet data in memory to make room for the uncompressed header. */ 00177 memmove(&buf[UIP_IPUDPH_LEN - HC_HLEN], 00178 buf, len); 00179 uhdr = (struct udpip_hdr *)buf; 00180 hdr = (struct hc_hdr *)&buf[UIP_IPUDPH_LEN - HC_HLEN]; 00181 00182 uip_ipaddr_copy(&uhdr->srcipaddr, &hdr->srcipaddr); 00183 uhdr->srcport = hdr->flagsport & UIP_HTONS(0x3fff); 00184 uhdr->destport = hdr->flagsport & UIP_HTONS(0x3fff); 00185 00186 uhdr->udplen = len; 00187 00188 len += UIP_IPUDPH_LEN - HC_HLEN; 00189 00190 00191 uhdr->vhl = 0x45; 00192 uhdr->tos = 0; 00193 uhdr->len[0] = 0; 00194 uhdr->len[1] = len; 00195 uhdr->ipid[0] = uhdr->ipid[1] = 0xAD; 00196 uhdr->ipoffset[0] = uhdr->ipoffset[1] = 0; 00197 uhdr->ttl = 2; 00198 uhdr->proto = UIP_PROTO_UDP; 00199 uip_ipaddr_copy(&uhdr->destipaddr, &uip_broadcast_addr); 00200 uhdr->udpchksum = 0; 00201 00202 uhdr->ipchksum = 0; 00203 uhdr->ipchksum = ~(uip_ipchksum()); 00204 00205 } 00206 00207 return len; 00208 } 00209 /*---------------------------------------------------------------------------*/