123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- /*
- * DOCSIS configuration file encoder.
- * Copyright (c) 2001,2005 Cornel Ciocirlan, ctrl@users.sourceforge.net.
- * Copyright (c) 2002,2003,2004,2005 Evvolve Media SRL,office@evvolve.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * DOCSIS is a registered trademark of Cablelabs, http://www.cablelabs.com
- */
- #include <netdb.h>
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <fcntl.h>
- #include <math.h>
- #include "docsis_common.h"
- #include "docsis_encode.h"
- #include "docsis_snmp.h"
- #include "ethermac.h"
- extern unsigned int line; /* defined in docsis_lex.l */
- int encode_uint ( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- unsigned int int_value;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_uint called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_uint called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- if ( sym_ptr->low_limit || sym_ptr->high_limit ) {
- if ( helper->uintval < sym_ptr->low_limit || helper->uintval > sym_ptr->high_limit ) {
- fprintf(stderr, "docsis: at line %d, %s value %d out of range %hd-%hd\n ", line,sym_ptr->sym_ident,helper->uintval,sym_ptr->low_limit, sym_ptr->high_limit);
- exit(-15);
- }
- }
- int_value = htonl( helper->uintval );
- #ifdef DEBUG
- fprintf(stderr, "encode_uint: found %s value %d\n",sym_ptr->sym_ident, helper->uintval);
- #endif /* DEBUG */
- memcpy ( buf,&int_value, sizeof(unsigned int));
- return ( sizeof(unsigned int));
- }
- int encode_ushort ( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- unsigned short sint;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_ushort called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_ushort called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- if ( sym_ptr->low_limit || sym_ptr->high_limit ) {
- if ( helper->uintval < sym_ptr->low_limit || helper->uintval > sym_ptr->high_limit ) {
- fprintf(stderr, "docsis: at line %d, %s value %d out of range %hd-%hd\n ", line,sym_ptr->sym_ident,helper->uintval,sym_ptr->low_limit, sym_ptr->high_limit);
- exit(-15);
- }
- }
- sint = htons( (unsigned short) helper->uintval );
- #ifdef DEBUG
- fprintf(stderr, "encode_ushort: found %s value %hd\n",sym_ptr->sym_ident, helper->uintval);
- #endif /* DEBUG */
- memcpy ( buf,&sint,sizeof(unsigned short));
- return ( sizeof(unsigned short));
- }
- int encode_uchar ( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- unsigned int int_value;
- char *cp;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_uchar called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_uchar called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- int_value = htonl( helper->uintval );
- if ( sym_ptr->low_limit || sym_ptr->high_limit ) {
- if ( helper->uintval < sym_ptr->low_limit || helper->uintval > sym_ptr->high_limit ) {
- fprintf(stderr, "docsis: at line %d, %s value %d out of range %hd-%hd\n ", line,sym_ptr->sym_ident,helper->uintval,sym_ptr->low_limit, sym_ptr->high_limit);
- exit(-15);
- }
- }
- cp = (char *)&int_value;
- buf[0]=(unsigned char)cp[3];
- #ifdef DEBUG
- fprintf(stderr, "encode_uchar: found %s value %hd\n",sym_ptr->sym_ident, helper->uintval);
- #endif
- return ( sizeof(unsigned char));
- }
- int encode_ip( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- struct in_addr in;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_ip called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_ip called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- if ( !inet_aton ( helper->strval, &in) ) {
- fprintf(stderr, "Invalid IP address %s at line %d", helper->strval, line );
- exit (-1);
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_ip: found %s at line %d\n",inet_ntoa(in), line);
- #endif /* DEBUG */
- memcpy ( buf, &in, sizeof(struct in_addr));
- free(helper->strval);
- return ( sizeof(struct in_addr));
- }
- int encode_ip6( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- struct in6_addr in;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_ip called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_ip called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- if ( !inet_pton(AF_INET6, helper->strval, &in) ) {
- fprintf(stderr, "Invalid IP address %s at line %d\n", helper->strval, line );
- exit (-1);
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_ip: found %s at line %d\n",inet_ntoa(in), line);
- #endif /* DEBUG */
- memcpy ( buf, &in, sizeof(struct in6_addr));
- free(helper->strval);
- return ( sizeof(struct in6_addr));
- }
- int encode_ip_ip6( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- struct in6_addr in6;
- struct in_addr in;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- helper = (union t_val *) tval;
- if ( inet_pton(AF_INET6, helper->strval, &in6) ) {
- memcpy ( buf, &in6, sizeof(struct in6_addr));
- free(helper->strval);
- return ( sizeof(struct in6_addr));
- } else if ( inet_aton ( helper->strval, &in) ) {
- memcpy ( buf, &in, sizeof(struct in_addr));
- free(helper->strval);
- return ( sizeof(struct in_addr));
- } else {
- fprintf(stderr, "Invalid IP address %s at line %d\n", helper->strval, line );
- exit (-1);
- }
- }
- int encode_char_ip_ip6( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- struct in6_addr in6;
- struct in_addr in;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
-
- char ipv4 = 1;
- char ipv6 = 2;
- helper = (union t_val *) tval;
- if ( inet_pton(AF_INET6, helper->strval, &in6) ) {
- memcpy ( buf, &ipv6, sizeof(char) );
- memcpy ( buf + 1, &in6, sizeof(struct in6_addr));
- free(helper->strval);
- return ( sizeof(char) + sizeof(struct in6_addr));
- } else if ( inet_aton ( helper->strval, &in) ) {
- memcpy ( buf, &ipv4, sizeof(char) );
- memcpy ( buf + 1, &in, sizeof(struct in_addr));
- free(helper->strval);
- return ( sizeof(char) + sizeof(struct in_addr));
- } else {
- fprintf(stderr, "Invalid IP address %s at line %d\n", helper->strval, line );
- exit (-1);
- }
- }
- int encode_lenzero( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- return (0);
- }
- int encode_ether ( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- int retval; /* return value of inet_aton */
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_ether called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_ether called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- if (!(retval = ether_aton ( helper->strval, buf)) ) {
- fprintf(stderr, "Invalid MAC address %s at line %d", helper->strval, line );
- exit (-1);
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_ether: found %s at line %d\n", ether_ntoa(buf), line);
- #endif /* DEBUG */
- free(helper->strval);
- return retval; /* hopefully this equals 6 :) */
- }
- int encode_dual_qtag ( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- int i, final;
- char *token;
- char *array[2];
- const char s[2] = ",";
- union t_val *helper;
- #ifdef DEBUG
- fprintf(stderr, "encode_dual_qtag: found '%s' on line %d\n", helper->strval, line );
- #endif /* DEBUG */
- helper = (union t_val *) tval;
- i = 0;
- token = strtok(helper->strval, s);
- while (token != NULL)
- {
- array[i++] = token;
- token = strtok (NULL, s);
- }
- final = htonl(atoi(array[0]) << 16 | atoi(array[1]));
- memcpy (buf, &final, sizeof(final));
- free(helper->strval);
- return (sizeof(final));
- }
- int encode_dual_int ( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- short int i, final;
- char *token;
- char *array[2];
- const char s[2] = ",";
- union t_val *helper;
- #ifdef DEBUG
- fprintf(stderr, "encode_dual_int: found '%s' on line %d\n", helper->strval, line );
- #endif /* DEBUG */
- helper = (union t_val *) tval;
- i = 0;
- token = strtok(helper->strval, s);
- while (token != NULL)
- {
- array[i++] = token;
- token = strtok (NULL, s);
- }
- final = htons(atoi(array[0]) << 8 | atoi(array[1]));
- memcpy (buf, &final, sizeof(final));
- free(helper->strval);
- return(sizeof(final));
- }
- int encode_ethermask ( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- int reta, retb; /* return value of ether_aton */
- char *ether,*mask;
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_ethermask called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_ethermask called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- ether = helper -> strval;
- mask = strchr ( ether, (int) '/');
- if (mask == NULL) {
- fprintf(stderr, "encode_ethermask: at line %d, format should be <mac_address>/<mac_mask>\n", line);
- exit (-1);
- }
- mask[0]=0x0; mask++; /* cut the string in two */
- if (!(reta = ether_aton ( ether, buf)) ) {
- fprintf(stderr, "Invalid MAC address %s at line %d\n", ether, line );
- exit (-1);
- }
- if (!(retb = ether_aton ( mask, buf+reta*(sizeof(char))) ) ) {
- fprintf(stderr, "Invalid MAC address %s at line %d\n", mask, line );
- exit (-1);
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_ethermask: found %s/%s at line %d\n", ether_ntoa(buf), ether_ntoa(buf+reta*sizeof(char)), line);
- #endif /* DEBUG */
- free(helper->strval);
- return (reta+retb); /* hopefully this equals 12 :) */
- }
- int encode_string(unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- unsigned int string_size;
- /* We only use this to cast the void* we receive to what we think it should be */
- union t_val *helper;
- if ( buf == NULL ) {
- fprintf(stderr, "encode_string called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_string called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- string_size = strlen ( helper->strval );
- if (sym_ptr->low_limit || sym_ptr->high_limit) {
- if ( string_size < sym_ptr->low_limit ) {
- fprintf(stderr, "encode_string: String too short, must be min %d chars\n",
- sym_ptr->low_limit);
- exit(-1);
- }
- if ( sym_ptr->high_limit < string_size ) {
- fprintf(stderr, "encode_string: String too long (%d chars), must be max %d chars\n",
- string_size, sym_ptr->high_limit);
- exit(-1);
- }
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_string: found '%s' on line %d\n", helper->strval, line );
- #endif /* DEBUG */
- memset(buf,0,string_size+1);
- memcpy ( buf, helper->strval, string_size);
- /* No need to free strings because we use a static buffer to parse them */
- return ( string_size );
- }
- /* This is for strings which need the terminating 0 at the end, e.g. Service Flow Class Name */
- int encode_strzero(unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- unsigned int string_size;
- /* We only use this to cast the void* we receive to what we think it should be */
- union t_val *helper;
- if ( buf == NULL ) {
- fprintf(stderr, "encode_string called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_string called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- string_size = strlen ( helper->strval );
- if (sym_ptr->low_limit || sym_ptr->high_limit) {
- if ( string_size < sym_ptr->low_limit ) {
- fprintf(stderr, "encode_string: String too short, must be min %d chars\n",
- sym_ptr->low_limit);
- exit(-1);
- }
- if ( sym_ptr->high_limit < string_size ) {
- fprintf(stderr, "encode_string: String too long, must be max %d chars\n",
- sym_ptr->high_limit);
- exit(-1);
- }
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_string: found '%s' on line %d\n", helper->strval, line );
- #endif /* DEBUG */
- memset(buf,0,string_size+1);
- memcpy ( buf, helper->strval, string_size);
- /* No need to free strings because we use a static buffer to parse them */
- return ( string_size+1 );
- }
- int encode_hexstr (unsigned char *buf, void *tval, struct symbol_entry *sym_ptr)
- {
- unsigned int fragval;
- unsigned int i;
- int rval;
- char *p;
- unsigned int string_size;
- /* We only use this to cast the void * we receive and extract the data from the union */
- union t_val *helper;
- if ( buf == NULL ) {
- fprintf(stderr, "encode_hexstr called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_hexstr called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- string_size = strlen ( helper->strval );
- if ( string_size % 2 != 0 ) {
- fprintf(stderr, "encode_hexstr: invalid hex string\n");
- exit (-1);
- }
- p = helper->strval;
- if (p[0] != '0' || ( p[1] != 'x' && p[1] != 'X' )) {
- fprintf(stderr, "encode_hexstr: invalid hex string %s\n", p);
- exit (-1);
- }
- p += 2*sizeof(char);
- i=0;
- while (*p) {
- if ( (rval=sscanf(p, "%02x", &fragval)) == 0) {
- fprintf(stderr, "Invalid Hex Value %s\n", helper->strval);
- exit (-1);
- }
- buf[i] = (char) fragval; i++;
- p += 2*sizeof(char);
- }
- if (sym_ptr->low_limit || sym_ptr->high_limit) {
- if ( i < sym_ptr->low_limit ) {
- fprintf(stderr, "encode_hexstr: Hex value too short, must be min %d octets\n",
- sym_ptr->low_limit);
- exit(-1);
- }
- if ( sym_ptr->high_limit < i ) {
- fprintf(stderr, "encode_hexstr: Hex value too long, must be max %d octets\n",
- sym_ptr->high_limit);
- exit(-1);
- }
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_hexstr: found '%s' on line %d\n", helper->strval, line );
- #endif /* DEBUG */
- free(helper->strval);
- /* TODO Fix bug added by free(helper->strval) when double quote is used in text config file. */
- return ( i );
- }
- /* This is for strings which need the terminating 0 at the end, e.g. Service Flow Class Name */
- int encode_oid(unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- unsigned int output_size;
- /* We only use this to cast the void* we receive to what we think it should be */
- union t_val *helper;
- if ( buf == NULL ) {
- fprintf(stderr, "encode_oid called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_oid called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- output_size = encode_snmp_oid(helper->strval, buf, TLV_VSIZE);
- free(helper->strval);
- return ( output_size );
- }
- int encode_ushort_list( unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- unsigned short numbers[128];
- unsigned long value_found;
- unsigned int nr_found=0;
- char *cp;
- char *endptr[1];
- #ifdef DEBUG
- int i;
- #endif
- union t_val *helper; /* We only use this to cast the void* we receive to what we think it should be */
- if ( buf == NULL ) {
- fprintf(stderr, "encode_ushort_list called w/NULL buffer\n");
- exit (-1);
- }
- if ( tval == NULL ) {
- fprintf(stderr, "encode_ushort_list called w/NULL value struct\n");
- exit (-1);
- }
- helper = (union t_val *) tval;
- cp = helper->strval;
- do {
- if(*cp ==',' || *cp == ' ') cp++;
- value_found = strtoul( cp, endptr, 10);
- if (endptr == NULL)
- if (cp == *endptr) {
- fprintf(stderr, "Parse error at line %d: expecting digits\n",line);
- exit (-11);
- }
- if (value_found > 65535) {
- fprintf(stderr, "Parse error at line %d: value cannot exceed 65535\n",line);
- exit (-11);
- }
- nr_found++;
- numbers[nr_found-1]=htons((unsigned short) value_found);
- cp=*endptr;
- } while (*cp);
- if (sym_ptr->low_limit || sym_ptr->high_limit) {
- if ( nr_found < sym_ptr->low_limit ) {
- fprintf(stderr, "Line %d: Not enough numbers, minimum %d\n", line,
- sym_ptr->low_limit);
- exit(-1);
- }
- if ( sym_ptr->high_limit < nr_found ) {
- fprintf(stderr, "Line %d: too many numbers, max %d\n", line,
- sym_ptr->high_limit);
- exit(-1);
- }
- }
- #ifdef DEBUG
- fprintf(stderr, "encode_ushort_list: found ");
- for(i=0; i<nr_found; i++)
- fprintf(stderr, "%d ", ntohs(numbers[i]) );
- fprintf(stderr, "\n");
- #endif /* DEBUG */
- memcpy ( buf, numbers, nr_found*sizeof(unsigned short));
- free(helper->strval);
- return ( nr_found*sizeof(unsigned short));
- }
- int encode_nothing(unsigned char *buf, void *tval, struct symbol_entry *sym_ptr )
- {
- return 0;
- }
|