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