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