blob: 709dbe4ff91da121b662898bceb1033b956ca4dc [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
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <time.h>
28#include <ctype.h>
29#include <zebra.h>
jardin9e867fe2003-12-23 08:56:18 +000030#include <sys/utsname.h>
jardineb5d44e2003-12-23 08:09:43 +000031
32#include "stream.h"
33#include "vty.h"
34#include "hash.h"
35#include "if.h"
jardin9e867fe2003-12-23 08:56:18 +000036#include "command.h"
jardineb5d44e2003-12-23 08:09:43 +000037
38#include "isisd/dict.h"
39#include "isisd/isis_constants.h"
40#include "isisd/isis_common.h"
41#include "isisd/isis_circuit.h"
42#include "isisd/isisd.h"
43#include "isisd/isis_misc.h"
44
45#include "isisd/isis_tlv.h"
46#include "isisd/isis_lsp.h"
47#include "isisd/isis_constants.h"
48#include "isisd/isis_adjacency.h"
49
50/*
51 * This converts the isonet to its printable format
52 */
53char * isonet_print (u_char *from, int len) {
54 int i = 0;
55 char *pos = isonet;
56
57 if(!from)
58 return "unknown";
59
60 while (i < len) {
61 if (i & 1) {
62 sprintf ( pos, "%02x", *(from + i));
63 pos += 2;
64 } else {
hasso2097cd82003-12-23 11:51:08 +000065 if (i == (len - 1)) { /* No dot at the end of address */
jardineb5d44e2003-12-23 08:09:43 +000066 sprintf ( pos, "%02x", *(from + i));
67 pos += 2;
68 } else {
69 sprintf ( pos, "%02x.", *(from + i));
70 pos += 3;
71 }
72 }
73 i++;
74 }
75 *(pos) = '\0';
76 return isonet;
77}
78
79/*
80 * Returns 0 on error, length of buff on ok
81 * extract dot from the dotted str, and insert all the number in a buff
82 */
83int
84dotformat2buff (u_char *buff, u_char *dotted)
85{
86 int dotlen, len = 0;
87 u_char *pos = dotted;
88 u_char number[3];
89 int nextdotpos = 2;
90
91 number[2] = '\0';
92 dotlen = strlen(dotted);
93 if (dotlen > 50) {
94 /* this can't be an iso net, its too long */
95 return 0;
96 }
97
98 while ( (pos - dotted) < dotlen && len < 20 ) {
99 if (*pos == '.') {
100 /* we expect the . at 2, and than every 5 */
101 if ((pos - dotted) != nextdotpos) {
102 len = 0;
103 break;
104 }
105 nextdotpos += 5;
106 pos++;
107 continue;
108 }
109 /* we must have at least two chars left here */
110 if (dotlen - (pos - dotted) < 2) {
111 len = 0;
112 break;
113 }
114
115 if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos+1)))){
116 memcpy (number, pos ,2);
117 pos+=2;
118 } else {
119 len = 0;
120 break;
121 }
122
123 *(buff + len) = (char)strtol(number, NULL, 16);
124 len++;
125 }
126
127 return len;
128}
129/*
130 * conversion of XXXX.XXXX.XXXX to memory
131 */
132int
133sysid2buff (u_char *buff, u_char *dotted)
134 {
135 int len = 0;
136 u_char *pos = dotted;
137 u_char number[3];
138
139 number[2] = '\0';
140 // surely not a sysid_string if not 14 length
141 if (strlen(dotted) != 14) {
142 return 0;
143 }
144
145 while ( len < ISIS_SYS_ID_LEN ) {
146 if (*pos == '.') {
147 /* the . is not positioned correctly */
148 if (((pos - dotted) !=4) && ((pos - dotted) != 9)) {
149 len = 0;
150 break;
151 }
152 pos++;
153 continue;
154 }
155 if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos+1)))){
156 memcpy (number, pos ,2);
157 pos+=2;
158 } else {
159 len = 0;
160 break;
161 }
162
163 *(buff + len) = (char)strtol(number, NULL, 16);
164 len++;
165 }
166
167 return len;
168
169}
170
171/*
172 * converts the nlpids struct (filled by TLV #129)
173 * into a string
174 */
175
176char *
177nlpid2string (struct nlpids *nlpids) {
178 char *pos = nlpidstring;
179 int i;
180
181 for (i=0;i<nlpids->count;i++) {
182 switch (nlpids->nlpids[i]) {
183 case NLPID_IP:
184 pos += sprintf (pos, "IPv4");
185 break;
186 case NLPID_IPV6:
187 pos += sprintf (pos, "IPv6");
188 break;
hasso2097cd82003-12-23 11:51:08 +0000189 case NLPID_SNAP:
190 pos += sprintf (pos, "SNAP");
191 break;
192 case NLPID_CLNP:
193 pos += sprintf (pos, "CLNP");
194 break;
195 case NLPID_ESIS:
196 pos += sprintf (pos, "ES-IS");
197 break;
jardineb5d44e2003-12-23 08:09:43 +0000198 default:
199 pos += sprintf (pos, "unknown");
200 break;
201 }
202 if (nlpids->count-i>1)
203 pos += sprintf (pos, ", ");
204
205 }
206
207 *(pos) = '\0';
208
209 return nlpidstring;
210}
211
212/*
213 * supports the given af ?
214 */
215int
216speaks (struct nlpids *nlpids, int family)
217{
218 int i, speaks = 0;
219
220 if (nlpids == (struct nlpids*)NULL)
221 return speaks;
222 for (i = 0;i < nlpids->count; i++) {
223 if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
224 speaks = 1;
225 if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
226 speaks = 1;
227 }
228
229 return speaks;
230}
231
232
233/*
234 * Returns 0 on error, IS-IS Circuit Type on ok
235 */
236int
237string2circuit_t (u_char *str)
238{
239
240 if (!str)
241 return 0;
242
243 if (!strcmp(str,"level-1"))
244 return IS_LEVEL_1;
245
246 if (!strcmp(str,"level-2-only") || !strcmp(str,"level-2"))
247 return IS_LEVEL_2;
248
249 if (!strcmp(str,"level-1-2"))
250 return IS_LEVEL_1_AND_2;
251
252 return 0;
253}
254
255const char *
256circuit_t2string (int circuit_t)
257{
258 switch (circuit_t) {
259 case IS_LEVEL_1:
260 return "L1";
261 case IS_LEVEL_2:
262 return "L2";
263 case IS_LEVEL_1_AND_2:
264 return "L1L2";
265 default:
266 return "??";
267 }
268
269 return NULL; /* not reached */
270}
271
272const char *
273syst2string (int type)
274{
275 switch (type) {
276 case ISIS_SYSTYPE_ES:
277 return "ES";
278 case ISIS_SYSTYPE_IS:
279 return "IS";
280 case ISIS_SYSTYPE_L1_IS:
281 return "1";
282 case ISIS_SYSTYPE_L2_IS:
283 return "2";
284 default:
285 return "??";
286 }
287
288 return NULL; /* not reached */
289}
290
291/*
292 * Print functions - we print to static vars
293 */
294char *
295snpa_print (u_char *from)
296{
297 int i = 0;
298 u_char *pos = snpa;
299
300 if(!from)
301 return "unknown";
302
303 while (i < ETH_ALEN - 1) {
304 if (i & 1) {
305 sprintf ( pos, "%02x.", *(from + i));
306 pos += 3;
307 } else {
308 sprintf ( pos, "%02x", *(from + i));
309 pos += 2;
310
311 }
312 i++;
313 }
314
315 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
316 pos += 2;
317 *(pos) = '\0';
318
319 return snpa;
320}
321
322char *
323sysid_print (u_char *from)
324{
325 int i = 0;
326 char *pos = sysid;
327
328 if(!from)
329 return "unknown";
330
331 while (i < ISIS_SYS_ID_LEN - 1) {
332 if (i & 1) {
333 sprintf ( pos, "%02x.", *(from + i));
334 pos += 3;
335 } else {
336 sprintf ( pos, "%02x", *(from + i));
337 pos += 2;
338
339 }
340 i++;
341 }
342
343 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
344 pos += 2;
345 *(pos) = '\0';
346
347 return sysid;
348}
349
350char *
351rawlspid_print (u_char *from)
352{
353 char *pos = lspid;
354 if(!from)
355 return "unknown";
356 memcpy(pos, sysid_print(from), 15);
357 pos += 14;
358 sprintf (pos, ".%02x", LSP_PSEUDO_ID(from));
359 pos += 3;
360 sprintf (pos, "-%02x", LSP_FRAGMENT(from));
361 pos += 3;
362
363 *(pos) = '\0';
364
365 return lspid;
366}
367
368char *
369time2string (u_int32_t time) {
370 char *pos = datestring;
371 u_int32_t rest;
372
373 if (time==0)
374 return "-";
375
376 if(time/SECS_PER_YEAR)
377 pos += sprintf (pos, "%uY",time/SECS_PER_YEAR);
378 rest=time%SECS_PER_YEAR;
379 if(rest/SECS_PER_MONTH)
380 pos += sprintf (pos, "%uM",rest/SECS_PER_MONTH);
381 rest=rest%SECS_PER_MONTH;
382 if(rest/SECS_PER_WEEK)
383 pos += sprintf (pos, "%uw",rest/SECS_PER_WEEK);
384 rest=rest%SECS_PER_WEEK;
385 if(rest/SECS_PER_DAY)
386 pos += sprintf (pos, "%ud",rest/SECS_PER_DAY);
387 rest=rest%SECS_PER_DAY;
388 if(rest/SECS_PER_HOUR)
389 pos += sprintf (pos, "%uh",rest/SECS_PER_HOUR);
390 rest=rest%SECS_PER_HOUR;
391 if(rest/SECS_PER_MINUTE)
392 pos += sprintf (pos, "%um",rest/SECS_PER_MINUTE);
393 rest=rest%SECS_PER_MINUTE;
394 if(rest)
395 pos += sprintf (pos, "%us",rest);
396
397 *(pos) = 0;
398
399 return datestring;
400}
401
402/*
403 * routine to decrement a timer by a random
404 * number
405 *
406 * first argument is the timer and the second is
407 * the jitter
408 */
409unsigned long
410isis_jitter (unsigned long timer, unsigned long jitter)
411{
412 int j,k;
413
414 if (jitter>=100)
415 return timer;
416
417 if (timer == 1)
418 return timer;
419 /*
420 * randomizing just the percent value provides
421 * no good random numbers - hence the spread
422 * to RANDOM_SPREAD (100000), which is ok as
423 * most IS-IS timers are no longer than 16 bit
424 */
425
426 j = 1 + (int) ((RANDOM_SPREAD * rand()) / (RAND_MAX + 1.0 ));
427
428 k = timer - (timer * (100 - jitter))/100;
429
430 timer = timer - (k * j / RANDOM_SPREAD);
431
432 return timer;
433}
434
435struct in_addr
436newprefix2inaddr (u_char *prefix_start, u_char prefix_masklen)
437{
438 memset(&new_prefix, 0, sizeof (new_prefix));
439 memcpy(&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
440 ((((prefix_masklen & 0x3F)-1)>>3)+1) : 0);
441 return new_prefix;
442}
443
jardin9e867fe2003-12-23 08:56:18 +0000444/*
445 * Returns host.name if any, otherwise
446 * it returns the system hostname.
447 */
448const char *
449unix_hostname(void)
450{
451 static struct utsname names;
452 const char *hostname;
453 extern struct host host;
jardineb5d44e2003-12-23 08:09:43 +0000454
jardin9e867fe2003-12-23 08:56:18 +0000455 hostname = host.name;
456 if (!hostname) {
457 uname(&names);
458 hostname = names.nodename;
459 }
jardineb5d44e2003-12-23 08:09:43 +0000460
jardin9e867fe2003-12-23 08:56:18 +0000461 return hostname;
462}