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