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: 717897c598acb0c15b64276c8ba13b4eddd5a8e7 $")
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 
125  fr_nbo_from_uint64(swapped, num);
126  memcpy(out, (swapped + (sizeof(uint64_t) - ret)), ret); /* aligned */
127 
128  return ret;
129 }
130 
131 /** Read an unsigned 16bit integer from wire format (big endian)
132  *
133  * @param[in] data To convert to a 16bit unsigned integer of native endianness.
134  * @return a 16 bit unsigned integer of native endianness.
135  */
136 /* coverity[-taint_source : arg-0] */
137 static inline uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
138 {
139  return (((uint16_t)data[0]) << 8) | data[1];
140 }
141 
142 /** Read an unsigned 24bit integer from wire format (big endian)
143  *
144  * @param[in] data To convert to a 24bit unsigned integer of native endianness.
145  * @return a 24 bit unsigned integer of native endianness.
146  */
147 /* coverity[-taint_source : arg-0] */
148 static inline uint32_t fr_nbo_to_uint24(uint8_t const data[static 3])
149 {
150  return (((uint32_t)data[0]) << 16) | (((uint32_t)data[1]) << 8) | data[2];
151 }
152 
153 /** Read an unsigned 32bit integer from wire format (big endian)
154  *
155  * @param[in] data To convert to a 32bit unsigned integer of native endianness.
156  * @return a 32 bit unsigned integer of native endianness.
157  */
158 static inline uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
159 {
160  return ((uint32_t)fr_nbo_to_uint16(data) << 16) | fr_nbo_to_uint16(data + sizeof(uint16_t));
161 }
162 
163 /** Read an unsigned 64bit integer from wire format (big endian)
164  *
165  * @param[in] data To convert to a 64bit unsigned integer of native endianness.
166  * @return a 64 bit unsigned integer of native endianness.
167  */
168 static inline uint64_t fr_nbo_to_uint64(uint8_t const data[static sizeof(uint64_t)])
169 {
170  return ((uint64_t)fr_nbo_to_uint32(data) << 32) | fr_nbo_to_uint32(data + sizeof(uint32_t));
171 }
172 
173 /*
174  * To get signed integers, simply cast.
175  */
176 #define fr_nbo_to_int16(_x) ((int16_t) fr_nbo_to_uint16(_x))
177 #define fr_nbo_to_int32(_x) ((int32_t) fr_nbo_to_uint32(_x))
178 #define fr_nbo_to_int64(_x) ((int64_t) fr_nbo_to_uint64(_x))
179 
180 
181 /** Read an unsigned 64bit integer from wire format (big endian) with a variable length encoding
182  *
183  * @param[in] data Buffer containing the number.
184  * @param[in] data_len Length of number.
185  * @return a 64 bit unsigned integer of native endianness.
186  */
187 static inline uint64_t fr_nbo_to_uint64v(uint8_t const *data, size_t data_len)
188 {
189  uint64_t num = 0;
190  uint64_t nbo;
191 
192  if (unlikely(data_len > sizeof(uint64_t))) return 0;
193 
194  /*
195  * Copy at an offset into memory
196  * allocated for the uin64_t
197  */
198  memcpy(((uint8_t *)&num) + (sizeof(uint64_t) - data_len), data, data_len); /* aligned */
199  fr_nbo_from_uint64((uint8_t *)&nbo, num);
200 
201  return nbo;
202 }
203 
204 static inline uint64_t fr_nbo_to_int64v(uint8_t const *data, size_t data_len)
205 {
206  int64_t num = 0;
207  uint64_t nbo;
208 
209  if (unlikely(data_len > sizeof(uint64_t))) return 0;
210 
211  /*
212  * Copy at an offset into memory
213  * allocated for the uin64_t
214  */
215  memcpy(((uint8_t *)&num) + (sizeof(uint64_t) - data_len), data, data_len); /* aligned */
216  if (*data & 0x80) memset(((uint8_t *)&num) + data_len, 0xff, sizeof(num) - data_len);
217 
218  fr_nbo_from_uint64((uint8_t *)&nbo, num);
219 
220  return nbo;
221 }
222 
223 /** Convert bits (as in prefix length) to bytes, rounding up.
224  *
225  * @param bits number of bits in the prefix
226  * @return number of bytes taken to store the prefix
227  */
228 static inline unsigned int fr_bytes_from_bits(unsigned int bits)
229 {
230  return (bits + 7) >> 3;
231 }
232 
233 #ifdef __cplusplus
234 }
235 #endif
#define RCSIDH(h, id)
Definition: build.h:445
#define unlikely(_x)
Definition: build.h:378
#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:228
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:168
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:187
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:204
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:137
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:148
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:158
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:1259
static size_t char ** out
Definition: value.h:984