]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_misc.c
Sync bgpd and ripd set_metric_addsub_cmd commands. Fixes bugzilla #192.
[mirror_frr.git] / isisd / isis_misc.c
CommitLineData
eb5d44eb 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
eb5d44eb 24#include <stdlib.h>
25#include <stdio.h>
26#include <time.h>
27#include <ctype.h>
28#include <zebra.h>
9e867fe6 29#include <sys/utsname.h>
eb5d44eb 30
31#include "stream.h"
32#include "vty.h"
33#include "hash.h"
34#include "if.h"
9e867fe6 35#include "command.h"
eb5d44eb 36
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
73d1aead 49/* 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
eb5d44eb 64/*
65 * This converts the isonet to its printable format
66 */
1cd80845 67const char *
f390d2c7 68isonet_print (u_char * from, int len)
69{
eb5d44eb 70 int i = 0;
71 char *pos = isonet;
72
f390d2c7 73 if (!from)
eb5d44eb 74 return "unknown";
75
f390d2c7 76 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++;
eb5d44eb 97 }
eb5d44eb 98 *(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
f390d2c7 107dotformat2buff (u_char * buff, u_char * dotted)
eb5d44eb 108{
109 int dotlen, len = 0;
110 u_char *pos = dotted;
111 u_char number[3];
112 int nextdotpos = 2;
113
114 number[2] = '\0';
f7c43dcb 115 dotlen = strlen ((char *)dotted);
f390d2c7 116 if (dotlen > 50)
117 {
118 /* this can't be an iso net, its too long */
119 return 0;
eb5d44eb 120 }
121
f390d2c7 122 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
f7c43dcb 154 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
f390d2c7 155 len++;
eb5d44eb 156 }
157
eb5d44eb 158 return len;
159}
f390d2c7 160
eb5d44eb 161/*
162 * conversion of XXXX.XXXX.XXXX to memory
163 */
164int
f390d2c7 165sysid2buff (u_char * buff, u_char * dotted)
166{
eb5d44eb 167 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
f7c43dcb 173 if (strlen ((char *)dotted) != 14)
f390d2c7 174 {
175 return 0;
eb5d44eb 176 }
177
f390d2c7 178 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
f7c43dcb 202 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
f390d2c7 203 len++;
204 }
eb5d44eb 205
206 return len;
207
208}
209
210/*
211 * converts the nlpids struct (filled by TLV #129)
212 * into a string
213 */
214
215char *
f390d2c7 216nlpid2string (struct nlpids *nlpids)
217{
eb5d44eb 218 char *pos = nlpidstring;
219 int i;
220
f390d2c7 221 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
eb5d44eb 247 }
eb5d44eb 248
249 *(pos) = '\0';
f390d2c7 250
eb5d44eb 251 return nlpidstring;
252}
253
254/*
255 * supports the given af ?
256 */
f390d2c7 257int
eb5d44eb 258speaks (struct nlpids *nlpids, int family)
259{
260 int i, speaks = 0;
f390d2c7 261
262 if (nlpids == (struct nlpids *) NULL)
eb5d44eb 263 return speaks;
f390d2c7 264 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 }
eb5d44eb 271
272 return speaks;
273}
274
eb5d44eb 275/*
276 * Returns 0 on error, IS-IS Circuit Type on ok
277 */
f390d2c7 278int
279string2circuit_t (u_char * str)
eb5d44eb 280{
f390d2c7 281
eb5d44eb 282 if (!str)
283 return 0;
f390d2c7 284
f7c43dcb 285 if (!strcmp ((char *)str, "level-1"))
eb5d44eb 286 return IS_LEVEL_1;
287
f7c43dcb 288 if (!strcmp ((char *)str, "level-2-only") || !strcmp ((char *)str, "level-2"))
eb5d44eb 289 return IS_LEVEL_2;
f390d2c7 290
f7c43dcb 291 if (!strcmp ((char *)str, "level-1-2"))
eb5d44eb 292 return IS_LEVEL_1_AND_2;
293
294 return 0;
295}
296
297const char *
298circuit_t2string (int circuit_t)
299{
f390d2c7 300 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 }
311
312 return NULL; /* not reached */
eb5d44eb 313}
314
315const char *
316syst2string (int type)
317{
f390d2c7 318 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 }
331
332 return NULL; /* not reached */
eb5d44eb 333}
334
335/*
336 * Print functions - we print to static vars
337 */
1cd80845 338const char *
f390d2c7 339snpa_print (u_char * from)
eb5d44eb 340{
341 int i = 0;
f7c43dcb 342 u_char *pos = (u_char *)snpa;
eb5d44eb 343
f390d2c7 344 if (!from)
eb5d44eb 345 return "unknown";
eb5d44eb 346
f390d2c7 347 while (i < ETH_ALEN - 1)
348 {
349 if (i & 1)
350 {
f7c43dcb 351 sprintf ((char *)pos, "%02x.", *(from + i));
f390d2c7 352 pos += 3;
353 }
354 else
355 {
f7c43dcb 356 sprintf ((char *)pos, "%02x", *(from + i));
f390d2c7 357 pos += 2;
358
359 }
360 i++;
eb5d44eb 361 }
eb5d44eb 362
f7c43dcb 363 sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
eb5d44eb 364 pos += 2;
365 *(pos) = '\0';
366
367 return snpa;
368}
369
1cd80845 370const char *
f390d2c7 371sysid_print (u_char * from)
eb5d44eb 372{
373 int i = 0;
374 char *pos = sysid;
375
f390d2c7 376 if (!from)
eb5d44eb 377 return "unknown";
378
f390d2c7 379 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 }
eb5d44eb 394
395 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
396 pos += 2;
397 *(pos) = '\0';
f390d2c7 398
eb5d44eb 399 return sysid;
400}
401
1cd80845 402const char *
f390d2c7 403rawlspid_print (u_char * from)
eb5d44eb 404{
405 char *pos = lspid;
f390d2c7 406 if (!from)
eb5d44eb 407 return "unknown";
f390d2c7 408 memcpy (pos, sysid_print (from), 15);
eb5d44eb 409 pos += 14;
f390d2c7 410 sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
eb5d44eb 411 pos += 3;
f390d2c7 412 sprintf (pos, "-%02x", LSP_FRAGMENT (from));
eb5d44eb 413 pos += 3;
414
415 *(pos) = '\0';
416
417 return lspid;
418}
419
1cd80845 420const char *
f390d2c7 421time2string (u_int32_t time)
422{
423 char *pos = datestring;
eb5d44eb 424 u_int32_t rest;
425
f390d2c7 426 if (time == 0)
eb5d44eb 427 return "-";
428
f390d2c7 429 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
eb5d44eb 450 *(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 */
f390d2c7 462unsigned long
eb5d44eb 463isis_jitter (unsigned long timer, unsigned long jitter)
464{
f390d2c7 465 int j, k;
eb5d44eb 466
f390d2c7 467 if (jitter >= 100)
eb5d44eb 468 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
f390d2c7 479 j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
eb5d44eb 480
f390d2c7 481 k = timer - (timer * (100 - jitter)) / 100;
eb5d44eb 482
483 timer = timer - (k * j / RANDOM_SPREAD);
484
485 return timer;
486}
487
488struct in_addr
f390d2c7 489newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
eb5d44eb 490{
f390d2c7 491 memset (&new_prefix, 0, sizeof (new_prefix));
492 memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
493 ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
eb5d44eb 494 return new_prefix;
495}
496
9e867fe6 497/*
498 * Returns host.name if any, otherwise
499 * it returns the system hostname.
500 */
501const char *
f390d2c7 502unix_hostname (void)
9e867fe6 503{
504 static struct utsname names;
505 const char *hostname;
506 extern struct host host;
507
508 hostname = host.name;
f390d2c7 509 if (!hostname)
510 {
511 uname (&names);
512 hostname = names.nodename;
513 }
eb5d44eb 514
9e867fe6 515 return hostname;
516}