00001 /* 00002 * Copyright (c) 2010, FIP AUTHORS 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 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 * 00011 * 2) Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * 3) Neither the name of the FIP AUTHORS nor the names of its contributors 00016 * may be used to endorse or promote products derived from this software 00017 * without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00029 * POSSIBILITY OF SUCH DAMAGE. 00030 */ 00031 /** 00032 * @file 00033 * Header for Active Packet Interface 00034 * 00035 * @author 00036 * Colin O'Flynn 00037 */ 00038 /** 00039 * @addtogroup fip_packet 00040 * 00041 * For background & high-level information on what the active packet buffer 00042 * is see @ref packetBuffer. 00043 * 00044 * The active packet 00045 * could contain a number of different buffers to store information such as 00046 * Link-Layer Headers, IP Headers, IP Data, UDP Data, etc. The buffers are 00047 * flexible themselves in that they can be just be statically or dynamically 00048 * allocated depending on your available resources. 00049 * 00050 * The configuration file will define possible buffers you can use. They must 00051 * be configured as a number indicating the order in which the packets will 00052 * be sent, although adding data can occur in any order. Thus you can fill 00053 * in buffer 0, 3, 2, 4 in that order. When the packet is sent the message 00054 * will look like [0][2][3][4]. Note buffer 1 had nothing in it, so was omitted 00055 * from the final message. This configuration allows you to for example define 00056 * IPv6 Extension Header buffers, and when you need to insert one there is no 00057 * need to actually move anything, you just insert a pointer to where the 00058 * extension header is stored. 00059 * 00060 * An example configuration file might look like: 00061 * 00062 @code 00063 //Link-layer Buffer 00064 #define FIP_LLBUF 0 00065 00066 //IPv6 Header Buffer 00067 #define FIP_IPHDRBUF 1 00068 00069 //IPv6 Hop-By-Hop Buffer 00070 #define FIP_IPHBHBUF 2 00071 00072 //IPv6 Routing Header Buffer 00073 #define FIP_IPRHBUF 3 00074 00075 //IPv6 Additional Header Space 00076 #define FIP_IPAHBUF 4 00077 00078 //Transport Layer Buffer 00079 #define FIP_TLBUF 5 00080 00081 //Application Layer Buffer 00082 #define FIP_APPBUF 6 00083 00084 //Total of 7 buffer types defined (0-6) 00085 #define FIP_NUMBUFS 7 00086 @endcode 00087 * 00088 * You don't need to use every buffer type you define, but you can't use any 00089 * type more than once on any packet. If you required multiple of the same 00090 * type (e.g. for tunnelling, multiple extension headers) you need to define 00091 * things like FIP_IPHBH1, etc. Each buffer has the following properties: 00092 * 00093 * @li @c Ptr A pointer to the buffer 00094 * 00095 * @li @c AllocSize The allocated size of the buffer 00096 * 00097 * @li @c UsedSize The actual space used in the buffer 00098 * 00099 * In addition the 'link-layer' buffer has additional properties. They are: 00100 * 00101 * @li @c srcLLAddrOffset Offset of the source LL Address from start of LL buffer 00102 * 00103 * @li @c srcLLAddrLen Length of the source LL address in bytes 00104 * 00105 * @li @c destLLAddrOffset Offset of the destination LL Address from start of LL buffer 00106 * 00107 * @li @c destLLAddrLen Length of the destination LL address in bytes 00108 * 00109 * Addresses are stored MSB first, if the link-layer provides them another order 00110 * you are required to flip the addresses around. 00111 * 00112 * @{ 00113 */ 00114 00115 #ifndef FIP_PACKET_H_ 00116 #define FIP_PACKET_H_ 00117 00118 /* ################################## TYPES ############################### */ 00119 00120 /** 00121 * Valid states the active packet buffer can be in. 00122 */ 00123 typedef enum { 00124 PS_UNUSED, /**< This packet is not allocated. */ 00125 PS_EMPTY, /**< Packet is allocated, but nothing done with it yet. */ 00126 PS_RECEIVINGLL, /**< LL is not done receiving data yet */ 00127 PS_PROCESSIP, /**< Packet is ready for IP-level processing */ 00128 PS_WAITING_AR, /**< Packet's dest IP address is awaiting address resolution to complete */ 00129 PS_SEND, /**< Packet is ready to be sent */ 00130 PS_STARTLLSEND, /**< Start Link-Layer Transmit */ 00131 PS_LLSENDING, /**< Link-Layer Transmit in Progress */ 00132 }fip_packetstate_t; 00133 00134 typedef struct { 00135 uint8_t * ptr; /**< Pointer to the packet buffers */ 00136 uint16_t allocSize; /**< Allocated size of buffer */ 00137 uint16_t usedSize; /**< Size of data in buffer */ 00138 #if FIP_CONF_BUFFER_TYPE == FIP_DYNAMIC 00139 uint8_t * freeBufPtr; /**< Pointer to be used with the call to free() */ 00140 #endif 00141 }fip_packetbuf_t; 00142 00143 /** 00144 * Hold the current active packet. 00145 */ 00146 typedef struct { 00147 /* Generic Stuff */ 00148 fip_packetstate_t state; /**< State of the packet */ 00149 fip_packetbuf_t buf[FIP_NUMBUFS]; /**< The buffers */ 00150 unsigned char refNum; /**< Reference number, Incremented for every new packet */ 00151 00152 /* Link-Layer Stuff */ 00153 fip_ifnum_t IFNum; /**< Interface Number this packet deals with */ 00154 00155 unsigned char srcLLAddrOffset; /**< Offset from start of LL header to source 00156 * address, where address is MSB first */ 00157 unsigned char srcLLAddrLen; /**< Length of the source address */ 00158 unsigned char destLLAddrOffset; /**< Offset from start of LL header to dest 00159 * address, where address is MSB first */ 00160 unsigned char destLLAddrLen; /**< Length of destination address */ 00161 00162 /* IP Header Stuff */ 00163 fip_ipversion_t IPVersion; /**< IP Version of Packet (IPV6 or IPV4) */ 00164 00165 /* Flags for quicker processing */ 00166 fip_ip6addr_flags_t srcFlags; /**< Destination IPv6 Address Flags */ 00167 fip_ip6addr_flags_t destFlags; /**< Source IPv6 Address Flags */ 00168 fip_ipnum_t destIPNum; /**< Destination IP Number (0xFF = Unknown) */ 00169 00170 /* Generic state mechanism */ 00171 uint8_t scratchPad[FIP_CONF_SP_SIZE]; /**< Scratchpad which holds attributes 00172 * as required */ 00173 } fip_packet_t; 00174 00175 /* ################################## FUNCTIONS ############################### */ 00176 /* Note: Documented in associated .c file */ 00177 fip_return_t fip_packet_newPacket(fip_bufnum_t bufnum, uint16_t length, fip_ifnum_t ifnum); 00178 void fip_packet_bufSplit(fip_bufnum_t bufnumLeft, fip_bufnum_t bufnumRight); 00179 fip_return_t fip_packet_bufAlloc(fip_bufnum_t bufnum, uint16_t length); 00180 void fip_packet_freePacket(void); 00181 fip_return_t fip_packet_newResponsePacket(fip_bufnum_t bufnum, unsigned int length); 00182 void fip_packet_queuePacket(void); 00183 void fip_packet_unqueuePacket(void); 00184 unsigned int fip_packet_getBufSizes(fip_bufnum_t first, fip_bufnum_t last); 00185 00186 void fip_packet_copyToIP6Hdr_destAddr(const uint8_t * const address); 00187 void fip_packet_copyToIP6Hdr_srcAddr(const uint8_t * const address); 00188 00189 void fip_packet_setToIP6Hdr_srcAddrUnspecified(void); 00190 void fip_packet_setToIP6Hdr_destAddrAllNodes(void); 00191 void fip_packet_setToIP6Hdr_destAddrAllRouters(void); 00192 00193 /* ############################## PACKET BUFFER ACCESS ######################### */ 00194 00195 /** Optimised function to check for IPv6 Multicast in source address */ 00196 #define fip_packet_getFromIP6Hdr_isSrcMulticast() (*(fip_packet_getIPBufPtr() + 8) == 0xFF) 00197 00198 /** Optimized function to check for IPv6 Multicast in dest address */ 00199 #define fip_packet_getFromIP6Hdr_isDestMulticast() (*(fip_packet_getIPBufPtr() + 24) == 0xFF) 00200 00201 /** @todo: technically this includes site-local too */ 00202 #define fip_packet_getFromIP6Hdr_isDestLinkLocal() (*(fip_packet_getIPBufPtr() + 24) == 0xFE) 00203 00204 /** 00205 * Get a pointer to a specific buffer, such as the L2 buffer, IP buffer, etc 00206 * @param bufNum Buffer to get a pointer to 00207 */ 00208 #define fip_packet_getBufPtr(bufNum) (fip_packet_get().buf[bufNum].ptr) 00209 00210 /** 00211 * Get the allocated (maximum) size of a buffer 00212 * @param bufNum Buffer to get the max size of 00213 */ 00214 #define fip_packet_getBufMaxSize(bufNum) (fip_packet_get().buf[bufNum].allocSize) 00215 00216 /** 00217 * Get the size of data currently written into the buffer 00218 * @param bufNum Buffer to get size of 00219 */ 00220 #define fip_packet_getBufSize(bufNum) (fip_packet_get().buf[bufNum].usedSize) 00221 00222 /** 00223 * Set the size of data currently written into the buffer 00224 * 00225 * @param bufNum Buffer to get size of 00226 * @param size Size of data to write 00227 */ 00228 #define fip_packet_setBufSize(bufNum, size) (fip_packet_get().buf[bufNum].usedSize = size) 00229 00230 /** 00231 * Get the value of an attribute from the active packet buffer. 00232 * @param attr The attribute to get. Valid values are elements of the @ref fip_packet_t struct. 00233 */ 00234 #define fip_packet_getAttr(attr) fip_packet_get().attr 00235 00236 /** 00237 * Set the value of an attribute to the active packet buffer. 00238 * @param attr The attribute to set. Valid values are elements of the @ref fip_packet_t struct. 00239 * @param value The value to set this attribute to. 00240 */ 00241 #define fip_packet_setAttr(attr, value) fip_packet_get().attr = (value) 00242 00243 00244 /* .srcAddrOffset and .srcAddrLen Access */ 00245 /** @todo PH.4: Improve performance for fixed LL header lengths. */ 00246 /** Set the LL source address, you must have set the srcLLAddrOffset attribute 00247 * before calling this! */ 00248 #define fip_packet_setLLSrcAddr(addr, len) {fip_packet_get().srcLLAddrLen = len; \ 00249 memcpy(fip_packet_get().srcLLAddrOffset + fip_packet_getBufPtr(FIP_LLBUF), addr, len);} 00250 00251 /* .destAddrOffset and .destAddrLen Access */ 00252 /** @todo PH.4: Improve performance for fixed LL header lengths. */ 00253 /** Set the LL dest address, you must have set the destLLAddrOffset attribute 00254 * before calling this! */ 00255 #define fip_packet_setLLDestAddr(addr, len) {fip_packet_get().destLLAddrLen = len; \ 00256 memcpy(fip_packet_get().destLLAddrOffset + fip_packet_getBufPtr(FIP_LLBUF), addr, len);} 00257 00258 /** Set the address flags 00259 * @param type Either 'srcFlags' or 'destFlags' 00260 * @param flag See @ref fip_ip6addr_flags_t for flags 00261 * @param value Value to set 00262 */ 00263 #define fip_packet_setAddrFlags(type, flag, value) (fip_packet_get().type.flag = value) 00264 00265 /** Get the address flags 00266 * @param type Either 'srcFlags' or 'destFlags' 00267 * @param flag See @ref fip_ip6addr_flags_t for flags 00268 */ 00269 #define fip_packet_getAddrFlags(type, flag) fip_packet_get().type.flag 00270 00271 /** Get a pointer to the 'scratchpad', and cast it to a pointer of the type passed */ 00272 #define fip_packet_spGetPtr(type) ((type *)(fip_packet_get().scratchPad)) 00273 00274 #define fip_packet_getFromBuf_Uint8(bufNum, offset) *((uint8_t *)fip_packet_getBufPtr(bufNum) + (offset)) 00275 #define fip_packet_setToBuf_Uint8(bufNum, offset, data) (*((uint8_t *)fip_packet_getBufPtr(bufNum) + (offset)) = data) 00276 /*---------------- Macros which depend on buffer type ---------------------- */ 00277 #ifdef DOXYGEN 00278 /** @def fip_packet_getFromIPBuf_Uint8Unaligned(offset) 00279 * Get a single byte from the IP buffer, the byte located offset 00280 * bytes from the start of the IP buffer. Byte offset is NOT a 32-bit aligned 00281 * address, so this macro will result in "safe" code on platforms that care 00282 * about alignment. 00283 */ 00284 /**@todo make this safe */ 00285 #define fip_packet_getFromBuf_Uint8Unaligned(offset, bufNum) 00286 00287 #elif FIP_CONF_BUFFER_TYPE == FIP_STATIC_SINGLEUSE 00288 extern uint8_t fip_activePacket_buffer[FIP_STATIC_BUF_SIZE]; 00289 extern fip_packet_t fip_activePacket; 00290 00291 #define fip_packet_getPtr() &fip_activePacket 00292 00293 #define fip_packet_get() fip_activePacket 00294 00295 #define fip_packet_getIPBufPtr() &fip_activePacket_buffer[FIP_CONF_LLH_MAX] 00296 00297 /** @todo IPv4.1: Add IPv4 Handling into headers etc */ 00298 #define fip_packet_getFromIPBuf_Uint8Unaligned(offset) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] 00299 #define fip_packet_getFromIPBuf_Uint8Aligned(offset) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] 00300 #define fip_packet_setToIPBuf_Uint8Unaligned(offset,x) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] = (x) 00301 #define fip_packet_setToIPBuf_Uint8Aligned(offset,x) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] = (x) 00302 00303 #elif FIP_CONF_BUFFER_TYPE == FIP_DYNAMIC 00304 00305 extern fip_packet_t * fip_activePacketPtr; 00306 00307 #define fip_packet_getPtr() fip_activePacketPtr 00308 00309 #define fip_packet_get() (*fip_activePacketPtr) 00310 00311 #define fip_packet_getIPBufPtr() fip_packet_getBufPtr(FIP_IPHDRBUF) 00312 00313 /** @todo IPv4.1: Add IPv4 Handling into headers etc */ 00314 #define fip_packet_getFromIPBuf_Uint8Unaligned(offset) fip_packet_getFromBuf_Uint8(FIP_IPHDRBUF, offset) 00315 #define fip_packet_getFromIPBuf_Uint8Aligned(offset) fip_packet_getFromBuf_Uint8(FIP_IPHDRBUF, offset) 00316 #define fip_packet_setToIPBuf_Uint8Unaligned(offset,x) fip_packet_setToBuf_Uint8(FIP_IPHDRBUF, offset, x) 00317 #define fip_packet_setToIPBuf_Uint8Aligned(offset,x) fip_packet_setToBuf_Uint8(FIP_IPHDRBUF, offset, x) 00318 00319 #else 00320 00321 #error "Unimplemented FIP BUFFER TYPE choosen" 00322 00323 /* Things that need defining */ 00324 00325 #define fip_packet_getPtr() 00326 00327 #define fip_packet_get() 00328 00329 /** @todo IPv4.1: Add IPv4 Handling into headers etc */ 00330 #define fip_packet_getFromIPBuf_Uint8Unaligned(offset) 00331 #define fip_packet_getFromIPBuf_Uint8Aligned(offset) 00332 #define fip_packet_setToIPBuf_Uint8Unaligned(offset,x) 00333 #define fip_packet_setToIPBuf_Uint8Aligned(offset,x) 00334 00335 #define fip_packet_getIPBufPtr() fip_packet_getBufPtr(FIP_IPHBUF) 00336 00337 #endif 00338 00339 00340 /** Get the interface number, available as a separate macro as single-interface systems 00341 * can replace this with a constant */ 00342 #define fip_packet_getIfNum() fip_packet_getAttr(IFNum) 00343 00344 00345 /** @defgroup ipv6packet IPv6 Specific Packet Handling 00346 * @{ */ 00347 00348 /** Get the offset from the start of the IP buffer to the next header. */ 00349 #define fip_packet_getFromIP6Hdr_nhOffset() (6) 00350 00351 /** Get a pointer to the IPv6 Destination Address. WARNING: If you change the IP 00352 * address with this function, you need to reset the associated flags. It is better 00353 * to use the @ref fip_packet_copyToIP6Hdr_destAddr() function. */ 00354 #define fip_packet_getFromIP6Hdr_destPtr() (fip_packet_getIPBufPtr() + 24) 00355 00356 /** Get a single byte from the IPv6 Destination Address. 00357 * @param x Offset of the byte to get. 00358 */ 00359 #define fip_packet_getFromIP6Hdr_destAddr(x) fip_packet_getFromIPBuf_Uint8Unaligned(x + 24) 00360 00361 /** Set a single byte to the IPv6 Destination Address. WARNING: If you change the IP 00362 * address with this function, you need to reset the associated flags. It is better 00363 * to use the @ref fip_packet_copyToIP6Hdr_destAddr() function. 00364 * @param x Offset of the byte to set. 00365 * @param data Byte to set 00366 */ 00367 #define fip_packet_setToIP6Hdr_destAddr(x, data) fip_packet_setToIPBuf_Uint8Unaligned(x + 24, data) 00368 00369 /** Get a pointer to the IPv6 Source Address. WARNING: If you change the IP 00370 * address with this function, you need to reset the associated flags. It is better 00371 * to use the @ref fip_packet_copyToIP6Hdr_srcAddr() function. */ 00372 #define fip_packet_getFromIP6Hdr_srcPtr() (fip_packet_getIPBufPtr() + 8) 00373 00374 /** Get a single byte from the IPv6 Destination Address. 00375 * @param x Offset of the byte to get. 00376 */ 00377 #define fip_packet_getFromIP6Hdr_srcAddr(x) fip_packet_getFromIPBuf_Uint8Unaligned(x + 8) 00378 00379 /** Reset the flags associated with a certain address */ 00380 #define fip_packet_resetAddrFlags(type) {fip_packet_setAddrFlags(type, isMySolicitedNode, tribool_untested); \ 00381 fip_packet_setAddrFlags(type, isUnspecified, tribool_untested); \ 00382 fip_packet_setAddrFlags(type, isLinkLocal, tribool_untested); \ 00383 fip_packet_setAddrFlags(type, isOnLink, tribool_untested); } 00384 00385 /** Get the IP version of this packet, equates to either FIP_IPHDR_V6 or FIP_IPHDR_V4 */ 00386 #define fip_packet_getFromIPHdr_version() (fip_packet_getFromIPBuf_Uint8Aligned(0) & 0xF0) 00387 00388 /** Get the length field of the IPv6 header. */ 00389 #define fip_packet_getFromIP6Hdr_length() (fip_toUint16(fip_packet_getFromIPBuf_Uint8Aligned(4), fip_packet_getFromIPBuf_Uint8Unaligned(5))) 00390 #define fip_packet_getFromIP6Hdr_nextHeader() (fip_packet_getFromIPBuf_Uint8Unaligned(6)) 00391 #define fip_packet_getFromIP6Hdr_hopLimit() (fip_packet_getFromIPBuf_Uint8Unaligned(7)) 00392 00393 /* */ 00394 #define fip_packet_setToIPHdr_versionClobberTC(data) (fip_packet_setToIPBuf_Uint8Aligned(0, data)) 00395 00396 /** Set the length field in the IPv6 header, Handles conversion to network order */ 00397 #define fip_packet_setToIP6Hdr_length(data) {fip_packet_setToIPBuf_Uint8Unaligned(4, fip_Uint16_getMSB(data)); fip_packet_setToIPBuf_Uint8Unaligned(5, fip_Uint16_getLSB(data));} 00398 /** Set the next header field in the IPv6 Header */ 00399 #define fip_packet_setToIP6Hdr_nextHeader(data) (fip_packet_setToIPBuf_Uint8Unaligned(6, data)) 00400 /** Set the hop limit field in the IPv6 Header */ 00401 #define fip_packet_setToIP6Hdr_hopLimit(data) (fip_packet_setToIPBuf_Uint8Unaligned(7, data)) 00402 00403 /** @} */ 00404 /*---------------------------------------------------------------------------*/ 00405 /** @defgroup icmpv6packet ICMPv6 Specific Packet Handling 00406 * @{ */ 00407 00408 /** Get the ICMPv6 'type' in the header */ 00409 #define fip_packet_getFromICMP6Hdr_Type() fip_packet_getFromBuf_Uint8(FIP_TLBUF, 0) 00410 /** Get the ICMPv6 'Code' in the header */ 00411 #define fip_packet_getFromICMP6Hdr_Code() fip_packet_getFromBuf_Uint8(FIP_TLBUF, 1) 00412 /** Set the ICMPv6 'type' in the header */ 00413 #define fip_packet_setToICMP6Hdr_Type(data) fip_packet_setToBuf_Uint8(FIP_TLBUF, 0, data) 00414 /** Set the ICMPv6 'code' in the header */ 00415 #define fip_packet_setToICMP6Hdr_Code(data) fip_packet_setToBuf_Uint8(FIP_TLBUF, 1, data) 00416 /** Set the ICMPv6 'checksum' in the header, converts byte order correctly */ 00417 #define fip_packet_setToICMP6Hdr_Checksum(data) {fip_packet_setToBuf_Uint8(FIP_TLBUF, 2, fip_Uint16_getMSB((data))); fip_packet_setToBuf_Uint8(FIP_TLBUF, 3, fip_Uint16_getLSB((data)));} 00418 00419 /** @} */ 00420 /*---------------------------------------------------------------------------*/ 00421 /** 00422 * @} fip_packet 00423 */ 00424 00425 #endif /* FIP_PACKET_H_ */ 00426