1 /*
2  *  DOCSIS configuration file encoder.
3  *  Copyright (c) 2001 Cornel Ciocirlan, ctrl@users.sourceforge.net.
4  *  Copyright (c) 2002 Evvolve Media SRL,office@evvolve.com
5  *  Copyright (c) 2014 - 2015 Adrian Simionov, daniel.simionov@gmail.com
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License along
18  *  with this program; if not, write to the Free Software Foundation, Inc.,
19  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  *  DOCSIS is a registered trademark of Cablelabs, http://www.cablelabs.com
22  */
23 
24 #include <sys/types.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <netdb.h>
30 
31 #include <math.h>
32 #include <ctype.h>
33 #include <string.h>
34 
35 /* #include "docsis.h" */
36 #include "docsis_decode.h"
37 #include "docsis_globals.h"
38 #include "docsis_snmp.h"
39 #include "ethermac.h"
40 
41 extern unsigned int is_vspecific = FALSE;
42 
43 struct symbol_entry *
find_symbol_by_code_and_pid(unsigned char code,unsigned int pid)44 find_symbol_by_code_and_pid (unsigned char code, unsigned int pid)
45 {
46  int i;
47 
48  for ( i=0; i<NUM_IDENTIFIERS; i++) {
49         if (global_symtable[i].docsis_code == code && global_symtable[i].parent_id == pid) {
50                 return &global_symtable[i];
51         }
52  }
53  return NULL;
54 }
55 
decode_uint(unsigned char * tlvbuf,struct symbol_entry * sym,size_t length)56 void decode_uint (unsigned char *tlvbuf, struct symbol_entry *sym, size_t length)
57 {
58   static unsigned int helper;
59   if (length != sizeof(unsigned int) ) {
60 	fprintf(stderr, "u_int length mismatch\n");
61 	exit(-45);
62   }
63   memset( &helper, 0, sizeof(unsigned int));
64   memcpy( &helper, tlvbuf, length);
65 
66   printf("%s %u;\n", sym->sym_ident, ntohl(helper));
67 }
68 
decode_uint24(unsigned char * tlvbuf,struct symbol_entry * sym,size_t length)69 void decode_uint24 (unsigned char *tlvbuf, struct symbol_entry *sym, size_t length)
70 {
71   printf("%s %d;\n", sym->sym_ident, tlvbuf[0] * 256 * 256 + tlvbuf[1] * 256 + tlvbuf[2]);
72 }
73 
decode_ushort(unsigned char * tlvbuf,symbol_type * sym,size_t length)74 void decode_ushort (unsigned char *tlvbuf, symbol_type *sym, size_t length)
75 {
76   static unsigned short helper;
77   if (length != sizeof(unsigned short) ) {
78         fprintf(stderr, "u_short length mismatch\n");
79         exit(-45);
80   }
81 
82   memset( &helper, 0, length);
83   memcpy( &helper, tlvbuf, length );
84 
85   printf("%s %hu;\n", sym->sym_ident, ntohs(helper));
86 }
87 
decode_uchar(unsigned char * tlvbuf,symbol_type * sym,size_t length)88 void decode_uchar (unsigned char *tlvbuf, symbol_type *sym, size_t length )
89 {
90   printf("%s %hhu;\n", sym->sym_ident, (unsigned char) *tlvbuf );
91 }
92 
decode_ip(unsigned char * tlvbuf,symbol_type * sym,size_t length)93 void decode_ip (unsigned char *tlvbuf, symbol_type *sym, size_t length )
94 {
95   static struct in_addr helper;
96   if (length != sizeof(struct in_addr) ) {
97         fprintf(stderr, "ip address length mismatch\n");
98         exit(-45);
99   }
100 
101   memcpy (&helper, tlvbuf, length );
102   printf("%s %s;\n",
103 	sym->sym_ident, inet_ntoa(helper) );
104 }
105 
decode_ip_list(unsigned char * tlvbuf,symbol_type * sym,size_t length)106 void decode_ip_list (unsigned char *tlvbuf, symbol_type *sym, size_t length )
107 {
108   static struct in_addr helper;
109   unsigned int i;
110   printf("%s ", sym->sym_ident);
111   for ( i=0; i < length / 4; i++) {
112     memcpy (&helper, tlvbuf + i * 4, 4 );
113     printf( "%s", inet_ntoa(helper) );
114     if (i < (length/4) - 1 ) {
115       printf(",");
116     }
117   }
118   printf(";\n");
119 }
120 
decode_ip6(unsigned char * tlvbuf,symbol_type * sym,size_t length)121 void decode_ip6 (unsigned char *tlvbuf, symbol_type *sym, size_t length )
122 {
123   static struct in6_addr helper;
124   char ipstr[INET6_ADDRSTRLEN];
125   if (length != sizeof(struct in6_addr) ) {
126         fprintf(stderr, "ip address length mismatch\n");
127         exit(-45);
128   }
129 
130   memcpy (&helper, tlvbuf, length );
131   fprintf (stdout, "%s %s;\n",
132 	sym->sym_ident, inet_ntop(AF_INET6,tlvbuf,ipstr,sizeof ipstr) );
133 }
134 
decode_ip6_list(unsigned char * tlvbuf,symbol_type * sym,size_t length)135 void decode_ip6_list (unsigned char *tlvbuf, symbol_type *sym, size_t length )
136 {
137   static struct in6_addr helper;
138   char ipstr[INET6_ADDRSTRLEN];
139   unsigned int i;
140   printf("%s ", sym->sym_ident);
141   for ( i=0; i < length / 16; i++) {
142     memcpy (&helper, tlvbuf + i * 16, 16 );
143     printf( "%s", inet_ntop(AF_INET6, tlvbuf + i * 16, ipstr, sizeof ipstr) );
144     if (i < (length/16) - 1 ) {
145       printf(",");
146     }
147   }
148   printf(";\n");
149 }
150 
decode_ip6_prefix_list(unsigned char * tlvbuf,symbol_type * sym,size_t length)151 void decode_ip6_prefix_list (unsigned char *tlvbuf, symbol_type *sym, size_t length )
152 {
153   char ipstr[INET6_ADDRSTRLEN];
154   unsigned int i;
155   printf("%s ", sym->sym_ident);
156   for ( i=0; i < length / 17; i++) {
157     printf( "%s", inet_ntop(AF_INET6, tlvbuf + i * 17, ipstr, sizeof ipstr) );
158     printf( "/%d", tlvbuf[i * 17 + 16] );
159     if (i < (length/17) - 1 ) {
160       printf(",");
161     }
162   }
163   printf(";\n");
164 }
165 
decode_ip_ip6(unsigned char * tlvbuf,symbol_type * sym,size_t length)166 void decode_ip_ip6 (unsigned char *tlvbuf, symbol_type *sym, size_t length )
167 {
168   static char ip6_addr[INET6_ADDRSTRLEN];
169   char ipstr[INET6_ADDRSTRLEN];
170   static struct in_addr ip_addr;
171   if (length == 4 ) {
172     memcpy (&ip_addr, tlvbuf, 4);
173     printf("%s %s;\n", sym->sym_ident, inet_ntoa(ip_addr) );
174   }
175   if (length == 16 ) {
176       memcpy (&ip6_addr, tlvbuf, INET6_ADDRSTRLEN);
177       printf("%s %s;\n", sym->sym_ident, inet_ntop(AF_INET6,ip6_addr,ipstr,sizeof ipstr) );
178   }
179 }
180 
decode_char_ip_ip6(unsigned char * tlvbuf,symbol_type * sym,size_t length)181 void decode_char_ip_ip6 (unsigned char *tlvbuf, symbol_type *sym, size_t length )
182 {
183   static char ip6_addr[INET6_ADDRSTRLEN];
184   char ipstr[INET6_ADDRSTRLEN];
185   static struct in_addr ip_addr;
186   if (length == 5 ) {
187     memcpy (&ip_addr, tlvbuf + 1, 4);
188     printf("%s %s;\n", sym->sym_ident, inet_ntoa(ip_addr) );
189   }
190   if (length == 17 ) {
191       memcpy (&ip6_addr, tlvbuf + 1, INET6_ADDRSTRLEN);
192       printf("%s %s;\n", sym->sym_ident, inet_ntop(AF_INET6,ip6_addr,ipstr,sizeof ipstr) );
193   }
194 }
195 
decode_ip_ip6_port(unsigned char * tlvbuf,symbol_type * sym,size_t length)196 void decode_ip_ip6_port (unsigned char *tlvbuf, symbol_type *sym, size_t length )
197 {
198   static char ip6_addr[INET6_ADDRSTRLEN];
199   char ipstr[INET6_ADDRSTRLEN];
200   static struct in_addr ip_addr;
201   if (length == 6 ) {
202     memcpy (&ip_addr, tlvbuf, 4);
203     printf("%s %s/%d;\n", sym->sym_ident, inet_ntoa(ip_addr), tlvbuf[4] * 256 + tlvbuf[5] );
204   }
205   if (length == 18 ) {
206       memcpy (&ip6_addr, tlvbuf, INET6_ADDRSTRLEN);
207       printf("%s %s/%d;\n", sym->sym_ident, inet_ntop(AF_INET6,ip6_addr,ipstr,sizeof ipstr), tlvbuf[16] * 256 + tlvbuf[17] );
208   }
209 }
210 
decode_lenzero(unsigned char * tlvbuf,symbol_type * sym,size_t length)211 void decode_lenzero (unsigned char *tlvbuf, symbol_type *sym, size_t length )
212 {
213   printf("%s 0x00;\n", sym->sym_ident );
214 }
215 
decode_ether(unsigned char * tlvbuf,symbol_type * sym,size_t length)216 void decode_ether (unsigned char *tlvbuf, symbol_type *sym, size_t length )
217 {
218 
219  if (length != 6 ) {
220         fprintf(stderr, "ethermac length mismatch\n");
221         exit(-45);
222  }
223  printf("%s %s;\n",
224 	sym->sym_ident, ether_ntoa(tlvbuf) );
225 }
226 
decode_dual_qtag(unsigned char * tlvbuf,symbol_type * sym,size_t length)227 void decode_dual_qtag (unsigned char *tlvbuf, symbol_type *sym, size_t length )
228 {
229     if (length != 4 ) {
230         fprintf(stderr, "dual qtag length mismatch\n");
231         exit(-45);
232     }
233     printf("%s %d,%d;\n", sym->sym_ident, tlvbuf[0] * 256 + tlvbuf[1], tlvbuf[2]*256 + tlvbuf[3]);
234 }
235 
decode_char_list(unsigned char * tlvbuf,symbol_type * sym,size_t length)236 void decode_char_list (unsigned char *tlvbuf, symbol_type *sym, size_t length )
237 {
238     unsigned int i;
239     printf("%s ", sym->sym_ident);
240     for (i = 0; i < length; i++) {
241         printf("%d", tlvbuf[i]);
242         if (i < (length - 1) ) {
243             printf(",");
244         }
245     }
246     printf(";\n");
247 }
248 
decode_ethermask(unsigned char * tlvbuf,symbol_type * sym,size_t length)249 void decode_ethermask (unsigned char *tlvbuf, symbol_type *sym, size_t length)
250 {
251 /* the return value of ether_ntoa is a pointer to a static string
252  * in the ether_ntoa function, so we have to print the values in two
253  * "passees" to avoid the 2nd call overwriting the 1st.
254  */
255   if (length != 12 ) {
256         fprintf(stderr, "ethermac_and_mask length mismatch\n");
257         exit(-45);
258   }
259   printf("%s %s/", sym->sym_ident, ether_ntoa(tlvbuf));
260 
261   printf("%s;\n", ether_ntoa(tlvbuf+6));
262 }
263 
decode_md5(unsigned char * tlvbuf,symbol_type * sym,size_t length)264 void decode_md5 (unsigned char *tlvbuf, symbol_type *sym, size_t length)
265 {
266   size_t j=0;
267   if (length != 16 ) {
268         fprintf(stderr, "md5digest length mismatch\n");
269         exit(-45);
270   }
271 
272   printf("/* %s ", sym->sym_ident);
273   for (j=0;j<length;j++)	printf("%02x", tlvbuf[j]);
274 
275   printf("; */\n");
276 }
277 
decode_snmp_wd(unsigned char * tlvbuf,symbol_type * sym,size_t length)278 void decode_snmp_wd (unsigned char *tlvbuf, symbol_type *sym, size_t length )
279 {
280   printf( "%s ", sym->sym_ident);
281 
282   /* last char in this TLV is not part of OID */
283   decode_snmp_oid (tlvbuf, (unsigned int) length-1 );
284 
285   printf(" %d ;\n", (unsigned int) tlvbuf[length-1] );
286 }
287 
decode_oid(unsigned char * tlvbuf,symbol_type * sym,size_t length)288 void decode_oid (unsigned char *tlvbuf, symbol_type *sym, size_t length )
289 {
290   printf("%s ", sym->sym_ident);
291   decode_snmp_oid (tlvbuf,(unsigned int) length );
292   printf(";\n");
293 }
294 
decode_snmp_object(unsigned char * tlvbuf,symbol_type * sym,size_t length)295 void decode_snmp_object (unsigned char *tlvbuf, symbol_type *sym, size_t length )
296 {
297   void *pj = malloc(17);
298   void *pi = malloc(17);
299   void *pk = malloc(15);
300   void *pl = malloc(15);
301   void *pm = malloc(19);
302   void *pn = malloc(19);
303   void *po = malloc(19);
304   void *pp = malloc(19);
305   void *pq = malloc(19);
306   void *pr = malloc(19);
307 
308   if (nohash) {
309     memcpy (pi, "\x30\x26\x06\x0e\x2b\x06\x01\x04\x01\xa3\x0b\x02\x02\x01\x01\x02\x07", 17);
310     memcpy (pj, tlvbuf, 17);
311     if ( *(int*)pi == *(int*)pj ) {
312       printf("/* ");
313       printf("%s ", sym->sym_ident);
314       decode_vbind (tlvbuf, length );
315       printf(" */");
316       printf("\n");
317       return;
318     }
319     memcpy (pk, "\x30\x24\x06\x0c\x2b\x06\x01\x04\x01\xba\x08\x01\x01\x02\x09", 15);
320     memcpy (pl, tlvbuf, 15);
321     if ( *(int*)pk == *(int*)pl ) {
322       printf("/* ");
323       printf("%s ", sym->sym_ident);
324       decode_vbind (tlvbuf, length );
325       printf(" */");
326       printf("\n");
327       return;
328     }
329   }
330 
331   // when dialplan is shorter than 7F
332   memcpy (pm, "\x06\x12\x2b\x06\x01\x04\x01\xa3\x0b\x02\x02\x08\x02\x01\x01\x03\x01\x01\x02", 19);
333   memcpy (pn, tlvbuf + 2, 19);
334 
335   // when dialplan is longer than 7F
336   memcpy (po, "\x06\x12\x2b\x06\x01\x04\x01\xa3\x0b\x02\x02\x08\x02\x01\x01\x03\x01\x01\x02", 19);
337   memcpy (pp, tlvbuf + 4, 19);
338 
339   //special case dialplan between 0x69 and 0x7f
340   memcpy (pq, "\x04\x82", 2);
341   memcpy (pr, tlvbuf + 24, 2);
342 
343   if ( memcmp(pm, pn, 19) == 0 || memcmp(po, pp, 19) == 0 ) {
344     FILE *dialplan = fopen("dialplan.txt", "w");
345     // when dialplan is shorter than 7F
346     if (*(int*)pm == *(int*)pn) {
347       fwrite(tlvbuf+24, sizeof(char), length - 24, dialplan);
348     }
349     // when dialplan is longer than 7F
350     if ( memcmp(po, pp, 19) == 0 ) {
351       if ( memcmp(pq, pr, 2) == 0) {
352         fwrite(tlvbuf+28, sizeof(char), length - 28, dialplan);
353       } else {
354         fwrite(tlvbuf+26, sizeof(char), length - 26, dialplan);
355       }
356     }
357     fclose(dialplan);
358     printf("/* ");
359     printf("PC20 dialplan found, dialplan.txt file created.");
360     printf(" */");
361     printf("\n");
362     return;
363   }
364 
365   printf("%s ", sym->sym_ident);
366   decode_vbind (tlvbuf, length );
367   printf("\n");
368 
369   free(pi);
370   free(pj);
371   free(pk);
372   free(pl);
373   free(pm);
374   free(pn);
375   free(po);
376   free(pp);
377   free(pq);
378   free(pr);
379 }
380 
decode_string(unsigned char * tlvbuf,symbol_type * sym,size_t length)381 void decode_string (unsigned char *tlvbuf, symbol_type *sym, size_t length )
382 {
383  static char helper[TLV_VSIZE];
384 
385 /* helper = (char *) malloc ( ((unsigned int) tlvbuf[1])+1 );  */
386  memset ( helper, 0, length+1);
387  strncpy ( helper, (char *) tlvbuf, length );
388  printf("%s \"%s\";\n", sym->sym_ident, helper );
389 }
390 
decode_strzero(unsigned char * tlvbuf,symbol_type * sym,size_t length)391 void decode_strzero (unsigned char *tlvbuf, symbol_type *sym, size_t length )
392 {
393  char *helper;
394 
395  helper = (char *) malloc ( length +1 );
396  memset ( helper, 0, length+1);
397  strncpy ( helper, (char *) tlvbuf, length );
398  printf("%s \"%s\";\n", sym->sym_ident, helper );
399  free(helper);
400 }
401 
402 
decode_hexstr(unsigned char * tlvbuf,symbol_type * sym,size_t length)403 void decode_hexstr (unsigned char *tlvbuf, symbol_type *sym, size_t length )
404 {
405  char *helper;
406  unsigned int i;
407  unsigned int len;
408  int ff = 0xFF;
409 
410 /* TODO */
411  len =  length;
412  helper = (char *) malloc ( len+1 );
413  memset ( helper, 0, len+1);
414  memcpy ( helper, (char *) tlvbuf, len );
415  printf("%s 0x", sym->sym_ident);
416  for(i=0; i<len; i++) {
417 	printf("%02x", (unsigned char) helper[i]);
418  }
419  printf(";\n");
420  if (!strncmp (sym->sym_ident, "VendorIdentifier", 16)) {
421    if ( (ff != tlvbuf[0]) || (ff != tlvbuf[1]) || (ff != tlvbuf[2]) ) {
422      is_vspecific = TRUE;
423    }
424  }
425  free(helper);
426 }
427 
decode_ushort_list(unsigned char * tlvbuf,symbol_type * sym,size_t length)428 void decode_ushort_list (unsigned char *tlvbuf, symbol_type *sym, size_t length)
429 {
430  char *helper;
431  unsigned int i;
432  unsigned int len;
433 
434  len = length ;
435  helper = (char *) malloc ( len+1 );
436  memset ( helper, 0, len+1);
437  memcpy ( helper, (char *) tlvbuf, len );
438  printf("%s ", sym->sym_ident);
439  if ( len < 2*sym->low_limit || len > 2*sym->high_limit )
440 	printf("/* -- warning: illegal length of buffer --*/");
441 
442  for(i=0; i<len; i=i+2) {
443         printf("%hu", ntohs( (* (unsigned short *) &helper[i])) );
444 	if (i< len-2) printf(",");
445  }
446  printf(";\n");
447  free(helper);
448 }
449 
decode_unknown(unsigned char * tlvbuf,symbol_type * sym,size_t length)450 void decode_unknown (unsigned char *tlvbuf, symbol_type *sym, size_t length )
451 {
452   size_t len=0;
453   char *cp,*value;
454   char hexvalue[514];
455 
456   len = length ;
457   if (len > 256 ) {
458 	fprintf(stderr, "/* ** next TLV is truncated** */"); len = 256;
459   }
460   memset (hexvalue, 0, 514);
461 
462   value = (char *) malloc ( len+1 );
463   memset ( value, 0, len+1);
464   memcpy ( value, (char *) tlvbuf+2, len );
465 
466   cp = value;
467   if ( str_isprint(cp, len) && len > 1 ) {
468 
469 	printf("GenericTLV TlvCode %d TlvString ",
470 			(unsigned int) tlvbuf[0]) ;
471 	printf("\"%s\"; /* tlv length = %zd */", cp, len);
472   } else if ( len > 1 && cp[len-1] == 0 && str_isprint(cp, len-1 ) ) {
473 	printf("GenericTLV TlvCode %d TlvStringZero ",
474                         (unsigned int) tlvbuf[0] ) ;
475 	printf("\"%s\"; /* tlv length = %zd */", cp, len);
476   } else {
477 	printf("GenericTLV TlvCode %d TlvLength %zd TlvValue ",
478 			(unsigned int) tlvbuf[0], len) ;
479   	snprint_hexadecimal ( hexvalue, 514, value, len);
480 
481 	printf("%s;", hexvalue);
482   }
483   printf("\n");
484   free(value);
485 }
486 
decode_special(unsigned char * tlvbuf,symbol_type * sym,size_t length)487 void decode_special (unsigned char *tlvbuf, symbol_type *sym, size_t length )
488 {
489   printf("%s\n", sym->sym_ident);
490 }
491 
decode_aggregate(unsigned char * tlvbuf,symbol_type * sym,size_t length)492 void decode_aggregate (unsigned char *tlvbuf, symbol_type *sym, size_t length )
493 {
494   register unsigned char *cp;
495   symbol_type *current_symbol;
496   unsigned int tlv_llen = 1; /* length of "Length" encoding of current TLV */
497   size_t tlv_vlen; 	/* length of "Value" encoding of current TLV */
498 
499   /* cp = tlvbuf+1+tlv_llen; */ /* skip type,len of parent TLV */
500   cp = tlvbuf;
501 
502   printf("%s\n", sym->sym_ident);
503   __docsis_indent(INDENT_NOOP, TRUE);
504   printf("{\n");
505 
506   __docsis_indent(INDENT_INCREMENT, FALSE);
507 
508 /*  while ( (unsigned int) (cp - tlvbuf +(sizeof(unsigned char))) < (unsigned int) tlvbuf[1] ) { */
509   while ( (unsigned int) (cp - tlvbuf) < (unsigned int) length ) {
510 
511   __docsis_indent(INDENT_NOOP, TRUE);
512   current_symbol = find_symbol_by_code_and_pid (cp[0], sym->id);
513   tlv_vlen = (size_t) cp[1];
514   /* printf("tlvbuf has value: %01x\n", tlvbuf); */
515   if (is_vspecific == TRUE) {
516 	  current_symbol = NULL;
517   }
518   if (current_symbol == NULL) {
519 		decode_unknown(cp, NULL, tlv_vlen );
520   	} else {
521       		current_symbol->decode_func (cp+1+tlv_llen, current_symbol, tlv_vlen);
522   	}
523  	cp = (unsigned char*) cp + 1 + tlv_llen + tlv_vlen; /* skip type, length value */
524   }
525 
526   __docsis_indent(INDENT_DECREMENT, FALSE);
527 
528   __docsis_indent(INDENT_NOOP, TRUE);
529   is_vspecific = FALSE;
530   printf("}\n");
531 }
532 
533 /*
534 ** This is just like decode_aggregate, but it only does symbol lookup
535 ** for the VendorIdentifier which is the only 'known' TLV.
536 **/
537 
decode_vspecific(unsigned char * tlvbuf,symbol_type * sym,size_t length)538 void decode_vspecific (unsigned char *tlvbuf, symbol_type *sym, size_t length )
539 {
540   register unsigned char *cp;
541   symbol_type *first_symbol;
542   unsigned int tlv_llen = 1; /* length of "Length" encoding of current TLV */
543   size_t tlv_vlen; 	/* length of "Value" encoding of current TLV */
544 
545   /*  cp = tlvbuf+1+tlv_llen; */ /* skip type,len of parent TLV */
546   cp = tlvbuf;
547 
548   printf("%s\n", sym->sym_ident);
549   __docsis_indent(INDENT_NOOP, TRUE);
550   printf("{\n");
551 
552   __docsis_indent(INDENT_INCREMENT, FALSE);
553 
554   /* First TLV inside VendorSpecific has to be VendorIdentifier... the rest we don't care */
555 
556   first_symbol = find_symbol_by_code_and_pid (cp[0], sym->id);
557   tlv_vlen = (size_t) cp[1];
558   if (first_symbol == NULL) {
559   		__docsis_indent(INDENT_NOOP, TRUE);
560 		fprintf(stderr, "/* WARNING: Invalid VendorSpecific option - 1st element is NOT VendorIdentifier */\n");
561   		__docsis_indent(INDENT_NOOP, TRUE);
562                 decode_unknown(cp, NULL, tlv_vlen);
563         } else {
564 	/* Symbol found ... check if it's the right one */
565 		if (!strncmp (first_symbol->sym_ident, "VendorIdentifier", 16))
566 		{
567   			__docsis_indent(INDENT_NOOP, TRUE);
568 	                first_symbol->decode_func(cp+1+tlv_llen, first_symbol, tlv_vlen);
569 		}
570 		else
571 		{
572   			__docsis_indent(INDENT_NOOP, TRUE);
573 			fprintf(stderr, "/* Invalid VendorSpecific option - 1st element is NOT VendorIdentifier */");
574   			__docsis_indent(INDENT_NOOP, TRUE);
575 			decode_unknown(cp, NULL, tlv_vlen );
576 		}
577         }
578 
579   cp = (unsigned char*) cp + 1 + tlv_llen + tlv_vlen; /* skip type, length, value */
580 
581   while ( (unsigned int) (cp - tlvbuf) < (unsigned int) length ) {
582 
583   __docsis_indent(INDENT_NOOP, TRUE);
584 
585  	tlv_vlen = (size_t) cp[1];
586         decode_unknown(cp, NULL, tlv_vlen );
587         cp = (unsigned char*) cp + 1 + tlv_llen + tlv_vlen; /* skip type, length, value */
588   }
589 
590   __docsis_indent(INDENT_DECREMENT, FALSE);
591 
592   __docsis_indent(INDENT_NOOP, TRUE);
593   printf("}\n");
594 }
595 
596 /*
597  * This function is needed because we don't have a symbol to call it.
598  * We can't put a "Main" symbol in the symtable because docsis_code is
599  * unsigned char (in struct symbol_entry) and we reserve the values for
600  * DOCSIS use.
601  * It's also a bit different from docsis_aggregate in that docsis_aggregate
602  * takes an aggregate tlvbuf as argument that INCLUDES the "parent" code and
603  * length. On the main aggregate we don't have a code / length.
604  */
605 
decode_main_aggregate(unsigned char * tlvbuf,size_t buflen)606 void decode_main_aggregate (unsigned char *tlvbuf, size_t buflen)
607 {
608 #define TLV_LEN_SIZE 1
609   register unsigned char *cp = NULL;
610   symbol_type *current_symbol;
611   unsigned int tlv_llen = 1; /* length of "Length" encoding of current TLV */
612   unsigned int is_mta = FALSE;
613   size_t tlv_vlen; 	/* length of "Value" encoding of current TLV */
614 
615   cp = tlvbuf;
616 
617   __docsis_indent(INDENT_CLEAR, FALSE);
618 
619   printf("Main \n{\n");
620   __docsis_indent(INDENT_INCREMENT, FALSE);
621 
622   while ( (unsigned int) (cp - tlvbuf) < buflen ) {
623 
624   __docsis_indent(INDENT_NOOP, TRUE);
625 
626   current_symbol = find_symbol_by_code_and_pid (cp[0],0);
627     tlv_llen = 1;
628     tlv_vlen = (size_t) cp[1];
629     if (cp[0] == 254) {
630         is_mta = TRUE;
631     }
632     if (is_mta) {
633         if (cp[0] == 64) {
634             current_symbol = find_symbol_by_code_and_pid (11,0);
635             tlv_llen = 2;
636             tlv_vlen = (size_t) ntohs(*((unsigned short *)(cp+1)));
637         }
638     }
639   if (current_symbol == NULL) {
640 		decode_unknown(cp, NULL, (size_t) cp[1] );
641   	} else {
642       		current_symbol->decode_func (cp+1+tlv_llen, current_symbol, tlv_vlen );
643   	}
644 #ifdef DEBUG
645 	if (cp[0] == 64 )   /* TLV 64 has length encoded as a short */
646 	   printf("/* TLV 64, size %hu */ \n", ntohs(*((unsigned short *)(cp+1))) );
647 #endif
648     cp = (unsigned char*) cp + 1 + tlv_llen + tlv_vlen ; /* type, length, value   */
649   }
650   __docsis_indent(INDENT_DECREMENT, FALSE);
651   printf("}\n");
652 }
653 
654 int
hexadecimal_to_binary(const char * str,unsigned char * bufp)655 hexadecimal_to_binary (const char *str, unsigned char * bufp)
656 {
657   int len, itmp;
658 #ifdef DEBUG
659   printf("Hex string rx'd: %s\n", str);
660 #endif
661   if (!bufp)
662     return -1;
663   if (*str && *str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X'))
664     str += 2;
665   for (len = 0; *str; str++)
666     {
667       if (isspace ((int) *str))
668 	continue;
669       if (!isxdigit ((int) *str))
670 	return -1;
671       len++;
672       if (sscanf (str++, "%2x", &itmp) == 0)
673 	return -1;
674       *bufp++ = itmp;
675       if (!*str)
676 	return -1;		/* odd number of chars is an error */
677     }
678   return len;
679 }
680 
681 int
str_isalpha(const char * str,size_t str_len)682 str_isalpha (const char *str, size_t str_len)
683 {
684   unsigned int i;
685 
686   for (i=0; i<str_len; i++)
687 		if (!(isalnum((int) str[i]) && isprint((int) str[i]) && isascii((int) str[i])) ) return FALSE;
688 
689   return TRUE;
690 }
691 
692 int
str_isprint(const char * str,size_t str_len)693 str_isprint (const char *str, size_t str_len)
694 {
695   unsigned int i;
696 
697   for (i=0; i<str_len; i++)
698 		if (!(isprint((int) str[i]))) return FALSE;
699 
700   return TRUE;
701 }
702 
703 /*
704  * Print a string in hex format output ... for strings that are not alphanumeric, i.e.
705  * HexString, BitString etc
706  * str is the original string
707  * str_len is the length of the original string
708  * outbuf is a pointer to the output buffer
709  */
710 
711 
712 void
snprint_hexadecimal(char * outbuf,size_t outsize,const char * str,size_t str_len)713 snprint_hexadecimal ( char *outbuf, size_t outsize, const char *str, size_t str_len )
714 {
715   unsigned int i;
716   char *cp;
717 
718   cp=outbuf;
719 
720   memset (outbuf, 0, outsize);
721   sprintf(cp, "0x");
722   cp = cp +2*sizeof(char);
723 
724   for (i=0; i<str_len && (unsigned int) (cp-outbuf) < outsize; i++) {
725 	sprintf(cp, "%02x", (unsigned char) str[i]);
726 	cp = cp +2*sizeof(char);
727   }
728 
729 }
730 
731 /* Simple indent handler ... */
732 
__docsis_indent(int opCode,int doPrint)733 void __docsis_indent(int opCode, int doPrint )
734 {
735 	static int numtabs;
736 	int i;
737 
738 	switch (opCode)
739 	{
740 		case INDENT_INCREMENT:
741 			numtabs++;
742 			break;
743 			;;
744 		case INDENT_DECREMENT:
745 			numtabs--;
746 			break;
747 			;;
748 		case INDENT_CLEAR:
749 			numtabs=0;
750 			break;
751 			;;
752 	}
753 
754 	if ( doPrint )
755 	{
756 		for (i=0; i<numtabs; i++) printf("\t");
757 	}
758 }
759 
760