The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
nbo.h
Go to the documentation of this file.
1 #pragma once
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16  */
17 
18 /** Structures and functions for converting integers to/from network byte order
19  *
20  * @file src/lib/util/nbo.h
21  *
22  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  * @copyright 2022 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24  */
25 RCSIDH(nbo_h, "$Id: f19bb2c0ade062a04d9cc666286dcc534ca3fa3b $")
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #include <freeradius-devel/util/misc.h>
32 
33 /** Write out an unsigned 16bit integer in wire format (big endian)
34  *
35  * @param[out] out Where to write the integer.
36  * @param[in] num to encode.
37  */
38 static inline void fr_nbo_from_uint16(uint8_t out[static sizeof(uint16_t)], uint16_t num)
39 {
40  out[0] = (num >> 8) & 0xff;
41  out[1] = num & 0xff;
42 }
43 
44 /** Write out an unsigned 24bit integer in wire format (big endian)
45  *
46  * @param[out] out Where to write the integer.
47  * @param[in] num to encode.
48  */
49 static inline void fr_nbo_from_uint24(uint8_t out[static 3], uint32_t num)
50 {
51  out[0] = (num >> 16) & 0xff;
52  out[1] = (num >> 8) & 0xff;
53  out[2] = num & 0xff;
54 }
55 
56 /** Write out an unsigned 32bit integer in wire format (big endian)
57  *
58  * @param[out] out Where to write the integer.
59  * @param[in] num to encode.
60  */
61 static inline void fr_nbo_from_uint32(uint8_t out[static sizeof(uint32_t)], uint32_t num)
62 {
63  fr_nbo_from_uint16(out, (uint16_t) (num >> 16));
64  fr_nbo_from_uint16(out + sizeof(uint16_t), (uint16_t) num);
65 }
66 
67 /** Write out an unsigned 64bit integer in wire format (big endian)
68  *
69  * @param[out] out Where to write the integer.
70  * @param[in] num to encode.
71  */
72 static inline void fr_nbo_from_uint64(uint8_t out[static sizeof(uint64_t)], uint64_t num)
73 {
74  fr_nbo_from_uint32(out, (uint32_t)(num >> 32));
75  fr_nbo_from_uint32(out + sizeof(uint32_t), (uint32_t)num);
76 }
77 
78 /** Write out an signed 16bit integer in wire format (big endian)
79  *
80  * @param[out] out Where to write the integer.
81  * @param[in] num to encode.
82  */
83 static inline void fr_nbo_from_int16(uint8_t out[static sizeof(int16_t)], int16_t num)
84 {
85  out[0] = (num >> 8) & 0xff;
86  out[1] = num & 0xff;
87 }
88 
89 /** Write out an signed 32bit integer in wire format (big endian)
90  *
91  * @param[out] out Where to write the integer.
92  * @param[in] num to encode.
93  */
94 static inline void fr_nbo_from_int32(uint8_t out[static sizeof(int32_t)], int32_t num)
95 {
96  fr_nbo_from_uint16(out, (int16_t) (num >> 16));
97  fr_nbo_from_uint16(out + sizeof(int16_t), (int16_t) num);
98 }
99 
100 /** Write out an signed 64bit integer in wire format (big endian)
101  *
102  * @param[out] out Where to write the integer.
103  * @param[in] num to encode.
104  */
105 static inline void fr_nbo_from_int64(uint8_t out[static sizeof(uint64_t)], uint64_t num)
106 {
107  fr_nbo_from_uint32(out, (int32_t)(num >> 32));
108  fr_nbo_from_uint32(out + sizeof(int32_t), (int32_t)num);
109 }
110 
111 /** Write out an unsigned 64bit integer in wire format using the fewest bytes possible
112  *
113  * @param[out] out Where to write big endian encoding of num.
114  * Should be at least 8 bytes.
115  * @param[in] num Number to encode.
116  * @return the number of bytes written to out.
117  */
118 static inline size_t fr_nbo_from_uint64v(uint8_t out[static sizeof(uint64_t)], uint64_t num)
119 {
120  size_t ret;
121  uint8_t swapped[sizeof(uint64_t)];
122 
123  ret = ROUND_UP_DIV((size_t)fr_high_bit_pos(num | 0x80), 8);
124 #ifdef __COVERITY__
125  /*
126  * Coverity doesn't realize that ret is necessarily <= 8,
127  * so we give it a hint.
128  */
129  if (ret > 8) return 0;
130 #endif
131 
132  fr_nbo_from_uint64(swapped, num);
133  memcpy(out, (swapped + (sizeof(uint64_t) - ret)), ret); /* aligned */
134 
135  return ret;
136 }
137 
138 /** Read an unsigned 16bit integer from wire format (big endian)
139  *
140  * @param[in] data To convert to a 16bit unsigned integer of native endianness.
141  * @return a 16 bit unsigned integer of native endianness.
142  */
143 /* coverity[-taint_source : arg-0] */
144 static inline uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
145 {
146  return (((uint16_t)data[0]) << 8) | data[1];
147 }
148 
149 /** Read an unsigned 24bit integer from wire format (big endian)
150  *
151  * @param[in] data To convert to a 24bit unsigned integer of native endianness.
152  * @return a 24 bit unsigned integer of native endianness.
153  */
154 /* coverity[-taint_source : arg-0] */
155 static inline uint32_t fr_nbo_to_uint24(uint8_t const data[static 3])
156 {
157  return (((uint32_t)data[0]) << 16) | (((uint32_t)data[1]) << 8) | data[2];
158 }
159 
160 /** Read an unsigned 32bit integer from wire format (big endian)
161  *
162  * @param[in] data To convert to a 32bit unsigned integer of native endianness.
163  * @return a 32 bit unsigned integer of native endianness.
164  */
165 static inline uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
166 {
167  return ((uint32_t)fr_nbo_to_uint16(data) << 16) | fr_nbo_to_uint16(data + sizeof(uint16_t));
168 }
169 
170 /** Read an unsigned 64bit integer from wire format (big endian)
171  *
172  * @param[in] data To convert to a 64bit unsigned integer of native endianness.
173  * @return a 64 bit unsigned integer of native endianness.
174  */
175 static inline uint64_t fr_nbo_to_uint64(uint8_t const data[static sizeof(uint64_t)])
176 {
177  return ((uint64_t)fr_nbo_to_uint32(data) << 32) | fr_nbo_to_uint32(data + sizeof(uint32_t));
178 }
179 
180 /*
181  * To get signed integers, simply cast.
182  */
183 #define fr_nbo_to_int16(_x) ((int16_t) fr_nbo_to_uint16(_x))
184 #define fr_nbo_to_int32(_x) ((int32_t) fr_nbo_to_uint32(_x))
185 #define fr_nbo_to_int64(_x) ((int64_t) fr_nbo_to_uint64(_x))
186 
187 
188 /** Read an unsigned 64bit integer from wire format (big endian) with a variable length encoding
189  *
190  * @param[in] data Buffer containing the number.
191  * @param[in] data_len Length of number.
192  * @return a 64 bit unsigned integer of native endianness.
193  */
194 static inline uint64_t fr_nbo_to_uint64v(uint8_t const *data, size_t data_len)
195 {
196  uint64_t num = 0;
197  uint64_t nbo;
198 
199  if (unlikely(data_len > sizeof(uint64_t))) return 0;
200 
201  /*
202  * Copy at an offset into memory
203  * allocated for the uin64_t
204  */
205  memcpy(((uint8_t *)&num) + (sizeof(uint64_t) - data_len), data, data_len); /* aligned */
206  fr_nbo_from_uint64((uint8_t *)&nbo, num);
207 
208  return nbo;
209 }
210 
211 static inline uint64_t fr_nbo_to_int64v(uint8_t const *data, size_t data_len)
212 {
213  int64_t num = 0;
214  uint64_t nbo;
215 
216  if (unlikely(data_len > sizeof(uint64_t))) return 0;
217 
218  /*
219  * Copy at an offset into memory
220  * allocated for the uin64_t
221  */
222  memcpy(((uint8_t *)&num) + (sizeof(uint64_t) - data_len), data, data_len); /* aligned */
223  if (*data & 0x80) memset(((uint8_t *)&num) + data_len, 0xff, sizeof(num) - data_len);
224 
225  fr_nbo_from_uint64((uint8_t *)&nbo, num);
226 
227  return nbo;
228 }
229 
230 /** Convert bits (as in prefix length) to bytes, rounding up.
231  *
232  * @param bits number of bits in the prefix
233  * @return number of bytes taken to store the prefix
234  */
235 static inline unsigned int fr_bytes_from_bits(unsigned int bits)
236 {
237  return (bits + 7) >> 3;
238 }
239 
240 #ifdef __cplusplus
241 }
242 #endif
#define RCSIDH(h, id)
Definition: build.h:482
#define unlikely(_x)
Definition: build.h:379
#define ROUND_UP_DIV(_x, _y)
Get the ceiling value of integer division.
Definition: math.h:153
static uint8_t fr_high_bit_pos(uint64_t num)
Find the highest order high bit in an unsigned 64 bit integer.
Definition: math.h:36
unsigned short uint16_t
Definition: merged_model.c:31
unsigned int uint32_t
Definition: merged_model.c:33
unsigned char uint8_t
Definition: merged_model.c:30
static unsigned int fr_bytes_from_bits(unsigned int bits)
Convert bits (as in prefix length) to bytes, rounding up.
Definition: nbo.h:235
static uint64_t fr_nbo_to_uint64(uint8_t const data[static sizeof(uint64_t)])
Read an unsigned 64bit integer from wire format (big endian)
Definition: nbo.h:175
static void fr_nbo_from_uint24(uint8_t out[static 3], uint32_t num)
Write out an unsigned 24bit integer in wire format (big endian)
Definition: nbo.h:49
static uint64_t fr_nbo_to_uint64v(uint8_t const *data, size_t data_len)
Read an unsigned 64bit integer from wire format (big endian) with a variable length encoding.
Definition: nbo.h:194
static size_t fr_nbo_from_uint64v(uint8_t out[static sizeof(uint64_t)], uint64_t num)
Write out an unsigned 64bit integer in wire format using the fewest bytes possible.
Definition: nbo.h:118
static void fr_nbo_from_uint16(uint8_t out[static sizeof(uint16_t)], uint16_t num)
Write out an unsigned 16bit integer in wire format (big endian)
Definition: nbo.h:38
static uint64_t fr_nbo_to_int64v(uint8_t const *data, size_t data_len)
Definition: nbo.h:211
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition: nbo.h:144
static void fr_nbo_from_int32(uint8_t out[static sizeof(int32_t)], int32_t num)
Write out an signed 32bit integer in wire format (big endian)
Definition: nbo.h:94
static void fr_nbo_from_int16(uint8_t out[static sizeof(int16_t)], int16_t num)
Write out an signed 16bit integer in wire format (big endian)
Definition: nbo.h:83
static uint32_t fr_nbo_to_uint24(uint8_t const data[static 3])
Read an unsigned 24bit integer from wire format (big endian)
Definition: nbo.h:155
static void fr_nbo_from_int64(uint8_t out[static sizeof(uint64_t)], uint64_t num)
Write out an signed 64bit integer in wire format (big endian)
Definition: nbo.h:105
static uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
Read an unsigned 32bit integer from wire format (big endian)
Definition: nbo.h:165
static void fr_nbo_from_uint64(uint8_t out[static sizeof(uint64_t)], uint64_t num)
Write out an unsigned 64bit integer in wire format (big endian)
Definition: nbo.h:72
static void fr_nbo_from_uint32(uint8_t out[static sizeof(uint32_t)], uint32_t num)
Write out an unsigned 32bit integer in wire format (big endian)
Definition: nbo.h:61
static fr_slen_t data
Definition: value.h:1265
static size_t char ** out
Definition: value.h:997