static unsigned int add_cmts_mic (unsigned char *tlvbuf, unsigned int tlvbuflen, unsigned char *key, int keylen) { int i; register unsigned char *cp, *dp; unsigned char *cmts_tlvs; unsigned char digest[17]; /* Only these configuration TLVs must be used to calculate the CMTS MIC */ #define NR_CMTS_MIC_TLVS 21 unsigned char digest_order[NR_CMTS_MIC_TLVS] = { 1, 2, 3, 4, 17, 43, 6, 18, 19, 20, 22, 23, 24, 25, 28, 29, 26, 35, 36, 37, 40 }; if (tlvbuf == NULL || tlvbuflen == 0 ) return 0; cmts_tlvs = (unsigned char *) malloc (tlvbuflen + 1); /* Plenty of space */ dp = cmts_tlvs; for (i = 0; i < NR_CMTS_MIC_TLVS; i++) { cp = tlvbuf; while ((unsigned int) (cp - tlvbuf) < tlvbuflen) { if (cp[0] == digest_order[i]) { memcpy (dp, cp, cp[1] + 2); dp = dp + cp[1] + 2; cp = cp + cp[1] + 2; } else { if ( cp[0] == 64 ) { fprintf(stderr, "docsis: warning: TLV64 (length > 255) not allowed in DOCSIS config files\n"); cp = cp + (size_t) ntohs(*((unsigned short *)(cp+1))) + 3; } else { cp = cp + cp[1] + 2; } } } } fprintf (stderr, "##### Calculating CMTS MIC using TLVs:\n"); decode_main_aggregate (cmts_tlvs, dp - cmts_tlvs); fprintf (stderr, "##### End of CMTS MIC TLVs\n"); hmac_md5 (cmts_tlvs, dp - cmts_tlvs, key, keylen, digest); md5_print_digest (digest); tlvbuf[tlvbuflen] = 7; /* CMTS MIC */ tlvbuf[tlvbuflen + 1] = 16; /* length of MD5 digest */ memcpy (&tlvbuf[tlvbuflen + 2], digest, 16); free (cmts_tlvs); return (tlvbuflen + 18); }
void decode_file (char *file) { int ifd; unsigned char *buffer; unsigned int buflen = 0; int rv = 0; struct stat st; if ((ifd = open (file, O_RDONLY)) == -1) { fprintf(stderr, "Error opening binary file %s: %s\n", file, strerror (errno)); exit (-1); } if ((rv = fstat (ifd, &st))) { fprintf(stderr, "Can't stat file %s: %s\n", file, strerror (errno)); exit (-1); } buffer = (unsigned char *) malloc (st.st_size * sizeof (unsigned char) + 1); buflen = read (ifd, buffer, st.st_size); decode_main_aggregate (buffer, buflen); free(buffer); }
int encode_one_file ( char *input_file, char *output_file, unsigned char *key, unsigned int keylen, int encode_docsis, unsigned int hash) { int parse_result=0; unsigned int buflen; unsigned char *buffer; FILE *of; /* It's not an error to specify the input and output as "-". */ if (!strcmp (input_file, output_file) && strcmp (input_file, "-")) { fprintf(stderr, "docsis: Error: source file is the same as destination file\n"); return -1; } parse_result = parse_config_file (input_file, &global_tlvtree_head ); if (parse_result || global_tlvtree_head == NULL) { fprintf(stderr, "Error parsing config file %s\n", input_file); return -1; } /* Check whether we're encoding PacketCable */ if (global_tlvtree_head->docs_code == 254) { fprintf(stderr, "First TLV is MtaConfigDelimiter, forcing PacketCable MTA file.\n"); encode_docsis=0; } /* walk the tree to find out how much memory we need */ /* leave some room for CM MIC, CMTS MIC, pad, and a HUGE PC20 dialplan */ buflen = tlvtreelen (global_tlvtree_head); buffer = (unsigned char *) malloc ( buflen + 255 + 8192 ); buflen = flatten_tlvsubtree(buffer, 0, global_tlvtree_head); #ifdef DEBUG fprintf(stderr, "TLVs found in parsed config file:\n"); decode_main_aggregate (buffer, buflen); #endif if (encode_docsis) { /* CM config file => add CM MIC, CMTS MIC, End-of-Data and pad */ buflen = add_cm_mic (buffer, buflen); buflen = add_cmts_mic (buffer, buflen, key, keylen); buflen = add_eod_and_pad (buffer, buflen); } if (dialplan == 1) { printf("Adding PC20 dialplan from external file.\n"); buflen = add_dialplan (buffer, buflen); } if (hash == 1) { printf("Adding NA ConfigHash to MTA file.\n"); buflen = add_mta_hash (buffer, buflen, hash); } if (hash == 2) { printf("Adding EU ConfigHash to MTA file.\n"); buflen = add_mta_hash (buffer, buflen, hash); } fprintf (stderr, "Final content of config file:\n"); decode_main_aggregate (buffer, buflen); if (!strcmp (output_file, "-")) { of = stdout; } else if ((of = fopen (output_file, "wb")) == NULL) { fprintf (stderr, "docsis: error: can't open output file %s\n", output_file); return -2; } if (fwrite (buffer, 1, buflen, of) != buflen) { fprintf (stderr, "docsis: error: can't write to output file %s\n", output_file); return -2; } fclose (of); free(buffer); return 0; /*free(global_tlvlist->tlvlist); free(global_tlvlist); */ /* TODO free tree */ }