xorp

netstream_access.h

00001 /* -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- */
00002 /* vim:set sts=4 ts=8: */
00003 
00004 /*
00005  * Copyright (c) 2001-2011 XORP, Inc and Others
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License, Version 2, June
00009  * 1991 as published by the Free Software Foundation. Redistribution
00010  * and/or modification of this program under the terms of any other
00011  * version of the GNU General Public License is not permitted.
00012  * 
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016  * see the GNU General Public License, Version 2, a copy of which can be
00017  * found in the XORP LICENSE.gpl file.
00018  * 
00019  * XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020  * http://xorp.net
00021  */
00022 
00023 /*
00024  * $XORP: xorp/mrt/netstream_access.h,v 1.10 2008/10/02 21:57:45 bms Exp $
00025  */
00026 
00027 
00028 #ifndef __MRT_NETSTREAM_ACCESS_H__
00029 #define __MRT_NETSTREAM_ACCESS_H__
00030 
00031 
00032 /*
00033  * A set of macros to get/put data from/to a stream when the fields
00034  * are not 32-bit boundary aligned. Also useful to automatically
00035  * check the boundary of the input/output buffer while accessing it.
00036  */
00037 /*
00038  * Idea taken from Eddy Rusty (eddy@isi.edu).
00039  */
00040 
00041 #include "libxorp/xorp.h"
00042 
00043 #include <sys/types.h>
00044 
00045 
00046 /*
00047  * Constants definitions
00048  */
00049 
00050 /*
00051  * Structures, typedefs and macros
00052  */
00053 /*
00054  * XXX: the data in the stream is ALWAYS in "network order".
00055  *
00056  * The current stream pointer is (uint8_t *)(cp)
00057  *
00058  * XXX: the macros below assume that the code has the following
00059  * labels that can be used to jump and process the particular error:
00060  *  'rcvlen_error' 'buflen_error'
00061  *
00062  * PUT_NET_32  puts "network ordered" 32-bit data to the datastream.
00063  * PUT_HOST_32 puts "host ordered" 32-bit data to the datastream.
00064  * GET_NET_32  gets 32-bit data and keeps it in "network order" in the memory.
00065  * GET_HOST_32 gets 32-bit data, but in the memory it is in "host order".
00066  * The same applies for the 16-bit {PUT,GET}_{NET,HOST}_16
00067  * GET_OCTET and PUT_OCTET get and put a single octet from/to the datastream.
00068  * GET_SKIP(octets,...) skips the next 'octets' from the datastream.
00069  * PUT_SKIP(octets,...) leaves the next 'octets' untouched in the datastream.
00070  * GET_DATA(to, cp, rcvlen, datalen) copies 'datalen' octets from 'cp' to 'to'.
00071  * PUT_DATA(from, cp, buflen, datalen) copies 'datalen' octets from 'from'
00072  *                                     to 'cp'.
00073  */
00074 #define GET_DATA(to, cp, rcvlen, datalen)               \
00075 do {                                    \
00076     if ((size_t)(rcvlen) < (size_t)(datalen))           \
00077         goto rcvlen_error;                  \
00078     memcpy((to), (cp), (datalen));                  \
00079     (rcvlen) -= (datalen);                      \
00080     (cp) += (datalen);                      \
00081 } while (0)
00082 #define PUT_DATA(from, cp, buflen, datalen)             \
00083 do {                                    \
00084     if ((size_t)(buflen) < (size_t)(datalen))           \
00085         goto buflen_error;                  \
00086     memcpy((cp), (from), (datalen));                \
00087     (buflen) -= (datalen);                      \
00088     (cp) += (datalen);                      \
00089 } while (0)
00090 
00091 #define GET_SKIP(octets, cp, rcvlen)                    \
00092 do {                                    \
00093     if ((size_t)(rcvlen) < (size_t)(octets))            \
00094         goto rcvlen_error;                  \
00095     (rcvlen) -= (octets);                       \
00096     (cp) += (octets);                       \
00097 } while (0)
00098 #define PUT_SKIP(octets, cp, buflen)                    \
00099 do {                                    \
00100     if ((size_t)(buflen) < (size_t)(octets))            \
00101         goto buflen_error;                  \
00102     (buflen) -= (octets);                       \
00103     (cp) += (octets);                       \
00104 } while (0)
00105 
00106 #define GET_OCTET(val, cp, rcvlen)                  \
00107 do {                                    \
00108     if ((size_t)(rcvlen) < (size_t)1)               \
00109         goto rcvlen_error;                  \
00110     (rcvlen)--;                         \
00111     ((val) = *(cp)++);                      \
00112 } while (0)
00113 #define PUT_OCTET(val, cp, buflen)                  \
00114 do {                                    \
00115     if ((size_t)(buflen) < (size_t)1)               \
00116         goto buflen_error;                  \
00117     (buflen)--;                         \
00118     (*(cp)++ = (uint8_t)(val));                 \
00119 } while (0)
00120 
00121 #define GET_HOST_16(val, cp, rcvlen)                    \
00122 do {                                    \
00123     register uint16_t v_;                       \
00124                                     \
00125     if ((size_t)(rcvlen) < (size_t)2)               \
00126         goto rcvlen_error;                  \
00127     (rcvlen) -= 2;                          \
00128     v_ = (*(cp)++) << 8;                        \
00129     v_ |= *(cp)++;                          \
00130     (val) = v_;                         \
00131 } while (0)
00132 
00133 #define PUT_HOST_16(val, cp, buflen)                    \
00134 do {                                    \
00135     register uint16_t v_;                       \
00136                                     \
00137     if ((size_t)(buflen) < (size_t)2)               \
00138         goto buflen_error;                  \
00139     (buflen) -= 2;                          \
00140     v_ = (uint16_t)(val);                       \
00141     *(cp)++ = (uint8_t)(v_ >> 8);                   \
00142     *(cp)++ = (uint8_t)v_;                      \
00143 } while (0)
00144 
00145 #if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
00146 #define GET_NET_16(val, cp, rcvlen)                 \
00147 do {                                    \
00148     register uint16_t v_;                       \
00149                                     \
00150     if ((size_t)(rcvlen) < (size_t)2)               \
00151         goto rcvlen_error;                  \
00152     (rcvlen) -= 2;                          \
00153     v_ = *(cp)++;                           \
00154     v_ |= (*(cp)++) << 8;                       \
00155     (val) = v_;                         \
00156 } while (0)
00157 #define PUT_NET_16(val, cp, buflen)                 \
00158 do {                                    \
00159     register uint16_t v_;                       \
00160                                     \
00161     if ((size_t)(buflen) < (size_t)2)               \
00162         goto buflen_error;                  \
00163     (buflen) -= 2;                          \
00164     v_ = (uint16_t)(val);                       \
00165     *(cp)++ = (uint8_t)v_;                      \
00166     *(cp)++ = (uint8_t)(v_ >> 8);                   \
00167 } while (0)
00168 #endif /* LITTLE_ENDIAN {GET,PUT}_NET_16 */
00169 
00170 #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
00171 #define GET_NET_16(val, cp, rcvlen) GET_HOST_16(val, cp, rcvlen)
00172 #define PUT_NET_16(val, cp, buflen) PUT_HOST_16(val, cp, buflen)
00173 #endif /* BIG_ENDIAN {GET,PUT}_NET_16 */
00174 
00175 #define GET_HOST_32(val, cp, rcvlen)                    \
00176 do {                                    \
00177     register uint32_t v_;                       \
00178                                     \
00179     if ((size_t)(rcvlen) < (size_t)4)               \
00180         goto rcvlen_error;                  \
00181     (rcvlen) -= 4;                          \
00182     v_  = (*(cp)++) << 24;                      \
00183     v_ |= (*(cp)++) << 16;                      \
00184     v_ |= (*(cp)++) <<  8;                      \
00185     v_ |= *(cp)++;                          \
00186     (val) = v_;                         \
00187 } while (0)
00188 
00189 #define PUT_HOST_32(val, cp, buflen)                    \
00190 do {                                    \
00191     register uint32_t v_;                       \
00192                                     \
00193     if ((size_t)(buflen) < (size_t)4)               \
00194         goto buflen_error;                  \
00195     (buflen) -= 4;                          \
00196     v_ = (uint32_t)(val);                       \
00197     *(cp)++ = (uint8_t)(v_ >> 24);                  \
00198     *(cp)++ = (uint8_t)(v_ >> 16);                  \
00199     *(cp)++ = (uint8_t)(v_ >>  8);                  \
00200     *(cp)++ = (uint8_t)v_;                      \
00201 } while (0)
00202 
00203 #if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
00204 #define GET_NET_32(val, cp, rcvlen)                 \
00205 do {                                    \
00206     register uint32_t v_;                       \
00207                                     \
00208     if ((size_t)(rcvlen) < (size_t)4)               \
00209         goto rcvlen_error;                  \
00210     (rcvlen) -= 4;                          \
00211     v_  = *(cp)++;                          \
00212     v_ |= (*(cp)++) <<  8;                      \
00213     v_ |= (*(cp)++) << 16;                      \
00214     v_ |= (*(cp)++) << 24;                      \
00215     (val) = v_;                         \
00216 } while (0)
00217 
00218 #define PUT_NET_32(val, cp, buflen)                 \
00219 do {                                    \
00220     register uint32_t v_;                       \
00221                                     \
00222     if ((size_t)(buflen) < (size_t)4)               \
00223         goto buflen_error;                  \
00224     (buflen) -= 4;                          \
00225     v_ = (uint32_t)(val);                       \
00226     *(cp)++ = (uint8_t)v_;                      \
00227     *(cp)++ = (uint8_t)(v_ >>  8);                  \
00228     *(cp)++ = (uint8_t)(v_ >> 16);                  \
00229     *(cp)++ = (uint8_t)(v_ >> 24);                  \
00230 } while (0)
00231 #endif /* LITTLE_ENDIAN {GET,PUT}_HOST_32 */
00232 
00233 #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
00234 #define GET_NET_32(val, cp, rcvlen) GET_HOST_32(val, cp, rcvlen)
00235 #define PUT_NET_32(val, cp, buflen) PUT_HOST_32(val, cp, buflen)
00236 #endif /* BIG_ENDIAN {GET,PUT}_HOST_32 */
00237 
00238 /*
00239  * Global variables
00240  */
00241 
00242 /*
00243  * Global functions prototypes
00244  */
00245 
00246 __BEGIN_DECLS
00247 
00248 __END_DECLS
00249 
00250 #endif /* __MRT_NETSTREAM_ACCESS_H__ */
 All Classes Namespaces Functions Variables Typedefs Enumerations