|
xorp
|
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__ */