diff options
Diffstat (limited to 'isisd/isis_misc.c')
-rw-r--r-- | isisd/isis_misc.c | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c new file mode 100644 index 000000000..763ae2434 --- /dev/null +++ b/isisd/isis_misc.c @@ -0,0 +1,438 @@ +/* + * IS-IS Rout(e)ing protocol - isis_misc.h + * Miscellanous routines + * + * Copyright (C) 2001,2002 Sampo Saaristo + * Tampere University of Technology + * Institute of Communications Engineering + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <ctype.h> +#include <zebra.h> +#include <net/ethernet.h> + + +#include "stream.h" +#include "vty.h" +#include "hash.h" +#include "if.h" + +#include "isisd/dict.h" +#include "isisd/isis_constants.h" +#include "isisd/isis_common.h" +#include "isisd/isis_circuit.h" +#include "isisd/isisd.h" +#include "isisd/isis_misc.h" + +#include "isisd/isis_tlv.h" +#include "isisd/isis_lsp.h" +#include "isisd/isis_constants.h" +#include "isisd/isis_adjacency.h" + +/* + * This converts the isonet to its printable format + */ +char * isonet_print (u_char *from, int len) { + int i = 0; + char *pos = isonet; + + if(!from) + return "unknown"; + + while (i < len) { + if (i & 1) { + sprintf ( pos, "%02x", *(from + i)); + pos += 2; + } else { + if (i == 0) { /* if the area addr is just one byte, eg. 47. */ + sprintf ( pos, "%02x", *(from + i)); + pos += 2; + } else { + sprintf ( pos, "%02x.", *(from + i)); + pos += 3; + } + } + i++; + } + *(pos) = '\0'; + return isonet; +} + +/* + * Returns 0 on error, length of buff on ok + * extract dot from the dotted str, and insert all the number in a buff + */ +int +dotformat2buff (u_char *buff, u_char *dotted) +{ + int dotlen, len = 0; + u_char *pos = dotted; + u_char number[3]; + int nextdotpos = 2; + + number[2] = '\0'; + dotlen = strlen(dotted); + if (dotlen > 50) { + /* this can't be an iso net, its too long */ + return 0; + } + + while ( (pos - dotted) < dotlen && len < 20 ) { + if (*pos == '.') { + /* we expect the . at 2, and than every 5 */ + if ((pos - dotted) != nextdotpos) { + len = 0; + break; + } + nextdotpos += 5; + pos++; + continue; + } + /* we must have at least two chars left here */ + if (dotlen - (pos - dotted) < 2) { + len = 0; + break; + } + + if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos+1)))){ + memcpy (number, pos ,2); + pos+=2; + } else { + len = 0; + break; + } + + *(buff + len) = (char)strtol(number, NULL, 16); + len++; + } + + return len; +} +/* + * conversion of XXXX.XXXX.XXXX to memory + */ +int +sysid2buff (u_char *buff, u_char *dotted) + { + int len = 0; + u_char *pos = dotted; + u_char number[3]; + + number[2] = '\0'; + // surely not a sysid_string if not 14 length + if (strlen(dotted) != 14) { + return 0; + } + + while ( len < ISIS_SYS_ID_LEN ) { + if (*pos == '.') { + /* the . is not positioned correctly */ + if (((pos - dotted) !=4) && ((pos - dotted) != 9)) { + len = 0; + break; + } + pos++; + continue; + } + if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos+1)))){ + memcpy (number, pos ,2); + pos+=2; + } else { + len = 0; + break; + } + + *(buff + len) = (char)strtol(number, NULL, 16); + len++; + } + + return len; + +} + +/* + * converts the nlpids struct (filled by TLV #129) + * into a string + */ + +char * +nlpid2string (struct nlpids *nlpids) { + char *pos = nlpidstring; + int i; + + for (i=0;i<nlpids->count;i++) { + switch (nlpids->nlpids[i]) { + case NLPID_IP: + pos += sprintf (pos, "IPv4"); + break; + case NLPID_IPV6: + pos += sprintf (pos, "IPv6"); + break; + default: + pos += sprintf (pos, "unknown"); + break; + } + if (nlpids->count-i>1) + pos += sprintf (pos, ", "); + + } + + *(pos) = '\0'; + + return nlpidstring; +} + +/* + * supports the given af ? + */ +int +speaks (struct nlpids *nlpids, int family) +{ + int i, speaks = 0; + + if (nlpids == (struct nlpids*)NULL) + return speaks; + for (i = 0;i < nlpids->count; i++) { + if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP) + speaks = 1; + if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6) + speaks = 1; + } + + return speaks; +} + + +/* + * Returns 0 on error, IS-IS Circuit Type on ok + */ +int +string2circuit_t (u_char *str) +{ + + if (!str) + return 0; + + if (!strcmp(str,"level-1")) + return IS_LEVEL_1; + + if (!strcmp(str,"level-2-only") || !strcmp(str,"level-2")) + return IS_LEVEL_2; + + if (!strcmp(str,"level-1-2")) + return IS_LEVEL_1_AND_2; + + return 0; +} + +const char * +circuit_t2string (int circuit_t) +{ + switch (circuit_t) { + case IS_LEVEL_1: + return "L1"; + case IS_LEVEL_2: + return "L2"; + case IS_LEVEL_1_AND_2: + return "L1L2"; + default: + return "??"; + } + + return NULL; /* not reached */ +} + +const char * +syst2string (int type) +{ + switch (type) { + case ISIS_SYSTYPE_ES: + return "ES"; + case ISIS_SYSTYPE_IS: + return "IS"; + case ISIS_SYSTYPE_L1_IS: + return "1"; + case ISIS_SYSTYPE_L2_IS: + return "2"; + default: + return "??"; + } + + return NULL; /* not reached */ +} + +/* + * Print functions - we print to static vars + */ +char * +snpa_print (u_char *from) +{ + int i = 0; + u_char *pos = snpa; + + if(!from) + return "unknown"; + + while (i < ETH_ALEN - 1) { + if (i & 1) { + sprintf ( pos, "%02x.", *(from + i)); + pos += 3; + } else { + sprintf ( pos, "%02x", *(from + i)); + pos += 2; + + } + i++; + } + + sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); + pos += 2; + *(pos) = '\0'; + + return snpa; +} + +char * +sysid_print (u_char *from) +{ + int i = 0; + char *pos = sysid; + + if(!from) + return "unknown"; + + while (i < ISIS_SYS_ID_LEN - 1) { + if (i & 1) { + sprintf ( pos, "%02x.", *(from + i)); + pos += 3; + } else { + sprintf ( pos, "%02x", *(from + i)); + pos += 2; + + } + i++; + } + + sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); + pos += 2; + *(pos) = '\0'; + + return sysid; +} + +char * +rawlspid_print (u_char *from) +{ + char *pos = lspid; + if(!from) + return "unknown"; + memcpy(pos, sysid_print(from), 15); + pos += 14; + sprintf (pos, ".%02x", LSP_PSEUDO_ID(from)); + pos += 3; + sprintf (pos, "-%02x", LSP_FRAGMENT(from)); + pos += 3; + + *(pos) = '\0'; + + return lspid; +} + +char * +time2string (u_int32_t time) { + char *pos = datestring; + u_int32_t rest; + + if (time==0) + return "-"; + + if(time/SECS_PER_YEAR) + pos += sprintf (pos, "%uY",time/SECS_PER_YEAR); + rest=time%SECS_PER_YEAR; + if(rest/SECS_PER_MONTH) + pos += sprintf (pos, "%uM",rest/SECS_PER_MONTH); + rest=rest%SECS_PER_MONTH; + if(rest/SECS_PER_WEEK) + pos += sprintf (pos, "%uw",rest/SECS_PER_WEEK); + rest=rest%SECS_PER_WEEK; + if(rest/SECS_PER_DAY) + pos += sprintf (pos, "%ud",rest/SECS_PER_DAY); + rest=rest%SECS_PER_DAY; + if(rest/SECS_PER_HOUR) + pos += sprintf (pos, "%uh",rest/SECS_PER_HOUR); + rest=rest%SECS_PER_HOUR; + if(rest/SECS_PER_MINUTE) + pos += sprintf (pos, "%um",rest/SECS_PER_MINUTE); + rest=rest%SECS_PER_MINUTE; + if(rest) + pos += sprintf (pos, "%us",rest); + + *(pos) = 0; + + return datestring; +} + +/* + * routine to decrement a timer by a random + * number + * + * first argument is the timer and the second is + * the jitter + */ +unsigned long +isis_jitter (unsigned long timer, unsigned long jitter) +{ + int j,k; + + if (jitter>=100) + return timer; + + if (timer == 1) + return timer; + /* + * randomizing just the percent value provides + * no good random numbers - hence the spread + * to RANDOM_SPREAD (100000), which is ok as + * most IS-IS timers are no longer than 16 bit + */ + + j = 1 + (int) ((RANDOM_SPREAD * rand()) / (RAND_MAX + 1.0 )); + + k = timer - (timer * (100 - jitter))/100; + + timer = timer - (k * j / RANDOM_SPREAD); + + return timer; +} + +struct in_addr +newprefix2inaddr (u_char *prefix_start, u_char prefix_masklen) +{ + memset(&new_prefix, 0, sizeof (new_prefix)); + memcpy(&new_prefix, prefix_start, (prefix_masklen & 0x3F) ? + ((((prefix_masklen & 0x3F)-1)>>3)+1) : 0); + return new_prefix; +} + + + + + |