File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / isisd / isis_misc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 5 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_20_1, v0_99_20, HEAD
quagga

    1: /*
    2:  * IS-IS Rout(e)ing protocol - isis_misc.h
    3:  *                             Miscellanous routines
    4:  *
    5:  * Copyright (C) 2001,2002   Sampo Saaristo
    6:  *                           Tampere University of Technology      
    7:  *                           Institute of Communications Engineering
    8:  *
    9:  * This program is free software; you can redistribute it and/or modify it 
   10:  * under the terms of the GNU General Public Licenseas published by the Free 
   11:  * Software Foundation; either version 2 of the License, or (at your option) 
   12:  * any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,but WITHOUT 
   15:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
   16:  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
   17:  * more details.
   18: 
   19:  * You should have received a copy of the GNU General Public License along 
   20:  * with this program; if not, write to the Free Software Foundation, Inc., 
   21:  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   22:  */
   23: 
   24: #include <zebra.h>
   25: 
   26: #include "stream.h"
   27: #include "vty.h"
   28: #include "hash.h"
   29: #include "if.h"
   30: #include "command.h"
   31: 
   32: #include "isisd/dict.h"
   33: #include "isisd/isis_constants.h"
   34: #include "isisd/isis_common.h"
   35: #include "isisd/isis_circuit.h"
   36: #include "isisd/isisd.h"
   37: #include "isisd/isis_misc.h"
   38: 
   39: #include "isisd/isis_tlv.h"
   40: #include "isisd/isis_lsp.h"
   41: #include "isisd/isis_constants.h"
   42: #include "isisd/isis_adjacency.h"
   43: 
   44: /* staticly assigned vars for printing purposes */
   45: struct in_addr new_prefix;
   46: /* len of xxxx.xxxx.xxxx + place for #0 termination */
   47: char sysid[15];
   48: /* len of xxxx.xxxx.xxxx + place for #0 termination */
   49: char snpa[15];
   50: /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
   51: char isonet[51];
   52: /* + place for #0 termination */
   53: /* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
   54: char lspid[21];
   55: /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
   56: char datestring[20];
   57: char nlpidstring[30];
   58: 
   59: /*
   60:  * This converts the isonet to its printable format
   61:  */
   62: const char *
   63: isonet_print (u_char * from, int len)
   64: {
   65:   int i = 0;
   66:   char *pos = isonet;
   67: 
   68:   if (!from)
   69:     return "unknown";
   70: 
   71:   while (i < len)
   72:     {
   73:       if (i & 1)
   74: 	{
   75: 	  sprintf (pos, "%02x", *(from + i));
   76: 	  pos += 2;
   77: 	}
   78:       else
   79: 	{
   80: 	  if (i == (len - 1))
   81: 	    {			/* No dot at the end of address */
   82: 	      sprintf (pos, "%02x", *(from + i));
   83: 	      pos += 2;
   84: 	    }
   85: 	  else
   86: 	    {
   87: 	      sprintf (pos, "%02x.", *(from + i));
   88: 	      pos += 3;
   89: 	    }
   90: 	}
   91:       i++;
   92:     }
   93:   *(pos) = '\0';
   94:   return isonet;
   95: }
   96: 
   97: /*
   98:  * Returns 0 on error, length of buff on ok
   99:  * extract dot from the dotted str, and insert all the number in a buff 
  100:  */
  101: int
  102: dotformat2buff (u_char * buff, const u_char * dotted)
  103: {
  104:   int dotlen, len = 0;
  105:   const u_char *pos = dotted;
  106:   u_char number[3];
  107:   int nextdotpos = 2;
  108: 
  109:   number[2] = '\0';
  110:   dotlen = strlen(dotted);
  111:   if (dotlen > 50)
  112:     {
  113:       /* this can't be an iso net, its too long */
  114:       return 0;
  115:     }
  116: 
  117:   while ((pos - dotted) < dotlen && len < 20)
  118:     {
  119:       if (*pos == '.')
  120: 	{
  121: 	  /* we expect the . at 2, and than every 5 */
  122: 	  if ((pos - dotted) != nextdotpos)
  123: 	    {
  124: 	      len = 0;
  125: 	      break;
  126: 	    }
  127: 	  nextdotpos += 5;
  128: 	  pos++;
  129: 	  continue;
  130: 	}
  131:       /* we must have at least two chars left here */
  132:       if (dotlen - (pos - dotted) < 2)
  133: 	{
  134: 	  len = 0;
  135: 	  break;
  136: 	}
  137: 
  138:       if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
  139: 	{
  140: 	  memcpy (number, pos, 2);
  141: 	  pos += 2;
  142: 	}
  143:       else
  144: 	{
  145: 	  len = 0;
  146: 	  break;
  147: 	}
  148: 
  149:       *(buff + len) = (char) strtol ((char *)number, NULL, 16);
  150:       len++;
  151:     }
  152: 
  153:   return len;
  154: }
  155: 
  156: /*
  157:  * conversion of XXXX.XXXX.XXXX to memory
  158:  */
  159: int
  160: sysid2buff (u_char * buff, const u_char * dotted)
  161: {
  162:   int len = 0;
  163:   const u_char *pos = dotted;
  164:   u_char number[3];
  165: 
  166:   number[2] = '\0';
  167:   // surely not a sysid_string if not 14 length
  168:   if (strlen (dotted) != 14)
  169:     {
  170:       return 0;
  171:     }
  172: 
  173:   while (len < ISIS_SYS_ID_LEN)
  174:     {
  175:       if (*pos == '.')
  176: 	{
  177: 	  /* the . is not positioned correctly */
  178: 	  if (((pos - dotted) != 4) && ((pos - dotted) != 9))
  179: 	    {
  180: 	      len = 0;
  181: 	      break;
  182: 	    }
  183: 	  pos++;
  184: 	  continue;
  185: 	}
  186:       if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
  187: 	{
  188: 	  memcpy (number, pos, 2);
  189: 	  pos += 2;
  190: 	}
  191:       else
  192: 	{
  193: 	  len = 0;
  194: 	  break;
  195: 	}
  196: 
  197:       *(buff + len) = (char) strtol ((char *)number, NULL, 16);
  198:       len++;
  199:     }
  200: 
  201:   return len;
  202: 
  203: }
  204: 
  205: /*
  206:  * converts the nlpids struct (filled by TLV #129)
  207:  * into a string
  208:  */
  209: 
  210: char *
  211: nlpid2string (struct nlpids *nlpids)
  212: {
  213:   char *pos = nlpidstring;
  214:   int i;
  215: 
  216:   for (i = 0; i < nlpids->count; i++)
  217:     {
  218:       switch (nlpids->nlpids[i])
  219: 	{
  220: 	case NLPID_IP:
  221: 	  pos += sprintf (pos, "IPv4");
  222: 	  break;
  223: 	case NLPID_IPV6:
  224: 	  pos += sprintf (pos, "IPv6");
  225: 	  break;
  226: 	case NLPID_SNAP:
  227: 	  pos += sprintf (pos, "SNAP");
  228: 	  break;
  229: 	case NLPID_CLNP:
  230: 	  pos += sprintf (pos, "CLNP");
  231: 	  break;
  232: 	case NLPID_ESIS:
  233: 	  pos += sprintf (pos, "ES-IS");
  234: 	  break;
  235: 	default:
  236: 	  pos += sprintf (pos, "unknown");
  237: 	  break;
  238: 	}
  239:       if (nlpids->count - i > 1)
  240: 	pos += sprintf (pos, ", ");
  241: 
  242:     }
  243: 
  244:   *(pos) = '\0';
  245: 
  246:   return nlpidstring;
  247: }
  248: 
  249: /*
  250:  *  supports the given af ?
  251:  */
  252: int
  253: speaks (struct nlpids *nlpids, int family)
  254: {
  255:   int i, speaks = 0;
  256: 
  257:   if (nlpids == (struct nlpids *) NULL)
  258:     return speaks;
  259:   for (i = 0; i < nlpids->count; i++)
  260:     {
  261:       if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
  262: 	speaks = 1;
  263:       if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
  264: 	speaks = 1;
  265:     }
  266: 
  267:   return speaks;
  268: }
  269: 
  270: /*
  271:  * Returns 0 on error, IS-IS Circuit Type on ok
  272:  */
  273: int
  274: string2circuit_t (const u_char * str)
  275: {
  276: 
  277:   if (!str)
  278:     return 0;
  279: 
  280:   if (!strcmp (str, "level-1"))
  281:     return IS_LEVEL_1;
  282: 
  283:   if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
  284:     return IS_LEVEL_2;
  285: 
  286:   if (!strcmp (str, "level-1-2"))
  287:     return IS_LEVEL_1_AND_2;
  288: 
  289:   return 0;
  290: }
  291: 
  292: const char *
  293: circuit_t2string (int circuit_t)
  294: {
  295:   switch (circuit_t)
  296:     {
  297:     case IS_LEVEL_1:
  298:       return "L1";
  299:     case IS_LEVEL_2:
  300:       return "L2";
  301:     case IS_LEVEL_1_AND_2:
  302:       return "L1L2";
  303:     default:
  304:       return "??";
  305:     }
  306: 
  307:   return NULL;			/* not reached */
  308: }
  309: 
  310: const char *
  311: syst2string (int type)
  312: {
  313:   switch (type)
  314:     {
  315:     case ISIS_SYSTYPE_ES:
  316:       return "ES";
  317:     case ISIS_SYSTYPE_IS:
  318:       return "IS";
  319:     case ISIS_SYSTYPE_L1_IS:
  320:       return "1";
  321:     case ISIS_SYSTYPE_L2_IS:
  322:       return "2";
  323:     default:
  324:       return "??";
  325:     }
  326: 
  327:   return NULL;			/* not reached */
  328: }
  329: 
  330: /*
  331:  * Print functions - we print to static vars
  332:  */
  333: const char *
  334: snpa_print (u_char * from)
  335: {
  336:   int i = 0;
  337:   u_char *pos = (u_char *)snpa;
  338: 
  339:   if (!from)
  340:     return "unknown";
  341: 
  342:   while (i < ETH_ALEN - 1)
  343:     {
  344:       if (i & 1)
  345: 	{
  346: 	  sprintf ((char *)pos, "%02x.", *(from + i));
  347: 	  pos += 3;
  348: 	}
  349:       else
  350: 	{
  351: 	  sprintf ((char *)pos, "%02x", *(from + i));
  352: 	  pos += 2;
  353: 
  354: 	}
  355:       i++;
  356:     }
  357: 
  358:   sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
  359:   pos += 2;
  360:   *(pos) = '\0';
  361: 
  362:   return snpa;
  363: }
  364: 
  365: const char *
  366: sysid_print (u_char * from)
  367: {
  368:   int i = 0;
  369:   char *pos = sysid;
  370: 
  371:   if (!from)
  372:     return "unknown";
  373: 
  374:   while (i < ISIS_SYS_ID_LEN - 1)
  375:     {
  376:       if (i & 1)
  377: 	{
  378: 	  sprintf (pos, "%02x.", *(from + i));
  379: 	  pos += 3;
  380: 	}
  381:       else
  382: 	{
  383: 	  sprintf (pos, "%02x", *(from + i));
  384: 	  pos += 2;
  385: 
  386: 	}
  387:       i++;
  388:     }
  389: 
  390:   sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
  391:   pos += 2;
  392:   *(pos) = '\0';
  393: 
  394:   return sysid;
  395: }
  396: 
  397: const char *
  398: rawlspid_print (u_char * from)
  399: {
  400:   char *pos = lspid;
  401:   if (!from)
  402:     return "unknown";
  403:   memcpy (pos, sysid_print (from), 15);
  404:   pos += 14;
  405:   sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
  406:   pos += 3;
  407:   sprintf (pos, "-%02x", LSP_FRAGMENT (from));
  408:   pos += 3;
  409: 
  410:   *(pos) = '\0';
  411: 
  412:   return lspid;
  413: }
  414: 
  415: const char *
  416: time2string (u_int32_t time)
  417: {
  418:   char *pos = datestring;
  419:   u_int32_t rest;
  420: 
  421:   if (time == 0)
  422:     return "-";
  423: 
  424:   if (time / SECS_PER_YEAR)
  425:     pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
  426:   rest = time % SECS_PER_YEAR;
  427:   if (rest / SECS_PER_MONTH)
  428:     pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
  429:   rest = rest % SECS_PER_MONTH;
  430:   if (rest / SECS_PER_WEEK)
  431:     pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
  432:   rest = rest % SECS_PER_WEEK;
  433:   if (rest / SECS_PER_DAY)
  434:     pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
  435:   rest = rest % SECS_PER_DAY;
  436:   if (rest / SECS_PER_HOUR)
  437:     pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
  438:   rest = rest % SECS_PER_HOUR;
  439:   if (rest / SECS_PER_MINUTE)
  440:     pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
  441:   rest = rest % SECS_PER_MINUTE;
  442:   if (rest)
  443:     pos += sprintf (pos, "%us", rest);
  444: 
  445:   *(pos) = 0;
  446: 
  447:   return datestring;
  448: }
  449: 
  450: /*
  451:  * routine to decrement a timer by a random
  452:  * number
  453:  *
  454:  * first argument is the timer and the second is
  455:  * the jitter
  456:  */
  457: unsigned long
  458: isis_jitter (unsigned long timer, unsigned long jitter)
  459: {
  460:   int j, k;
  461: 
  462:   if (jitter >= 100)
  463:     return timer;
  464: 
  465:   if (timer == 1)
  466:     return timer;
  467:   /* 
  468:    * randomizing just the percent value provides
  469:    * no good random numbers - hence the spread
  470:    * to RANDOM_SPREAD (100000), which is ok as
  471:    * most IS-IS timers are no longer than 16 bit
  472:    */
  473: 
  474:   j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
  475: 
  476:   k = timer - (timer * (100 - jitter)) / 100;
  477: 
  478:   timer = timer - (k * j / RANDOM_SPREAD);
  479: 
  480:   return timer;
  481: }
  482: 
  483: struct in_addr
  484: newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
  485: {
  486:   memset (&new_prefix, 0, sizeof (new_prefix));
  487:   memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
  488: 	  ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
  489:   return new_prefix;
  490: }
  491: 
  492: /*
  493:  * Returns host.name if any, otherwise
  494:  * it returns the system hostname.
  495:  */
  496: const char *
  497: unix_hostname (void)
  498: {
  499:   static struct utsname names;
  500:   const char *hostname;
  501:   extern struct host host;
  502: 
  503:   hostname = host.name;
  504:   if (!hostname)
  505:     {
  506:       uname (&names);
  507:       hostname = names.nodename;
  508:     }
  509: 
  510:   return hostname;
  511: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>