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_IPFRAG, /**< IP Fragmented received/transmit in progress */ 00131 PS_STARTLLSEND, /**< Start Link-Layer Transmit */ 00132 PS_LLSENDING, /**< Link-Layer Transmit in Progress */ 00133 }fip_packetstate_t; 00134 00135 typedef struct { 00136 uint8_t * ptr; /**< Pointer to the packet buffers */ 00137 uint16_t allocSize; /**< Allocated size of buffer */ 00138 uint16_t usedSize; /**< Size of data in buffer */ 00139 #if FIP_CONF_BUFFER_TYPE == FIP_DYNAMIC 00140 uint8_t * freeBufPtr; /**< Pointer to be used with the call to free() */ 00141 #endif 00142 }fip_packetbuf_t; 00143 00144 /** 00145 * Hold the current active packet. 00146 */ 00147 typedef struct { 00148 /* Generic Stuff */ 00149 fip_packetstate_t state; /**< State of the packet */ 00150 fip_packetbuf_t buf[FIP_NUMBUFS]; /**< The buffers */ 00151 unsigned char refNum; /**< Reference number, Incremented for every new packet */ 00152 00153 /* Link-Layer Stuff */ 00154 fip_ifnum_t IFNum; /**< Interface Number this packet deals with */ 00155 00156 unsigned char srcLLAddrOffset; /**< Offset from start of LL header to source 00157 * address, where address is MSB first */ 00158 unsigned char srcLLAddrLen; /**< Length of the source address */ 00159 unsigned char destLLAddrOffset; /**< Offset from start of LL header to dest 00160 * address, where address is MSB first */ 00161 unsigned char destLLAddrLen; /**< Length of destination address */ 00162 00163 /* IP Header Stuff */ 00164 fip_ipversion_t IPVersion; /**< IP Version of Packet (IPV6 or IPV4) */ 00165 00166 /* Flags for quicker processing */ 00167 fip_ip6addr_flags_t srcFlags; /**< Destination IPv6 Address Flags */ 00168 fip_ip6addr_flags_t destFlags; /**< Source IPv6 Address Flags */ 00169 fip_ipnum_t destIPNum; /**< Destination IP Number (0xFF = Unknown) */ 00170 00171 /* Generic state mechanism */ 00172 uint8_t scratchPad[FIP_CONF_SP_SIZE]; /**< Scratchpad which holds attributes 00173 * as required */ 00174 } fip_packet_t; 00175 00176 /* ################################## FUNCTIONS ############################### */ 00177 /* Note: Documented in associated .c file */ 00178 fip_return_t fip_packet_activeNew(fip_bufnum_t bufnum, uint16_t length, fip_ifnum_t ifnum); 00179 void fip_packet_activeBufSplit(fip_bufnum_t bufnumLeft, fip_bufnum_t bufnumRight); 00180 fip_return_t fip_packet_activeBufAlloc(fip_bufnum_t bufnum, uint16_t length); 00181 void fip_packet_activeDrop(void); 00182 fip_return_t fip_packet_activeResponsePacket(fip_bufnum_t bufnum, unsigned int length); 00183 void fip_packet_activeQueuePacket(void); 00184 fip_return_t fip_packet_activeUnqueuePacket(void); 00185 00186 void fip_packet_ptrQueueDrop(fip_packet_t * ptr); 00187 void fip_packet_ptrUnqueue(fip_packet_t * ptr); 00188 fip_packet_t * fip_packet_ptrUnqueuePacket(fip_packetstate_t ps, fip_ifnum_t ifnum, 00189 uint8_t * scratchPad, unsigned char scratchLen); 00190 unsigned int fip_packet_getBufSizes(fip_bufnum_t first, fip_bufnum_t last); 00191 fip_return_t fip_packet_ptrBufCpyFromActive(fip_packet_t * packetPtr, unsigned int destOffset, uint8_t * srcData, unsigned int srcLen); 00192 00193 void fip_packet_copyToIP6Hdr_destAddr(const uint8_t * const address); 00194 void fip_packet_copyToIP6Hdr_srcAddr(const uint8_t * const address); 00195 00196 void fip_packet_setToIP6Hdr_srcAddrUnspecified(void); 00197 void fip_packet_setToIP6Hdr_destAddrAllNodes(void); 00198 void fip_packet_setToIP6Hdr_destAddrAllRouters(void); 00199 00200 /* ############################## PACKET BUFFER ACCESS ######################### */ 00201 00202 /** Optimised function to check for IPv6 Multicast in source address */ 00203 #define fip_packet_getFromIP6Hdr_isSrcMulticast() (*(fip_packet_getIPBufPtr() + 8) == 0xFF) 00204 00205 /** Optimized function to check for IPv6 Multicast in dest address */ 00206 #define fip_packet_getFromIP6Hdr_isDestMulticast() (*(fip_packet_getIPBufPtr() + 24) == 0xFF) 00207 00208 /** @todo: technically this includes site-local too */ 00209 #define fip_packet_getFromIP6Hdr_isDestLinkLocal() (*(fip_packet_getIPBufPtr() + 24) == 0xFE) 00210 00211 /** 00212 * Get a pointer to a specific buffer, such as the L2 buffer, IP buffer, etc 00213 * @param bufNum Buffer to get a pointer to 00214 */ 00215 #define fip_packet_getBufPtr(bufNum) (fip_packet_get().buf[bufNum].ptr) 00216 00217 /** 00218 * Get the allocated (maximum) size of a buffer 00219 * @param bufNum Buffer to get the max size of 00220 */ 00221 #define fip_packet_getBufMaxSize(bufNum) (fip_packet_get().buf[bufNum].allocSize) 00222 00223 /** 00224 * Get the size of data currently written into the buffer 00225 * @param bufNum Buffer to get size of 00226 */ 00227 #define fip_packet_getBufSize(bufNum) (fip_packet_get().buf[bufNum].usedSize) 00228 00229 /** 00230 * Set the size of data currently written into the buffer 00231 * 00232 * @param bufNum Buffer to get size of 00233 * @param size Size of data to write 00234 */ 00235 #define fip_packet_setBufSize(bufNum, size) (fip_packet_get().buf[bufNum].usedSize = size) 00236 00237 /** 00238 * Get the value of an attribute from the active packet buffer. 00239 * @param attr The attribute to get. Valid values are elements of the @ref fip_packet_t struct. 00240 */ 00241 #define fip_packet_getAttr(attr) fip_packet_get().attr 00242 00243 /** 00244 * Set the value of an attribute to the active packet buffer. 00245 * @param attr The attribute to set. Valid values are elements of the @ref fip_packet_t struct. 00246 * @param value The value to set this attribute to. 00247 */ 00248 #define fip_packet_setAttr(attr, value) fip_packet_get().attr = (value) 00249 00250 00251 /* .srcAddrOffset and .srcAddrLen Access */ 00252 /** @todo PH.4: Improve performance for fixed LL header lengths. */ 00253 /** Set the LL source address, you must have set the srcLLAddrOffset attribute 00254 * before calling this! */ 00255 #define fip_packet_setLLSrcAddr(addr, len) {fip_packet_get().srcLLAddrLen = len; \ 00256 memcpy(fip_packet_get().srcLLAddrOffset + fip_packet_getBufPtr(FIP_LLBUF), addr, len);} 00257 00258 /* .destAddrOffset and .destAddrLen Access */ 00259 /** @todo PH.4: Improve performance for fixed LL header lengths. */ 00260 /** Set the LL dest address, you must have set the destLLAddrOffset attribute 00261 * before calling this! */ 00262 #define fip_packet_setLLDestAddr(addr, len) {fip_packet_get().destLLAddrLen = len; \ 00263 memcpy(fip_packet_get().destLLAddrOffset + fip_packet_getBufPtr(FIP_LLBUF), addr, len);} 00264 00265 /** Set the address flags 00266 * @param type Either 'srcFlags' or 'destFlags' 00267 * @param flag See @ref fip_ip6addr_flags_t for flags 00268 * @param value Value to set 00269 */ 00270 #define fip_packet_setAddrFlags(type, flag, value) (fip_packet_get().type.flag = value) 00271 00272 /** Get the address flags 00273 * @param type Either 'srcFlags' or 'destFlags' 00274 * @param flag See @ref fip_ip6addr_flags_t for flags 00275 */ 00276 #define fip_packet_getAddrFlags(type, flag) fip_packet_get().type.flag 00277 00278 /** Get a pointer to the 'scratchpad', and cast it to a pointer of the type passed */ 00279 #define fip_packet_spGetPtr(type) ((type *)(fip_packet_get().scratchPad)) 00280 00281 #define fip_packet_getFromBuf_Uint8(bufNum, offset) *((uint8_t *)fip_packet_getBufPtr(bufNum) + (offset)) 00282 #define fip_packet_setToBuf_Uint8(bufNum, offset, data) (*((uint8_t *)fip_packet_getBufPtr(bufNum) + (offset)) = data) 00283 /*---------------- Macros which depend on buffer type ---------------------- */ 00284 #ifdef DOXYGEN 00285 /** @def fip_packet_getFromIPBuf_Uint8Unaligned(offset) 00286 * Get a single byte from the IP buffer, the byte located offset 00287 * bytes from the start of the IP buffer. Byte offset is NOT a 32-bit aligned 00288 * address, so this macro will result in "safe" code on platforms that care 00289 * about alignment. 00290 */ 00291 /**@todo make this safe */ 00292 #define fip_packet_getFromBuf_Uint8Unaligned(offset, bufNum) 00293 00294 #elif FIP_CONF_BUFFER_TYPE == FIP_STATIC_SINGLEUSE 00295 extern uint8_t fip_activePacket_buffer[FIP_STATIC_BUF_SIZE]; 00296 extern fip_packet_t fip_activePacket; 00297 00298 #define fip_packet_getPtr() &fip_activePacket 00299 00300 #define fip_packet_get() fip_activePacket 00301 00302 #define fip_packet_getIPBufPtr() &fip_activePacket_buffer[FIP_CONF_LLH_MAX] 00303 00304 /** @todo IPv4.1: Add IPv4 Handling into headers etc */ 00305 #define fip_packet_getFromIPBuf_Uint8Unaligned(offset) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] 00306 #define fip_packet_getFromIPBuf_Uint8Aligned(offset) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] 00307 #define fip_packet_setToIPBuf_Uint8Unaligned(offset,x) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] = (x) 00308 #define fip_packet_setToIPBuf_Uint8Aligned(offset,x) fip_activePacket_buffer[FIP_CONF_LLH_MAX + (offset)] = (x) 00309 00310 #elif FIP_CONF_BUFFER_TYPE == FIP_DYNAMIC 00311 00312 extern fip_packet_t * fip_activePacketPtr; 00313 00314 #define fip_packet_getPtr() fip_activePacketPtr 00315 00316 #define fip_packet_get() (*fip_activePacketPtr) 00317 00318 #define fip_packet_getIPBufPtr() fip_packet_getBufPtr(FIP_IPHDRBUF) 00319 00320 /** @todo IPv4.1: Add IPv4 Handling into headers etc */ 00321 #define fip_packet_getFromIPBuf_Uint8Unaligned(offset) fip_packet_getFromBuf_Uint8(FIP_IPHDRBUF, offset) 00322 #define fip_packet_getFromIPBuf_Uint8Aligned(offset) fip_packet_getFromBuf_Uint8(FIP_IPHDRBUF, offset) 00323 #define fip_packet_setToIPBuf_Uint8Unaligned(offset,x) fip_packet_setToBuf_Uint8(FIP_IPHDRBUF, offset, x) 00324 #define fip_packet_setToIPBuf_Uint8Aligned(offset,x) fip_packet_setToBuf_Uint8(FIP_IPHDRBUF, offset, x) 00325 00326 #else 00327 00328 #error "Unimplemented FIP BUFFER TYPE choosen" 00329 00330 /* Things that need defining */ 00331 00332 #define fip_packet_getPtr() 00333 00334 #define fip_packet_get() 00335 00336 /** @todo IPv4.1: Add IPv4 Handling into headers etc */ 00337 #define fip_packet_getFromIPBuf_Uint8Unaligned(offset) 00338 #define fip_packet_getFromIPBuf_Uint8Aligned(offset) 00339 #define fip_packet_setToIPBuf_Uint8Unaligned(offset,x) 00340 #define fip_packet_setToIPBuf_Uint8Aligned(offset,x) 00341 00342 #define fip_packet_getIPBufPtr() fip_packet_getBufPtr(FIP_IPHBUF) 00343 00344 #endif 00345 00346 00347 /** Get the interface number, available as a separate macro as single-interface systems 00348 * can replace this with a constant */ 00349 #define fip_packet_getIfNum() fip_packet_getAttr(IFNum) 00350 00351 00352 /** @defgroup ipv6packet IPv6 Specific Packet Handling 00353 * @{ */ 00354 00355 /** Get the offset from the start of the IP buffer to the next header. */ 00356 #define fip_packet_getFromIP6Hdr_nhOffset() (6) 00357 00358 /** Get a pointer to the IPv6 Destination Address. WARNING: If you change the IP 00359 * address with this function, you need to reset the associated flags. It is better 00360 * to use the @ref fip_packet_copyToIP6Hdr_destAddr() function. */ 00361 #define fip_packet_getFromIP6Hdr_destPtr() (fip_packet_getIPBufPtr() + 24) 00362 00363 /** Get a single byte from the IPv6 Destination Address. 00364 * @param x Offset of the byte to get. 00365 */ 00366 #define fip_packet_getFromIP6Hdr_destAddr(x) fip_packet_getFromIPBuf_Uint8Unaligned(x + 24) 00367 00368 /** Set a single byte to the IPv6 Destination Address. WARNING: If you change the IP 00369 * address with this function, you need to reset the associated flags. It is better 00370 * to use the @ref fip_packet_copyToIP6Hdr_destAddr() function. 00371 * @param x Offset of the byte to set. 00372 * @param data Byte to set 00373 */ 00374 #define fip_packet_setToIP6Hdr_destAddr(x, data) fip_packet_setToIPBuf_Uint8Unaligned(x + 24, data) 00375 00376 /** Get a pointer to the IPv6 Source Address. WARNING: If you change the IP 00377 * address with this function, you need to reset the associated flags. It is better 00378 * to use the @ref fip_packet_copyToIP6Hdr_srcAddr() function. */ 00379 #define fip_packet_getFromIP6Hdr_srcPtr() (fip_packet_getIPBufPtr() + 8) 00380 00381 /** Get a single byte from the IPv6 Destination Address. 00382 * @param x Offset of the byte to get. 00383 */ 00384 #define fip_packet_getFromIP6Hdr_srcAddr(x) fip_packet_getFromIPBuf_Uint8Unaligned(x + 8) 00385 00386 /** Reset the flags associated with a certain address */ 00387 #define fip_packet_resetAddrFlags(type) {fip_packet_setAddrFlags(type, isMySolicitedNode, tribool_untested); \ 00388 fip_packet_setAddrFlags(type, isUnspecified, tribool_untested); \ 00389 fip_packet_setAddrFlags(type, isLinkLocal, tribool_untested); \ 00390 fip_packet_setAddrFlags(type, isOnLink, tribool_untested); } 00391 00392 /** Get the IP version of this packet, equates to either FIP_IPHDR_V6 or FIP_IPHDR_V4 */ 00393 #define fip_packet_getFromIPHdr_version() (fip_packet_getFromIPBuf_Uint8Aligned(0) & 0xF0) 00394 00395 /** Get the length field of the IPv6 header. */ 00396 #define fip_packet_getFromIP6Hdr_length() (fip_toUint16(fip_packet_getFromIPBuf_Uint8Aligned(4), fip_packet_getFromIPBuf_Uint8Unaligned(5))) 00397 #define fip_packet_getFromIP6Hdr_nextHeader() (fip_packet_getFromIPBuf_Uint8Unaligned(6)) 00398 #define fip_packet_getFromIP6Hdr_hopLimit() (fip_packet_getFromIPBuf_Uint8Unaligned(7)) 00399 00400 /* */ 00401 #define fip_packet_setToIPHdr_versionClobberTC(data) (fip_packet_setToIPBuf_Uint8Aligned(0, data)) 00402 00403 /** Set the length field in the IPv6 header, Handles conversion to network order */ 00404 #define fip_packet_setToIP6Hdr_length(data) {fip_packet_setToIPBuf_Uint8Unaligned(4, fip_Uint16_getMSB(data)); fip_packet_setToIPBuf_Uint8Unaligned(5, fip_Uint16_getLSB(data));} 00405 /** Set the next header field in the IPv6 Header */ 00406 #define fip_packet_setToIP6Hdr_nextHeader(data) (fip_packet_setToIPBuf_Uint8Unaligned(6, data)) 00407 /** Set the hop limit field in the IPv6 Header */ 00408 #define fip_packet_setToIP6Hdr_hopLimit(data) (fip_packet_setToIPBuf_Uint8Unaligned(7, data)) 00409 00410 /** @} */ 00411 /*---------------------------------------------------------------------------*/ 00412 /** @defgroup icmpv6packet ICMPv6 Specific Packet Handling 00413 * @{ */ 00414 00415 /** Get the ICMPv6 'type' in the header */ 00416 #define fip_packet_getFromICMP6Hdr_Type() fip_packet_getFromBuf_Uint8(FIP_TLBUF, 0) 00417 /** Get the ICMPv6 'Code' in the header */ 00418 #define fip_packet_getFromICMP6Hdr_Code() fip_packet_getFromBuf_Uint8(FIP_TLBUF, 1) 00419 /** Set the ICMPv6 'type' in the header */ 00420 #define fip_packet_setToICMP6Hdr_Type(data) fip_packet_setToBuf_Uint8(FIP_TLBUF, 0, data) 00421 /** Set the ICMPv6 'code' in the header */ 00422 #define fip_packet_setToICMP6Hdr_Code(data) fip_packet_setToBuf_Uint8(FIP_TLBUF, 1, data) 00423 /** Set the ICMPv6 'checksum' in the header, converts byte order correctly */ 00424 #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)));} 00425 00426 /** @} */ 00427 /*---------------------------------------------------------------------------*/ 00428 /** 00429 * @} fip_packet 00430 */ 00431 00432 #endif /* FIP_PACKET_H_ */ 00433