blob: 7fe5286f7d37299986a8e777f007fd8cb6bbfff0 [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
49/*
50 * This converts the isonet to its printable format
51 */
hassof390d2c2004-09-10 20:48:21 +000052char *
53isonet_print (u_char * from, int len)
54{
jardineb5d44e2003-12-23 08:09:43 +000055 int i = 0;
56 char *pos = isonet;
57
hassof390d2c2004-09-10 20:48:21 +000058 if (!from)
jardineb5d44e2003-12-23 08:09:43 +000059 return "unknown";
60
hassof390d2c2004-09-10 20:48:21 +000061 while (i < len)
62 {
63 if (i & 1)
64 {
65 sprintf (pos, "%02x", *(from + i));
66 pos += 2;
67 }
68 else
69 {
70 if (i == (len - 1))
71 { /* No dot at the end of address */
72 sprintf (pos, "%02x", *(from + i));
73 pos += 2;
74 }
75 else
76 {
77 sprintf (pos, "%02x.", *(from + i));
78 pos += 3;
79 }
80 }
81 i++;
jardineb5d44e2003-12-23 08:09:43 +000082 }
jardineb5d44e2003-12-23 08:09:43 +000083 *(pos) = '\0';
84 return isonet;
85}
86
87/*
88 * Returns 0 on error, length of buff on ok
89 * extract dot from the dotted str, and insert all the number in a buff
90 */
91int
hassof390d2c2004-09-10 20:48:21 +000092dotformat2buff (u_char * buff, u_char * dotted)
jardineb5d44e2003-12-23 08:09:43 +000093{
94 int dotlen, len = 0;
95 u_char *pos = dotted;
96 u_char number[3];
97 int nextdotpos = 2;
98
99 number[2] = '\0';
hassof390d2c2004-09-10 20:48:21 +0000100 dotlen = strlen (dotted);
101 if (dotlen > 50)
102 {
103 /* this can't be an iso net, its too long */
104 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000105 }
106
hassof390d2c2004-09-10 20:48:21 +0000107 while ((pos - dotted) < dotlen && len < 20)
108 {
109 if (*pos == '.')
110 {
111 /* we expect the . at 2, and than every 5 */
112 if ((pos - dotted) != nextdotpos)
113 {
114 len = 0;
115 break;
116 }
117 nextdotpos += 5;
118 pos++;
119 continue;
120 }
121 /* we must have at least two chars left here */
122 if (dotlen - (pos - dotted) < 2)
123 {
124 len = 0;
125 break;
126 }
127
128 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
129 {
130 memcpy (number, pos, 2);
131 pos += 2;
132 }
133 else
134 {
135 len = 0;
136 break;
137 }
138
139 *(buff + len) = (char) strtol (number, NULL, 16);
140 len++;
jardineb5d44e2003-12-23 08:09:43 +0000141 }
142
jardineb5d44e2003-12-23 08:09:43 +0000143 return len;
144}
hassof390d2c2004-09-10 20:48:21 +0000145
jardineb5d44e2003-12-23 08:09:43 +0000146/*
147 * conversion of XXXX.XXXX.XXXX to memory
148 */
149int
hassof390d2c2004-09-10 20:48:21 +0000150sysid2buff (u_char * buff, u_char * dotted)
151{
jardineb5d44e2003-12-23 08:09:43 +0000152 int len = 0;
153 u_char *pos = dotted;
154 u_char number[3];
155
156 number[2] = '\0';
157 // surely not a sysid_string if not 14 length
hassof390d2c2004-09-10 20:48:21 +0000158 if (strlen (dotted) != 14)
159 {
160 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000161 }
162
hassof390d2c2004-09-10 20:48:21 +0000163 while (len < ISIS_SYS_ID_LEN)
164 {
165 if (*pos == '.')
166 {
167 /* the . is not positioned correctly */
168 if (((pos - dotted) != 4) && ((pos - dotted) != 9))
169 {
170 len = 0;
171 break;
172 }
173 pos++;
174 continue;
175 }
176 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
177 {
178 memcpy (number, pos, 2);
179 pos += 2;
180 }
181 else
182 {
183 len = 0;
184 break;
185 }
186
187 *(buff + len) = (char) strtol (number, NULL, 16);
188 len++;
189 }
jardineb5d44e2003-12-23 08:09:43 +0000190
191 return len;
192
193}
194
195/*
196 * converts the nlpids struct (filled by TLV #129)
197 * into a string
198 */
199
200char *
hassof390d2c2004-09-10 20:48:21 +0000201nlpid2string (struct nlpids *nlpids)
202{
jardineb5d44e2003-12-23 08:09:43 +0000203 char *pos = nlpidstring;
204 int i;
205
hassof390d2c2004-09-10 20:48:21 +0000206 for (i = 0; i < nlpids->count; i++)
207 {
208 switch (nlpids->nlpids[i])
209 {
210 case NLPID_IP:
211 pos += sprintf (pos, "IPv4");
212 break;
213 case NLPID_IPV6:
214 pos += sprintf (pos, "IPv6");
215 break;
216 case NLPID_SNAP:
217 pos += sprintf (pos, "SNAP");
218 break;
219 case NLPID_CLNP:
220 pos += sprintf (pos, "CLNP");
221 break;
222 case NLPID_ESIS:
223 pos += sprintf (pos, "ES-IS");
224 break;
225 default:
226 pos += sprintf (pos, "unknown");
227 break;
228 }
229 if (nlpids->count - i > 1)
230 pos += sprintf (pos, ", ");
231
jardineb5d44e2003-12-23 08:09:43 +0000232 }
jardineb5d44e2003-12-23 08:09:43 +0000233
234 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000235
jardineb5d44e2003-12-23 08:09:43 +0000236 return nlpidstring;
237}
238
239/*
240 * supports the given af ?
241 */
hassof390d2c2004-09-10 20:48:21 +0000242int
jardineb5d44e2003-12-23 08:09:43 +0000243speaks (struct nlpids *nlpids, int family)
244{
245 int i, speaks = 0;
hassof390d2c2004-09-10 20:48:21 +0000246
247 if (nlpids == (struct nlpids *) NULL)
jardineb5d44e2003-12-23 08:09:43 +0000248 return speaks;
hassof390d2c2004-09-10 20:48:21 +0000249 for (i = 0; i < nlpids->count; i++)
250 {
251 if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
252 speaks = 1;
253 if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
254 speaks = 1;
255 }
jardineb5d44e2003-12-23 08:09:43 +0000256
257 return speaks;
258}
259
jardineb5d44e2003-12-23 08:09:43 +0000260/*
261 * Returns 0 on error, IS-IS Circuit Type on ok
262 */
hassof390d2c2004-09-10 20:48:21 +0000263int
264string2circuit_t (u_char * str)
jardineb5d44e2003-12-23 08:09:43 +0000265{
hassof390d2c2004-09-10 20:48:21 +0000266
jardineb5d44e2003-12-23 08:09:43 +0000267 if (!str)
268 return 0;
hassof390d2c2004-09-10 20:48:21 +0000269
270 if (!strcmp (str, "level-1"))
jardineb5d44e2003-12-23 08:09:43 +0000271 return IS_LEVEL_1;
272
hassof390d2c2004-09-10 20:48:21 +0000273 if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
jardineb5d44e2003-12-23 08:09:43 +0000274 return IS_LEVEL_2;
hassof390d2c2004-09-10 20:48:21 +0000275
276 if (!strcmp (str, "level-1-2"))
jardineb5d44e2003-12-23 08:09:43 +0000277 return IS_LEVEL_1_AND_2;
278
279 return 0;
280}
281
282const char *
283circuit_t2string (int circuit_t)
284{
hassof390d2c2004-09-10 20:48:21 +0000285 switch (circuit_t)
286 {
287 case IS_LEVEL_1:
288 return "L1";
289 case IS_LEVEL_2:
290 return "L2";
291 case IS_LEVEL_1_AND_2:
292 return "L1L2";
293 default:
294 return "??";
295 }
jardineb5d44e2003-12-23 08:09:43 +0000296
hassof390d2c2004-09-10 20:48:21 +0000297 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000298}
299
300const char *
301syst2string (int type)
302{
hassof390d2c2004-09-10 20:48:21 +0000303 switch (type)
304 {
305 case ISIS_SYSTYPE_ES:
306 return "ES";
307 case ISIS_SYSTYPE_IS:
308 return "IS";
309 case ISIS_SYSTYPE_L1_IS:
310 return "1";
311 case ISIS_SYSTYPE_L2_IS:
312 return "2";
313 default:
314 return "??";
315 }
jardineb5d44e2003-12-23 08:09:43 +0000316
hassof390d2c2004-09-10 20:48:21 +0000317 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000318}
319
320/*
321 * Print functions - we print to static vars
322 */
323char *
hassof390d2c2004-09-10 20:48:21 +0000324snpa_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000325{
326 int i = 0;
327 u_char *pos = snpa;
328
hassof390d2c2004-09-10 20:48:21 +0000329 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000330 return "unknown";
jardineb5d44e2003-12-23 08:09:43 +0000331
hassof390d2c2004-09-10 20:48:21 +0000332 while (i < ETH_ALEN - 1)
333 {
334 if (i & 1)
335 {
336 sprintf (pos, "%02x.", *(from + i));
337 pos += 3;
338 }
339 else
340 {
341 sprintf (pos, "%02x", *(from + i));
342 pos += 2;
343
344 }
345 i++;
jardineb5d44e2003-12-23 08:09:43 +0000346 }
jardineb5d44e2003-12-23 08:09:43 +0000347
348 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
349 pos += 2;
350 *(pos) = '\0';
351
352 return snpa;
353}
354
355char *
hassof390d2c2004-09-10 20:48:21 +0000356sysid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000357{
358 int i = 0;
359 char *pos = sysid;
360
hassof390d2c2004-09-10 20:48:21 +0000361 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000362 return "unknown";
363
hassof390d2c2004-09-10 20:48:21 +0000364 while (i < ISIS_SYS_ID_LEN - 1)
365 {
366 if (i & 1)
367 {
368 sprintf (pos, "%02x.", *(from + i));
369 pos += 3;
370 }
371 else
372 {
373 sprintf (pos, "%02x", *(from + i));
374 pos += 2;
375
376 }
377 i++;
378 }
jardineb5d44e2003-12-23 08:09:43 +0000379
380 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
381 pos += 2;
382 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000383
jardineb5d44e2003-12-23 08:09:43 +0000384 return sysid;
385}
386
387char *
hassof390d2c2004-09-10 20:48:21 +0000388rawlspid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000389{
390 char *pos = lspid;
hassof390d2c2004-09-10 20:48:21 +0000391 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000392 return "unknown";
hassof390d2c2004-09-10 20:48:21 +0000393 memcpy (pos, sysid_print (from), 15);
jardineb5d44e2003-12-23 08:09:43 +0000394 pos += 14;
hassof390d2c2004-09-10 20:48:21 +0000395 sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
jardineb5d44e2003-12-23 08:09:43 +0000396 pos += 3;
hassof390d2c2004-09-10 20:48:21 +0000397 sprintf (pos, "-%02x", LSP_FRAGMENT (from));
jardineb5d44e2003-12-23 08:09:43 +0000398 pos += 3;
399
400 *(pos) = '\0';
401
402 return lspid;
403}
404
405char *
hassof390d2c2004-09-10 20:48:21 +0000406time2string (u_int32_t time)
407{
408 char *pos = datestring;
jardineb5d44e2003-12-23 08:09:43 +0000409 u_int32_t rest;
410
hassof390d2c2004-09-10 20:48:21 +0000411 if (time == 0)
jardineb5d44e2003-12-23 08:09:43 +0000412 return "-";
413
hassof390d2c2004-09-10 20:48:21 +0000414 if (time / SECS_PER_YEAR)
415 pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
416 rest = time % SECS_PER_YEAR;
417 if (rest / SECS_PER_MONTH)
418 pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
419 rest = rest % SECS_PER_MONTH;
420 if (rest / SECS_PER_WEEK)
421 pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
422 rest = rest % SECS_PER_WEEK;
423 if (rest / SECS_PER_DAY)
424 pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
425 rest = rest % SECS_PER_DAY;
426 if (rest / SECS_PER_HOUR)
427 pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
428 rest = rest % SECS_PER_HOUR;
429 if (rest / SECS_PER_MINUTE)
430 pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
431 rest = rest % SECS_PER_MINUTE;
432 if (rest)
433 pos += sprintf (pos, "%us", rest);
434
jardineb5d44e2003-12-23 08:09:43 +0000435 *(pos) = 0;
436
437 return datestring;
438}
439
440/*
441 * routine to decrement a timer by a random
442 * number
443 *
444 * first argument is the timer and the second is
445 * the jitter
446 */
hassof390d2c2004-09-10 20:48:21 +0000447unsigned long
jardineb5d44e2003-12-23 08:09:43 +0000448isis_jitter (unsigned long timer, unsigned long jitter)
449{
hassof390d2c2004-09-10 20:48:21 +0000450 int j, k;
jardineb5d44e2003-12-23 08:09:43 +0000451
hassof390d2c2004-09-10 20:48:21 +0000452 if (jitter >= 100)
jardineb5d44e2003-12-23 08:09:43 +0000453 return timer;
454
455 if (timer == 1)
456 return timer;
457 /*
458 * randomizing just the percent value provides
459 * no good random numbers - hence the spread
460 * to RANDOM_SPREAD (100000), which is ok as
461 * most IS-IS timers are no longer than 16 bit
462 */
463
hassof390d2c2004-09-10 20:48:21 +0000464 j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
jardineb5d44e2003-12-23 08:09:43 +0000465
hassof390d2c2004-09-10 20:48:21 +0000466 k = timer - (timer * (100 - jitter)) / 100;
jardineb5d44e2003-12-23 08:09:43 +0000467
468 timer = timer - (k * j / RANDOM_SPREAD);
469
470 return timer;
471}
472
473struct in_addr
hassof390d2c2004-09-10 20:48:21 +0000474newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
jardineb5d44e2003-12-23 08:09:43 +0000475{
hassof390d2c2004-09-10 20:48:21 +0000476 memset (&new_prefix, 0, sizeof (new_prefix));
477 memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
478 ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
jardineb5d44e2003-12-23 08:09:43 +0000479 return new_prefix;
480}
481
jardin9e867fe2003-12-23 08:56:18 +0000482/*
483 * Returns host.name if any, otherwise
484 * it returns the system hostname.
485 */
486const char *
hassof390d2c2004-09-10 20:48:21 +0000487unix_hostname (void)
jardin9e867fe2003-12-23 08:56:18 +0000488{
489 static struct utsname names;
490 const char *hostname;
491 extern struct host host;
jardineb5d44e2003-12-23 08:09:43 +0000492
jardin9e867fe2003-12-23 08:56:18 +0000493 hostname = host.name;
hassof390d2c2004-09-10 20:48:21 +0000494 if (!hostname)
495 {
496 uname (&names);
497 hostname = names.nodename;
498 }
jardineb5d44e2003-12-23 08:09:43 +0000499
jardin9e867fe2003-12-23 08:56:18 +0000500 return hostname;
501}