blob: 51c4d92992469c98ba8f9e8cc0200b7db2ef7295 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
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
jardineb5d44e2003-12-23 08:09:43 +000024#include <stdlib.h>
25#include <stdio.h>
26#include <time.h>
27#include <ctype.h>
28#include <zebra.h>
jardin9e867fe2003-12-23 08:56:18 +000029#include <sys/utsname.h>
jardineb5d44e2003-12-23 08:09:43 +000030
31#include "stream.h"
32#include "vty.h"
33#include "hash.h"
34#include "if.h"
jardin9e867fe2003-12-23 08:56:18 +000035#include "command.h"
jardineb5d44e2003-12-23 08:09:43 +000036
37#include "isisd/dict.h"
38#include "isisd/isis_constants.h"
39#include "isisd/isis_common.h"
40#include "isisd/isis_circuit.h"
41#include "isisd/isisd.h"
42#include "isisd/isis_misc.h"
43
44#include "isisd/isis_tlv.h"
45#include "isisd/isis_lsp.h"
46#include "isisd/isis_constants.h"
47#include "isisd/isis_adjacency.h"
48
hasso73d1aea2004-09-24 10:45:28 +000049/* staticly assigned vars for printing purposes */
50struct in_addr new_prefix;
51/* len of xxxx.xxxx.xxxx + place for #0 termination */
52char sysid[15];
53/* len of xxxx.xxxx.xxxx + place for #0 termination */
54char snpa[15];
55/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
56char isonet[51];
57/* + place for #0 termination */
58/* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
59char lspid[21];
60/* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
61char datestring[20];
62char nlpidstring[30];
63
jardineb5d44e2003-12-23 08:09:43 +000064/*
65 * This converts the isonet to its printable format
66 */
hassof390d2c2004-09-10 20:48:21 +000067char *
68isonet_print (u_char * from, int len)
69{
jardineb5d44e2003-12-23 08:09:43 +000070 int i = 0;
71 char *pos = isonet;
72
hassof390d2c2004-09-10 20:48:21 +000073 if (!from)
jardineb5d44e2003-12-23 08:09:43 +000074 return "unknown";
75
hassof390d2c2004-09-10 20:48:21 +000076 while (i < len)
77 {
78 if (i & 1)
79 {
80 sprintf (pos, "%02x", *(from + i));
81 pos += 2;
82 }
83 else
84 {
85 if (i == (len - 1))
86 { /* No dot at the end of address */
87 sprintf (pos, "%02x", *(from + i));
88 pos += 2;
89 }
90 else
91 {
92 sprintf (pos, "%02x.", *(from + i));
93 pos += 3;
94 }
95 }
96 i++;
jardineb5d44e2003-12-23 08:09:43 +000097 }
jardineb5d44e2003-12-23 08:09:43 +000098 *(pos) = '\0';
99 return isonet;
100}
101
102/*
103 * Returns 0 on error, length of buff on ok
104 * extract dot from the dotted str, and insert all the number in a buff
105 */
106int
hassof390d2c2004-09-10 20:48:21 +0000107dotformat2buff (u_char * buff, u_char * dotted)
jardineb5d44e2003-12-23 08:09:43 +0000108{
109 int dotlen, len = 0;
110 u_char *pos = dotted;
111 u_char number[3];
112 int nextdotpos = 2;
113
114 number[2] = '\0';
hassof390d2c2004-09-10 20:48:21 +0000115 dotlen = strlen (dotted);
116 if (dotlen > 50)
117 {
118 /* this can't be an iso net, its too long */
119 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000120 }
121
hassof390d2c2004-09-10 20:48:21 +0000122 while ((pos - dotted) < dotlen && len < 20)
123 {
124 if (*pos == '.')
125 {
126 /* we expect the . at 2, and than every 5 */
127 if ((pos - dotted) != nextdotpos)
128 {
129 len = 0;
130 break;
131 }
132 nextdotpos += 5;
133 pos++;
134 continue;
135 }
136 /* we must have at least two chars left here */
137 if (dotlen - (pos - dotted) < 2)
138 {
139 len = 0;
140 break;
141 }
142
143 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
144 {
145 memcpy (number, pos, 2);
146 pos += 2;
147 }
148 else
149 {
150 len = 0;
151 break;
152 }
153
154 *(buff + len) = (char) strtol (number, NULL, 16);
155 len++;
jardineb5d44e2003-12-23 08:09:43 +0000156 }
157
jardineb5d44e2003-12-23 08:09:43 +0000158 return len;
159}
hassof390d2c2004-09-10 20:48:21 +0000160
jardineb5d44e2003-12-23 08:09:43 +0000161/*
162 * conversion of XXXX.XXXX.XXXX to memory
163 */
164int
hassof390d2c2004-09-10 20:48:21 +0000165sysid2buff (u_char * buff, u_char * dotted)
166{
jardineb5d44e2003-12-23 08:09:43 +0000167 int len = 0;
168 u_char *pos = dotted;
169 u_char number[3];
170
171 number[2] = '\0';
172 // surely not a sysid_string if not 14 length
hassof390d2c2004-09-10 20:48:21 +0000173 if (strlen (dotted) != 14)
174 {
175 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000176 }
177
hassof390d2c2004-09-10 20:48:21 +0000178 while (len < ISIS_SYS_ID_LEN)
179 {
180 if (*pos == '.')
181 {
182 /* the . is not positioned correctly */
183 if (((pos - dotted) != 4) && ((pos - dotted) != 9))
184 {
185 len = 0;
186 break;
187 }
188 pos++;
189 continue;
190 }
191 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
192 {
193 memcpy (number, pos, 2);
194 pos += 2;
195 }
196 else
197 {
198 len = 0;
199 break;
200 }
201
202 *(buff + len) = (char) strtol (number, NULL, 16);
203 len++;
204 }
jardineb5d44e2003-12-23 08:09:43 +0000205
206 return len;
207
208}
209
210/*
211 * converts the nlpids struct (filled by TLV #129)
212 * into a string
213 */
214
215char *
hassof390d2c2004-09-10 20:48:21 +0000216nlpid2string (struct nlpids *nlpids)
217{
jardineb5d44e2003-12-23 08:09:43 +0000218 char *pos = nlpidstring;
219 int i;
220
hassof390d2c2004-09-10 20:48:21 +0000221 for (i = 0; i < nlpids->count; i++)
222 {
223 switch (nlpids->nlpids[i])
224 {
225 case NLPID_IP:
226 pos += sprintf (pos, "IPv4");
227 break;
228 case NLPID_IPV6:
229 pos += sprintf (pos, "IPv6");
230 break;
231 case NLPID_SNAP:
232 pos += sprintf (pos, "SNAP");
233 break;
234 case NLPID_CLNP:
235 pos += sprintf (pos, "CLNP");
236 break;
237 case NLPID_ESIS:
238 pos += sprintf (pos, "ES-IS");
239 break;
240 default:
241 pos += sprintf (pos, "unknown");
242 break;
243 }
244 if (nlpids->count - i > 1)
245 pos += sprintf (pos, ", ");
246
jardineb5d44e2003-12-23 08:09:43 +0000247 }
jardineb5d44e2003-12-23 08:09:43 +0000248
249 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000250
jardineb5d44e2003-12-23 08:09:43 +0000251 return nlpidstring;
252}
253
254/*
255 * supports the given af ?
256 */
hassof390d2c2004-09-10 20:48:21 +0000257int
jardineb5d44e2003-12-23 08:09:43 +0000258speaks (struct nlpids *nlpids, int family)
259{
260 int i, speaks = 0;
hassof390d2c2004-09-10 20:48:21 +0000261
262 if (nlpids == (struct nlpids *) NULL)
jardineb5d44e2003-12-23 08:09:43 +0000263 return speaks;
hassof390d2c2004-09-10 20:48:21 +0000264 for (i = 0; i < nlpids->count; i++)
265 {
266 if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
267 speaks = 1;
268 if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
269 speaks = 1;
270 }
jardineb5d44e2003-12-23 08:09:43 +0000271
272 return speaks;
273}
274
jardineb5d44e2003-12-23 08:09:43 +0000275/*
276 * Returns 0 on error, IS-IS Circuit Type on ok
277 */
hassof390d2c2004-09-10 20:48:21 +0000278int
279string2circuit_t (u_char * str)
jardineb5d44e2003-12-23 08:09:43 +0000280{
hassof390d2c2004-09-10 20:48:21 +0000281
jardineb5d44e2003-12-23 08:09:43 +0000282 if (!str)
283 return 0;
hassof390d2c2004-09-10 20:48:21 +0000284
285 if (!strcmp (str, "level-1"))
jardineb5d44e2003-12-23 08:09:43 +0000286 return IS_LEVEL_1;
287
hassof390d2c2004-09-10 20:48:21 +0000288 if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
jardineb5d44e2003-12-23 08:09:43 +0000289 return IS_LEVEL_2;
hassof390d2c2004-09-10 20:48:21 +0000290
291 if (!strcmp (str, "level-1-2"))
jardineb5d44e2003-12-23 08:09:43 +0000292 return IS_LEVEL_1_AND_2;
293
294 return 0;
295}
296
297const char *
298circuit_t2string (int circuit_t)
299{
hassof390d2c2004-09-10 20:48:21 +0000300 switch (circuit_t)
301 {
302 case IS_LEVEL_1:
303 return "L1";
304 case IS_LEVEL_2:
305 return "L2";
306 case IS_LEVEL_1_AND_2:
307 return "L1L2";
308 default:
309 return "??";
310 }
jardineb5d44e2003-12-23 08:09:43 +0000311
hassof390d2c2004-09-10 20:48:21 +0000312 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000313}
314
315const char *
316syst2string (int type)
317{
hassof390d2c2004-09-10 20:48:21 +0000318 switch (type)
319 {
320 case ISIS_SYSTYPE_ES:
321 return "ES";
322 case ISIS_SYSTYPE_IS:
323 return "IS";
324 case ISIS_SYSTYPE_L1_IS:
325 return "1";
326 case ISIS_SYSTYPE_L2_IS:
327 return "2";
328 default:
329 return "??";
330 }
jardineb5d44e2003-12-23 08:09:43 +0000331
hassof390d2c2004-09-10 20:48:21 +0000332 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000333}
334
335/*
336 * Print functions - we print to static vars
337 */
338char *
hassof390d2c2004-09-10 20:48:21 +0000339snpa_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000340{
341 int i = 0;
342 u_char *pos = snpa;
343
hassof390d2c2004-09-10 20:48:21 +0000344 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000345 return "unknown";
jardineb5d44e2003-12-23 08:09:43 +0000346
hassof390d2c2004-09-10 20:48:21 +0000347 while (i < ETH_ALEN - 1)
348 {
349 if (i & 1)
350 {
351 sprintf (pos, "%02x.", *(from + i));
352 pos += 3;
353 }
354 else
355 {
356 sprintf (pos, "%02x", *(from + i));
357 pos += 2;
358
359 }
360 i++;
jardineb5d44e2003-12-23 08:09:43 +0000361 }
jardineb5d44e2003-12-23 08:09:43 +0000362
363 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
364 pos += 2;
365 *(pos) = '\0';
366
367 return snpa;
368}
369
370char *
hassof390d2c2004-09-10 20:48:21 +0000371sysid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000372{
373 int i = 0;
374 char *pos = sysid;
375
hassof390d2c2004-09-10 20:48:21 +0000376 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000377 return "unknown";
378
hassof390d2c2004-09-10 20:48:21 +0000379 while (i < ISIS_SYS_ID_LEN - 1)
380 {
381 if (i & 1)
382 {
383 sprintf (pos, "%02x.", *(from + i));
384 pos += 3;
385 }
386 else
387 {
388 sprintf (pos, "%02x", *(from + i));
389 pos += 2;
390
391 }
392 i++;
393 }
jardineb5d44e2003-12-23 08:09:43 +0000394
395 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
396 pos += 2;
397 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000398
jardineb5d44e2003-12-23 08:09:43 +0000399 return sysid;
400}
401
402char *
hassof390d2c2004-09-10 20:48:21 +0000403rawlspid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000404{
405 char *pos = lspid;
hassof390d2c2004-09-10 20:48:21 +0000406 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000407 return "unknown";
hassof390d2c2004-09-10 20:48:21 +0000408 memcpy (pos, sysid_print (from), 15);
jardineb5d44e2003-12-23 08:09:43 +0000409 pos += 14;
hassof390d2c2004-09-10 20:48:21 +0000410 sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
jardineb5d44e2003-12-23 08:09:43 +0000411 pos += 3;
hassof390d2c2004-09-10 20:48:21 +0000412 sprintf (pos, "-%02x", LSP_FRAGMENT (from));
jardineb5d44e2003-12-23 08:09:43 +0000413 pos += 3;
414
415 *(pos) = '\0';
416
417 return lspid;
418}
419
420char *
hassof390d2c2004-09-10 20:48:21 +0000421time2string (u_int32_t time)
422{
423 char *pos = datestring;
jardineb5d44e2003-12-23 08:09:43 +0000424 u_int32_t rest;
425
hassof390d2c2004-09-10 20:48:21 +0000426 if (time == 0)
jardineb5d44e2003-12-23 08:09:43 +0000427 return "-";
428
hassof390d2c2004-09-10 20:48:21 +0000429 if (time / SECS_PER_YEAR)
430 pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
431 rest = time % SECS_PER_YEAR;
432 if (rest / SECS_PER_MONTH)
433 pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
434 rest = rest % SECS_PER_MONTH;
435 if (rest / SECS_PER_WEEK)
436 pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
437 rest = rest % SECS_PER_WEEK;
438 if (rest / SECS_PER_DAY)
439 pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
440 rest = rest % SECS_PER_DAY;
441 if (rest / SECS_PER_HOUR)
442 pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
443 rest = rest % SECS_PER_HOUR;
444 if (rest / SECS_PER_MINUTE)
445 pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
446 rest = rest % SECS_PER_MINUTE;
447 if (rest)
448 pos += sprintf (pos, "%us", rest);
449
jardineb5d44e2003-12-23 08:09:43 +0000450 *(pos) = 0;
451
452 return datestring;
453}
454
455/*
456 * routine to decrement a timer by a random
457 * number
458 *
459 * first argument is the timer and the second is
460 * the jitter
461 */
hassof390d2c2004-09-10 20:48:21 +0000462unsigned long
jardineb5d44e2003-12-23 08:09:43 +0000463isis_jitter (unsigned long timer, unsigned long jitter)
464{
hassof390d2c2004-09-10 20:48:21 +0000465 int j, k;
jardineb5d44e2003-12-23 08:09:43 +0000466
hassof390d2c2004-09-10 20:48:21 +0000467 if (jitter >= 100)
jardineb5d44e2003-12-23 08:09:43 +0000468 return timer;
469
470 if (timer == 1)
471 return timer;
472 /*
473 * randomizing just the percent value provides
474 * no good random numbers - hence the spread
475 * to RANDOM_SPREAD (100000), which is ok as
476 * most IS-IS timers are no longer than 16 bit
477 */
478
hassof390d2c2004-09-10 20:48:21 +0000479 j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
jardineb5d44e2003-12-23 08:09:43 +0000480
hassof390d2c2004-09-10 20:48:21 +0000481 k = timer - (timer * (100 - jitter)) / 100;
jardineb5d44e2003-12-23 08:09:43 +0000482
483 timer = timer - (k * j / RANDOM_SPREAD);
484
485 return timer;
486}
487
488struct in_addr
hassof390d2c2004-09-10 20:48:21 +0000489newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
jardineb5d44e2003-12-23 08:09:43 +0000490{
hassof390d2c2004-09-10 20:48:21 +0000491 memset (&new_prefix, 0, sizeof (new_prefix));
492 memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
493 ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
jardineb5d44e2003-12-23 08:09:43 +0000494 return new_prefix;
495}
496
jardin9e867fe2003-12-23 08:56:18 +0000497/*
498 * Returns host.name if any, otherwise
499 * it returns the system hostname.
500 */
501const char *
hassof390d2c2004-09-10 20:48:21 +0000502unix_hostname (void)
jardin9e867fe2003-12-23 08:56:18 +0000503{
504 static struct utsname names;
505 const char *hostname;
506 extern struct host host;
jardineb5d44e2003-12-23 08:09:43 +0000507
jardin9e867fe2003-12-23 08:56:18 +0000508 hostname = host.name;
hassof390d2c2004-09-10 20:48:21 +0000509 if (!hostname)
510 {
511 uname (&names);
512 hostname = names.nodename;
513 }
jardineb5d44e2003-12-23 08:09:43 +0000514
jardin9e867fe2003-12-23 08:56:18 +0000515 return hostname;
516}