1 #include <libfb/fb_lib.h>
2
3 #ifdef HAVE_TIME_H
4 # include <time.h>
5 #endif
6
7 #ifdef HAVE_STDLIB_H
8 # include <stdlib.h>
9 #endif
10
11 /** @file utility.c
12 *
13 * @brief Utility functions, such as formatting and print functions
14 *
15 */
16
17 /** Map a FEATURE to the build number where this feature set begins. */
18 const uint16_t buildnum_featureset[FEATURE_MAX] = { 35, 36 };
19
20 /** @brief print a MAC address in a familiar format
21 *
22 * @param output the stream to print to (i.e. stdout)
23 * @param mac the MAC address to print
24 */
25 void
fprint_mac(FILE * output,const volatile unsigned char * mac)26 fprint_mac (FILE * output, const volatile unsigned char *mac)
27 {
28 fprintf (output, "%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2],
29 mac[3], mac[4], mac[5]);
30 }
31
32 /** @brief print a MAC address in a familiar format to stdout
33 *
34 * @param mac the MAC address to print
35 */
36 void
print_mac(const volatile unsigned char * mac)37 print_mac (const volatile unsigned char *mac)
38 {
39 fprint_mac (stdout, mac);
40 }
41
42 /** @brief print an IP address in a familiar format
43 *
44 * @param stream the stream to print to (i.e. stdout)
45 * @param ip the IP address to print
46 */
47 void
fprint_ip(FILE * stream,uint32_t ip)48 fprint_ip (FILE * stream, uint32_t ip)
49 {
50 fprintf (stream, "%d.%d.%d.%d\n", ip & 0xFF, (ip & 0xFF00) >> 8,
51 (ip & 0xFF0000) >> 16, (ip & 0xFF000000) >> 24);
52 }
53
54 /** @brief print an IP address in a familiar format to stdout
55 *
56 * @param ip the IP address to print
57 */
58 void
print_ip(uint32_t ip)59 print_ip (uint32_t ip)
60 {
61 fprint_ip (stdout, ip);
62 }
63
64
65 /** @brief calculate the CRC16 of a buffer
66 *
67 * @param buf the buffer
68 * @param len the length of the buffer
69 * @return the calculated CRC16
70 */
71 unsigned short
crc_16(unsigned char * buf,int len)72 crc_16 (unsigned char *buf, int len)
73 {
74 /* CRC16-CCITT */
75 unsigned short i, crc;
76 unsigned char xor, slice, bit, align;
77
78 #ifdef DEBUG
79 fprintf (stderr, "{crc_16: len(%d)}\n", len);
80 #endif
81 crc = 0xFFFF;
82 for (i = 0; i < len; i++)
83 {
84 slice = buf[i];
85 align = 0x80;
86 for (bit = 0; bit < 8; bit++)
87 {
88 if (crc & 0x8000)
89 xor = 1;
90 else
91 xor = 0;
92 crc = crc << 1;
93 if (slice & align)
94 crc = crc + 1;
95 if (xor)
96 crc = crc ^ CRCPOLY;
97 align = align >> 1;
98 }
99 }
100
101 for (bit = 0; bit < 16; bit++)
102 {
103 if (crc & 0x8000)
104 xor = 1;
105 else
106 xor = 0;
107 crc = crc << 1;
108 if (xor)
109 crc = crc ^ CRCPOLY;
110 }
111 return crc;
112 }
113
114
115 /* @brief Parse a MAC address into raw 6-byte memory location
116 *
117 * Takes src_mac in ASCII format (AABBCCDDEEFF) or colon-delimited
118 * (AA:BB:CC:DD:EE:FF) and translates to dst_mac
119 *
120 * @param src_mac null terminated string representing a MAC address.
121 * @param dst_mac destination memory location, must be at least 6 bytes
122 * @return 0 on success and non-zero otherwise. long.
123 */
124 int
parse_mac(char * src_mac,unsigned char * dst_mac)125 parse_mac (char *src_mac, unsigned char *dst_mac)
126 {
127 char hex[2];
128 int x, y;
129 int result = 0;
130 if (strchr (src_mac, ':') == NULL)
131 {
132 if (src_mac[0] == '\n')
133 return -1;
134
135 for (x = 0, y = 0; x < 6; x++)
136 {
137 hex[0] = src_mac[y++];
138 hex[1] = src_mac[y++];
139 dst_mac[x] = strtol (hex, NULL, 16);
140 }
141 }
142 else
143 {
144 /* Assume we are colon delimited */
145 result = sscanf (src_mac, "%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX",
146 &dst_mac[0], &dst_mac[1], &dst_mac[2], &dst_mac[3],
147 &dst_mac[4], &dst_mac[5]);
148 if (result == 6) /* 6 would imply success here. */
149 result = 0;
150 }
151 return result;
152 }
153
154
155 /** @brief print the current time to a stream
156 * @param output the stream to print to
157 */
158 void
print_current_time(FILE * output)159 print_current_time (FILE * output)
160 {
161 struct tm *time_info;
162 time_t calendar_time;
163
164 calendar_time = time (NULL);
165 time_info = localtime (&calendar_time);
166 fprintf (output, "Time: [%d/%d/%d %d:%d:%d]\n", time_info->tm_mon + 1,
167 time_info->tm_mday, time_info->tm_year + 1900, time_info->tm_hour,
168 time_info->tm_min, time_info->tm_sec);
169 }
170
171 /** @brief pack a 32-bit value into an 8-bit memory
172 * @param val the value to pack
173 * @param dst the destination memory location
174 */
175 void
store32(u_int32_t val,u_int8_t * dst)176 store32 (u_int32_t val, u_int8_t * dst)
177 {
178 dst[0] = val & 0xff;
179 dst[1] = val >> 8;
180 dst[2] = val >> 16;
181 dst[3] = val >> 24;
182 }
183
184 /** @brief unpack a 32-bit value from 8-bit memory
185 * @param src the 8-bit memory start location
186 * @return unpacked 32-bit value
187 */
188 u_int32_t
grab32(const volatile u_int8_t * src)189 grab32 (const volatile u_int8_t * src)
190 {
191 return ((src[0] & 0xff) | (src[1] << 8) | (src[2] << 16) | (src[3] << 24));
192 }
193
194 /** @brief unpack a 16-bit value from 8-bit memory
195 * @param src the 8-bit memory start location
196 * @return unpacked 16-bit value
197 */
198 u_int16_t
grab16(const volatile u_int8_t * src)199 grab16 (const volatile u_int8_t * src)
200 {
201 return ((src[0] & 0xff) | (src[1] << 8));
202 }
203
204 /** @brief pack a 16-bit value into an 8-bit memory
205 * @param val the value to pack
206 * @param dst the destination memory location
207 */
208 void
store16(u_int16_t val,u_int8_t * dst)209 store16 (u_int16_t val, u_int8_t * dst)
210 {
211 dst[0] = val & 0xff;
212 dst[1] = val >> 8;
213 }
214
215 /*********** Span configuration (informational) functions ************/
216
217 /** @brief Print the configuration of a T1/E1/J1 span
218 * @param link the link configuration
219 * @param output the stream to print to
220 */
221 void
print_span_mode_idtlink(IDT_LINK_CONFIG link,FILE * output)222 print_span_mode_idtlink (IDT_LINK_CONFIG link, FILE * output)
223 {
224 if (link.E1Mode)
225 {
226 fprintf (output, "E1");
227 if (link.CRCMF)
228 fprintf (output, " (CRC4)");
229 }
230 else
231 {
232 fprintf (output, "T1");
233 if (link.framing)
234 fprintf (output, ",ESF");
235 else
236 fprintf (output, ",SF");
237 }
238
239 if (link.encoding)
240 fprintf (output, ",AMI");
241 else if (link.E1Mode)
242 fprintf (output, ",HDB3");
243 else
244 fprintf (output, ",B8ZS");
245
246 if (link.rbs_en)
247 fprintf (output, ",RBS");
248
249 if (link.rlb)
250 fprintf (output, ",RLB");
251
252 if (link.EQ)
253 fprintf (output, ",EQ");
254
255 if (link.HDLC == 0x3)
256 fprintf (output, ",HARDHDLC");
257
258 fprintf (output, "\n");
259 }
260
261
262 /** @brief print the value of a span mode mask
263 * @deprecated span mode masked are no longer used
264 *
265 * @param mode the span mode mask
266 * @param output the stream to print to
267 */
268 void
print_span_mode(unsigned char mode,FILE * output)269 print_span_mode (unsigned char mode, FILE * output)
270 {
271 if (mode & SPAN_MODE_E1)
272 {
273 fprintf (output, "E1");
274 if (mode & SPAN_MODE_CRCMF)
275 fprintf (output, " (CRC4)");
276 }
277 else
278 {
279 fprintf (output, "T1");
280 if (mode & SPAN_MODE_ESF)
281 fprintf (output, ",ESF");
282 else
283 fprintf (output, ",SF");
284 }
285
286
287 if (mode & SPAN_MODE_AMI)
288 fprintf (output, ",AMI");
289 else if (mode & SPAN_MODE_E1)
290 fprintf (output, ",HDB3");
291 else
292 fprintf (output, ",B8ZS");
293
294 if (mode & SPAN_MODE_RBS)
295 fprintf (output, ",RBS");
296
297 if (mode & SPAN_MODE_RLB)
298 fprintf (output, ",RLB");
299
300 if (mode & SPAN_MODE_EQ)
301 fprintf (output, ",EQ");
302
303 fprintf (output, "\n");
304 }
305
306 /* Randomness and Key Generation Function */
307
308 /* We should really use the entire value returned by rand() for larger
309 * key generation. Multiple calls are bad and some platforms do not
310 * have much randomness in the lowest bytes.
311 */
312
313 /** @brief get a random byte
314 * @return a random byte
315 */
316 uint8_t
fblib_get_random_byte(void)317 fblib_get_random_byte (void)
318 {
319 static int initalized = 0;
320
321 if (!initalized)
322 {
323 srand (time (NULL));
324 initalized = 1;
325 }
326
327 return (rand () & 0xFF);
328 }
329
330 /** @brief Write a 32-byte random seed into a buffer
331 * @param buffer the buffer to write to, must be at least 32 bytes long
332 */
333 void
fblib_write_seed(uint8_t * buffer)334 fblib_write_seed (uint8_t * buffer)
335 {
336 int i;
337
338 if (buffer == NULL)
339 return;
340
341 for (i = 0; i < 32; i++)
342 buffer[i] = fblib_get_random_byte ();
343
344 return;
345 }
346
347 /** @brief print a key data structure
348 * @param stream the stream to print to
349 * @param key the key to print
350 *
351 * @return the number of bytes printed
352 */
353 int
libfb_fprint_key(FILE * stream,KEY_ENTRY * key)354 libfb_fprint_key (FILE * stream, KEY_ENTRY * key)
355 {
356 int i;
357 int len = 0;
358
359 /* Hash Key */
360 len += fprintf (stream, "\tHASH_KEY = 0x");
361
362 for (i = 0; i < HASH_KEY_SZ; i++)
363 len += fprintf (stream, "%02X", key->hash_key[i]);
364 len += fprintf (stream, ";\n");
365
366 /* Customer Key */
367 len += fprintf (stream, "\tCUSTOMER_KEY = 0x");
368
369 for (i = 0; i < CUSTOMER_KEY_SZ; i++)
370 len += fprintf (stream, "%02X", key->customer_key[i]);
371 len += fprintf (stream, ";\n");
372
373 return len;
374 }
375
376 /** @brief Returns the feature set the device being configured supports
377 *
378 * @return the feature set
379 */
380 FEATURE
libfb_feature_set(DOOF_STATIC_INFO * dsi)381 libfb_feature_set (DOOF_STATIC_INFO * dsi)
382 {
383 uint16_t buildnum = dsi->build_num;
384
385 if (IS_FEATURE_2_0 (buildnum))
386 return FEATURE_2_0;
387 else if (IS_FEATURE_PRE_2_0 (buildnum))
388 return FEATURE_PRE_2_0;
389 else
390 {
391 return FEATURE_MAX;
392 }
393 }
394
395
396 /** @brief Selected PMON registers for T1 ESF */
397 const libfb_PMONRegister libfb_regs_T1ESF[] = {
398 {"LCV", "Bipolar Violation/Code Violation", 0x08, 16, 2, NULL},
399 {"FER", "Frame Alignment Bit Error", 0x02, 12, 2, NULL},
400 {"CRCE", "CRC-6 Error", 0x00, 10, 2, NULL},
401 {"OOF", "Out of ESF Synchronization", 0x05, 5, 1, NULL},
402 {NULL, NULL, 0, 0, 0, NULL}
403 };
404
405
406 /** @brief Selected PMON registers for T1 SF */
407 const libfb_PMONRegister libfb_regs_T1SF[] = {
408 {"LCV", "Bipolar Violation/Code Violation", 0x08, 16, 2, NULL},
409 {"FER", "F Bit Error", 0x02, 12, 2, NULL},
410 {"OOF", "Out of ESF Synchronization", 0x05, 5, 1, NULL},
411 {NULL, NULL, 0, 0, 0, NULL}
412 };
413
414 /** @brief Selected PMON registers for E1 */
415 const libfb_PMONRegister libfb_regs_E1[] = {
416 {"LCV", "Bipolar Violation/Code Violation", 0x8, 16, 2, NULL},
417 {"FER", "FAS/NFAS Bit/Pattern Error", 0x02, 12, 2, NULL},
418 {"CRCE", "CRC-4 Error", 0x00, 10, 2, NULL},
419 {"FEBE", "Far End Block Error", 0x0C, 10, 2, NULL},
420 {"OOF", "Out of Basic Frame Synchronization", 0x05, 5, 1, NULL},
421 {NULL, NULL, 0, 0, 0, NULL}
422 };
423