Annotation of embedaddon/quagga/isisd/isis_misc.c, revision 1.1.1.2

1.1       misho       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"
1.1.1.2 ! misho      35: #include "isisd/isis_flags.h"
1.1       misho      36: #include "isisd/isis_circuit.h"
1.1.1.2 ! misho      37: #include "isisd/isis_csm.h"
1.1       misho      38: #include "isisd/isisd.h"
                     39: #include "isisd/isis_misc.h"
                     40: 
                     41: #include "isisd/isis_tlv.h"
                     42: #include "isisd/isis_lsp.h"
                     43: #include "isisd/isis_constants.h"
                     44: #include "isisd/isis_adjacency.h"
1.1.1.2 ! misho      45: #include "isisd/isis_dynhn.h"
1.1       misho      46: 
                     47: /* staticly assigned vars for printing purposes */
                     48: struct in_addr new_prefix;
                     49: /* len of xxxx.xxxx.xxxx + place for #0 termination */
                     50: char sysid[15];
                     51: /* len of xxxx.xxxx.xxxx + place for #0 termination */
                     52: char snpa[15];
                     53: /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
                     54: char isonet[51];
                     55: /* + place for #0 termination */
                     56: /* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
                     57: char lspid[21];
                     58: /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
                     59: char datestring[20];
                     60: char nlpidstring[30];
                     61: 
                     62: /*
                     63:  * This converts the isonet to its printable format
                     64:  */
                     65: const char *
                     66: isonet_print (u_char * from, int len)
                     67: {
                     68:   int i = 0;
                     69:   char *pos = isonet;
                     70: 
                     71:   if (!from)
                     72:     return "unknown";
                     73: 
                     74:   while (i < len)
                     75:     {
                     76:       if (i & 1)
                     77:        {
                     78:          sprintf (pos, "%02x", *(from + i));
                     79:          pos += 2;
                     80:        }
                     81:       else
                     82:        {
                     83:          if (i == (len - 1))
                     84:            {                   /* No dot at the end of address */
                     85:              sprintf (pos, "%02x", *(from + i));
                     86:              pos += 2;
                     87:            }
                     88:          else
                     89:            {
                     90:              sprintf (pos, "%02x.", *(from + i));
                     91:              pos += 3;
                     92:            }
                     93:        }
                     94:       i++;
                     95:     }
                     96:   *(pos) = '\0';
                     97:   return isonet;
                     98: }
                     99: 
                    100: /*
                    101:  * Returns 0 on error, length of buff on ok
                    102:  * extract dot from the dotted str, and insert all the number in a buff 
                    103:  */
                    104: int
1.1.1.2 ! misho     105: dotformat2buff (u_char * buff, const char * dotted)
1.1       misho     106: {
                    107:   int dotlen, len = 0;
1.1.1.2 ! misho     108:   const char *pos = dotted;
1.1       misho     109:   u_char number[3];
                    110:   int nextdotpos = 2;
                    111: 
                    112:   number[2] = '\0';
                    113:   dotlen = strlen(dotted);
                    114:   if (dotlen > 50)
                    115:     {
                    116:       /* this can't be an iso net, its too long */
                    117:       return 0;
                    118:     }
                    119: 
                    120:   while ((pos - dotted) < dotlen && len < 20)
                    121:     {
                    122:       if (*pos == '.')
                    123:        {
                    124:          /* we expect the . at 2, and than every 5 */
                    125:          if ((pos - dotted) != nextdotpos)
                    126:            {
                    127:              len = 0;
                    128:              break;
                    129:            }
                    130:          nextdotpos += 5;
                    131:          pos++;
                    132:          continue;
                    133:        }
                    134:       /* we must have at least two chars left here */
                    135:       if (dotlen - (pos - dotted) < 2)
                    136:        {
                    137:          len = 0;
                    138:          break;
                    139:        }
                    140: 
                    141:       if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
                    142:        {
                    143:          memcpy (number, pos, 2);
                    144:          pos += 2;
                    145:        }
                    146:       else
                    147:        {
                    148:          len = 0;
                    149:          break;
                    150:        }
                    151: 
                    152:       *(buff + len) = (char) strtol ((char *)number, NULL, 16);
                    153:       len++;
                    154:     }
                    155: 
                    156:   return len;
                    157: }
                    158: 
                    159: /*
                    160:  * conversion of XXXX.XXXX.XXXX to memory
                    161:  */
                    162: int
1.1.1.2 ! misho     163: sysid2buff (u_char * buff, const char * dotted)
1.1       misho     164: {
                    165:   int len = 0;
1.1.1.2 ! misho     166:   const char *pos = dotted;
1.1       misho     167:   u_char number[3];
                    168: 
                    169:   number[2] = '\0';
                    170:   // surely not a sysid_string if not 14 length
                    171:   if (strlen (dotted) != 14)
                    172:     {
                    173:       return 0;
                    174:     }
                    175: 
                    176:   while (len < ISIS_SYS_ID_LEN)
                    177:     {
                    178:       if (*pos == '.')
                    179:        {
                    180:          /* the . is not positioned correctly */
                    181:          if (((pos - dotted) != 4) && ((pos - dotted) != 9))
                    182:            {
                    183:              len = 0;
                    184:              break;
                    185:            }
                    186:          pos++;
                    187:          continue;
                    188:        }
                    189:       if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
                    190:        {
                    191:          memcpy (number, pos, 2);
                    192:          pos += 2;
                    193:        }
                    194:       else
                    195:        {
                    196:          len = 0;
                    197:          break;
                    198:        }
                    199: 
                    200:       *(buff + len) = (char) strtol ((char *)number, NULL, 16);
                    201:       len++;
                    202:     }
                    203: 
                    204:   return len;
                    205: 
                    206: }
                    207: 
                    208: /*
                    209:  * converts the nlpids struct (filled by TLV #129)
                    210:  * into a string
                    211:  */
                    212: 
                    213: char *
                    214: nlpid2string (struct nlpids *nlpids)
                    215: {
                    216:   char *pos = nlpidstring;
                    217:   int i;
                    218: 
                    219:   for (i = 0; i < nlpids->count; i++)
                    220:     {
                    221:       switch (nlpids->nlpids[i])
                    222:        {
                    223:        case NLPID_IP:
                    224:          pos += sprintf (pos, "IPv4");
                    225:          break;
                    226:        case NLPID_IPV6:
                    227:          pos += sprintf (pos, "IPv6");
                    228:          break;
                    229:        case NLPID_SNAP:
                    230:          pos += sprintf (pos, "SNAP");
                    231:          break;
                    232:        case NLPID_CLNP:
                    233:          pos += sprintf (pos, "CLNP");
                    234:          break;
                    235:        case NLPID_ESIS:
                    236:          pos += sprintf (pos, "ES-IS");
                    237:          break;
                    238:        default:
                    239:          pos += sprintf (pos, "unknown");
                    240:          break;
                    241:        }
                    242:       if (nlpids->count - i > 1)
                    243:        pos += sprintf (pos, ", ");
                    244: 
                    245:     }
                    246: 
                    247:   *(pos) = '\0';
                    248: 
                    249:   return nlpidstring;
                    250: }
                    251: 
                    252: /*
                    253:  *  supports the given af ?
                    254:  */
                    255: int
                    256: speaks (struct nlpids *nlpids, int family)
                    257: {
                    258:   int i, speaks = 0;
                    259: 
                    260:   if (nlpids == (struct nlpids *) NULL)
                    261:     return speaks;
                    262:   for (i = 0; i < nlpids->count; i++)
                    263:     {
                    264:       if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
                    265:        speaks = 1;
                    266:       if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
                    267:        speaks = 1;
                    268:     }
                    269: 
                    270:   return speaks;
                    271: }
                    272: 
                    273: /*
                    274:  * Returns 0 on error, IS-IS Circuit Type on ok
                    275:  */
                    276: int
1.1.1.2 ! misho     277: string2circuit_t (const char * str)
1.1       misho     278: {
                    279: 
                    280:   if (!str)
                    281:     return 0;
                    282: 
                    283:   if (!strcmp (str, "level-1"))
                    284:     return IS_LEVEL_1;
                    285: 
                    286:   if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
                    287:     return IS_LEVEL_2;
                    288: 
                    289:   if (!strcmp (str, "level-1-2"))
                    290:     return IS_LEVEL_1_AND_2;
                    291: 
                    292:   return 0;
                    293: }
                    294: 
                    295: const char *
1.1.1.2 ! misho     296: circuit_state2string (int state)
        !           297: {
        !           298: 
        !           299:   switch (state)
        !           300:     {
        !           301:     case C_STATE_INIT:
        !           302:       return "Init";
        !           303:     case C_STATE_CONF:
        !           304:       return "Config";
        !           305:     case C_STATE_UP:
        !           306:       return "Up";
        !           307:     default:
        !           308:       return "Unknown";
        !           309:     }
        !           310:   return NULL;
        !           311: }
        !           312: 
        !           313: const char *
        !           314: circuit_type2string (int type)
        !           315: {
        !           316: 
        !           317:   switch (type)
        !           318:     {
        !           319:     case CIRCUIT_T_P2P:
        !           320:       return "p2p";
        !           321:     case CIRCUIT_T_BROADCAST:
        !           322:       return "lan";
        !           323:     case CIRCUIT_T_LOOPBACK:
        !           324:       return "loopback";
        !           325:     default:
        !           326:       return "Unknown";
        !           327:     }
        !           328:   return NULL;
        !           329: }
        !           330: 
        !           331: const char *
1.1       misho     332: circuit_t2string (int circuit_t)
                    333: {
                    334:   switch (circuit_t)
                    335:     {
                    336:     case IS_LEVEL_1:
                    337:       return "L1";
                    338:     case IS_LEVEL_2:
                    339:       return "L2";
                    340:     case IS_LEVEL_1_AND_2:
                    341:       return "L1L2";
                    342:     default:
                    343:       return "??";
                    344:     }
                    345: 
                    346:   return NULL;                 /* not reached */
                    347: }
                    348: 
                    349: const char *
                    350: syst2string (int type)
                    351: {
                    352:   switch (type)
                    353:     {
                    354:     case ISIS_SYSTYPE_ES:
                    355:       return "ES";
                    356:     case ISIS_SYSTYPE_IS:
                    357:       return "IS";
                    358:     case ISIS_SYSTYPE_L1_IS:
                    359:       return "1";
                    360:     case ISIS_SYSTYPE_L2_IS:
                    361:       return "2";
                    362:     default:
                    363:       return "??";
                    364:     }
                    365: 
                    366:   return NULL;                 /* not reached */
                    367: }
                    368: 
                    369: /*
                    370:  * Print functions - we print to static vars
                    371:  */
                    372: const char *
                    373: snpa_print (u_char * from)
                    374: {
                    375:   int i = 0;
                    376:   u_char *pos = (u_char *)snpa;
                    377: 
                    378:   if (!from)
                    379:     return "unknown";
                    380: 
                    381:   while (i < ETH_ALEN - 1)
                    382:     {
                    383:       if (i & 1)
                    384:        {
                    385:          sprintf ((char *)pos, "%02x.", *(from + i));
                    386:          pos += 3;
                    387:        }
                    388:       else
                    389:        {
                    390:          sprintf ((char *)pos, "%02x", *(from + i));
                    391:          pos += 2;
                    392: 
                    393:        }
                    394:       i++;
                    395:     }
                    396: 
                    397:   sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
                    398:   pos += 2;
                    399:   *(pos) = '\0';
                    400: 
                    401:   return snpa;
                    402: }
                    403: 
                    404: const char *
                    405: sysid_print (u_char * from)
                    406: {
                    407:   int i = 0;
                    408:   char *pos = sysid;
                    409: 
                    410:   if (!from)
                    411:     return "unknown";
                    412: 
                    413:   while (i < ISIS_SYS_ID_LEN - 1)
                    414:     {
                    415:       if (i & 1)
                    416:        {
                    417:          sprintf (pos, "%02x.", *(from + i));
                    418:          pos += 3;
                    419:        }
                    420:       else
                    421:        {
                    422:          sprintf (pos, "%02x", *(from + i));
                    423:          pos += 2;
                    424: 
                    425:        }
                    426:       i++;
                    427:     }
                    428: 
                    429:   sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
                    430:   pos += 2;
                    431:   *(pos) = '\0';
                    432: 
                    433:   return sysid;
                    434: }
                    435: 
                    436: const char *
                    437: rawlspid_print (u_char * from)
                    438: {
                    439:   char *pos = lspid;
                    440:   if (!from)
                    441:     return "unknown";
                    442:   memcpy (pos, sysid_print (from), 15);
                    443:   pos += 14;
                    444:   sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
                    445:   pos += 3;
                    446:   sprintf (pos, "-%02x", LSP_FRAGMENT (from));
                    447:   pos += 3;
                    448: 
                    449:   *(pos) = '\0';
                    450: 
                    451:   return lspid;
                    452: }
                    453: 
                    454: const char *
                    455: time2string (u_int32_t time)
                    456: {
                    457:   char *pos = datestring;
                    458:   u_int32_t rest;
                    459: 
                    460:   if (time == 0)
                    461:     return "-";
                    462: 
                    463:   if (time / SECS_PER_YEAR)
                    464:     pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
                    465:   rest = time % SECS_PER_YEAR;
                    466:   if (rest / SECS_PER_MONTH)
                    467:     pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
                    468:   rest = rest % SECS_PER_MONTH;
                    469:   if (rest / SECS_PER_WEEK)
                    470:     pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
                    471:   rest = rest % SECS_PER_WEEK;
                    472:   if (rest / SECS_PER_DAY)
                    473:     pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
                    474:   rest = rest % SECS_PER_DAY;
                    475:   if (rest / SECS_PER_HOUR)
                    476:     pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
                    477:   rest = rest % SECS_PER_HOUR;
                    478:   if (rest / SECS_PER_MINUTE)
                    479:     pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
                    480:   rest = rest % SECS_PER_MINUTE;
                    481:   if (rest)
                    482:     pos += sprintf (pos, "%us", rest);
                    483: 
                    484:   *(pos) = 0;
                    485: 
                    486:   return datestring;
                    487: }
                    488: 
                    489: /*
                    490:  * routine to decrement a timer by a random
                    491:  * number
                    492:  *
                    493:  * first argument is the timer and the second is
                    494:  * the jitter
                    495:  */
                    496: unsigned long
                    497: isis_jitter (unsigned long timer, unsigned long jitter)
                    498: {
                    499:   int j, k;
                    500: 
                    501:   if (jitter >= 100)
                    502:     return timer;
                    503: 
                    504:   if (timer == 1)
                    505:     return timer;
                    506:   /* 
                    507:    * randomizing just the percent value provides
                    508:    * no good random numbers - hence the spread
                    509:    * to RANDOM_SPREAD (100000), which is ok as
                    510:    * most IS-IS timers are no longer than 16 bit
                    511:    */
                    512: 
                    513:   j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
                    514: 
                    515:   k = timer - (timer * (100 - jitter)) / 100;
                    516: 
                    517:   timer = timer - (k * j / RANDOM_SPREAD);
                    518: 
                    519:   return timer;
                    520: }
                    521: 
                    522: struct in_addr
                    523: newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
                    524: {
                    525:   memset (&new_prefix, 0, sizeof (new_prefix));
                    526:   memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
                    527:          ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
                    528:   return new_prefix;
                    529: }
                    530: 
                    531: /*
                    532:  * Returns host.name if any, otherwise
                    533:  * it returns the system hostname.
                    534:  */
                    535: const char *
                    536: unix_hostname (void)
                    537: {
                    538:   static struct utsname names;
                    539:   const char *hostname;
                    540: 
                    541:   hostname = host.name;
                    542:   if (!hostname)
                    543:     {
                    544:       uname (&names);
                    545:       hostname = names.nodename;
                    546:     }
                    547: 
                    548:   return hostname;
                    549: }
1.1.1.2 ! misho     550: 
        !           551: /*
        !           552:  * Returns the dynamic hostname associated with the passed system ID.
        !           553:  * If no dynamic hostname found then returns formatted system ID.
        !           554:  */
        !           555: const char *
        !           556: print_sys_hostname (u_char *sysid)
        !           557: {
        !           558:   struct isis_dynhn *dyn;
        !           559: 
        !           560:   if (!sysid)
        !           561:     return "nullsysid";
        !           562: 
        !           563:   /* For our system ID return our host name */
        !           564:   if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
        !           565:     return unix_hostname();
        !           566: 
        !           567:   dyn = dynhn_find_by_id (sysid);
        !           568:   if (dyn)
        !           569:     return (const char *)dyn->name.name;
        !           570: 
        !           571:   return sysid_print (sysid);
        !           572: }
        !           573: 
        !           574: /*
        !           575:  * This function is a generic utility that logs data of given length.
        !           576:  * Move this to a shared lib so that any protocol can use it.
        !           577:  */
        !           578: void
        !           579: zlog_dump_data (void *data, int len)
        !           580: {
        !           581:   int i;
        !           582:   unsigned char *p;
        !           583:   unsigned char c;
        !           584:   char bytestr[4];
        !           585:   char addrstr[10];
        !           586:   char hexstr[ 16*3 + 5];
        !           587:   char charstr[16*1 + 5];
        !           588: 
        !           589:   p = data;
        !           590:   memset (bytestr, 0, sizeof(bytestr));
        !           591:   memset (addrstr, 0, sizeof(addrstr));
        !           592:   memset (hexstr, 0, sizeof(hexstr));
        !           593:   memset (charstr, 0, sizeof(charstr));
        !           594: 
        !           595:   for (i = 1; i <= len; i++)
        !           596:   {
        !           597:     c = *p;
        !           598:     if (isalnum (c) == 0)
        !           599:       c = '.';
        !           600: 
        !           601:     /* store address for this line */
        !           602:     if ((i % 16) == 1)
        !           603:       snprintf (addrstr, sizeof(addrstr), "%p", p);
        !           604: 
        !           605:     /* store hex str (for left side) */
        !           606:     snprintf (bytestr, sizeof (bytestr), "%02X ", *p);
        !           607:     strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1);
        !           608: 
        !           609:     /* store char str (for right side) */
        !           610:     snprintf (bytestr, sizeof (bytestr), "%c", c);
        !           611:     strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1);
        !           612: 
        !           613:     if ((i % 16) == 0)
        !           614:     {
        !           615:       /* line completed */
        !           616:       zlog_debug ("[%8.8s]   %-50.50s  %s", addrstr, hexstr, charstr);
        !           617:       hexstr[0] = 0;
        !           618:       charstr[0] = 0;
        !           619:     }
        !           620:     else if ((i % 8) == 0)
        !           621:     {
        !           622:       /* half line: add whitespaces */
        !           623:       strncat (hexstr, "  ", sizeof (hexstr) - strlen (hexstr) - 1);
        !           624:       strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1);
        !           625:     }
        !           626:     p++; /* next byte */
        !           627:   }
        !           628: 
        !           629:   /* print rest of buffer if not empty */
        !           630:   if (strlen (hexstr) > 0)
        !           631:     zlog_debug ("[%8.8s]   %-50.50s  %s", addrstr, hexstr, charstr);
        !           632:   return;
        !           633: }

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