blob: 968fa05fe360e4231445723e3ec51cf607264e1b [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 <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000025
26#include "stream.h"
27#include "vty.h"
28#include "hash.h"
29#include "if.h"
jardin9e867fe2003-12-23 08:56:18 +000030#include "command.h"
jardineb5d44e2003-12-23 08:09:43 +000031
32#include "isisd/dict.h"
33#include "isisd/isis_constants.h"
34#include "isisd/isis_common.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070035#include "isisd/isis_flags.h"
jardineb5d44e2003-12-23 08:09:43 +000036#include "isisd/isis_circuit.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070037#include "isisd/isis_csm.h"
jardineb5d44e2003-12-23 08:09:43 +000038#include "isisd/isisd.h"
39#include "isisd/isis_misc.h"
40
41#include "isisd/isis_tlv.h"
42#include "isisd/isis_lsp.h"
43#include "isisd/isis_constants.h"
44#include "isisd/isis_adjacency.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070045#include "isisd/isis_dynhn.h"
jardineb5d44e2003-12-23 08:09:43 +000046
hasso73d1aea2004-09-24 10:45:28 +000047/* staticly assigned vars for printing purposes */
48struct in_addr new_prefix;
49/* len of xxxx.xxxx.xxxx + place for #0 termination */
50char sysid[15];
51/* len of xxxx.xxxx.xxxx + place for #0 termination */
52char snpa[15];
53/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
54char isonet[51];
55/* + place for #0 termination */
56/* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
57char lspid[21];
58/* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
59char datestring[20];
60char nlpidstring[30];
61
jardineb5d44e2003-12-23 08:09:43 +000062/*
63 * This converts the isonet to its printable format
64 */
hasso1cd80842004-10-07 20:07:40 +000065const char *
hassof390d2c2004-09-10 20:48:21 +000066isonet_print (u_char * from, int len)
67{
jardineb5d44e2003-12-23 08:09:43 +000068 int i = 0;
69 char *pos = isonet;
70
hassof390d2c2004-09-10 20:48:21 +000071 if (!from)
jardineb5d44e2003-12-23 08:09:43 +000072 return "unknown";
73
hassof390d2c2004-09-10 20:48:21 +000074 while (i < len)
75 {
76 if (i & 1)
77 {
78 sprintf (pos, "%02x", *(from + i));
79 pos += 2;
80 }
81 else
82 {
83 if (i == (len - 1))
84 { /* No dot at the end of address */
85 sprintf (pos, "%02x", *(from + i));
86 pos += 2;
87 }
88 else
89 {
90 sprintf (pos, "%02x.", *(from + i));
91 pos += 3;
92 }
93 }
94 i++;
jardineb5d44e2003-12-23 08:09:43 +000095 }
jardineb5d44e2003-12-23 08:09:43 +000096 *(pos) = '\0';
97 return isonet;
98}
99
100/*
101 * Returns 0 on error, length of buff on ok
102 * extract dot from the dotted str, and insert all the number in a buff
103 */
104int
Josh Bailey3f045a02012-03-24 08:35:20 -0700105dotformat2buff (u_char * buff, const char * dotted)
jardineb5d44e2003-12-23 08:09:43 +0000106{
107 int dotlen, len = 0;
Josh Bailey3f045a02012-03-24 08:35:20 -0700108 const char *pos = dotted;
jardineb5d44e2003-12-23 08:09:43 +0000109 u_char number[3];
110 int nextdotpos = 2;
111
112 number[2] = '\0';
Paul Jakma41b36e92006-12-08 01:09:50 +0000113 dotlen = strlen(dotted);
hassof390d2c2004-09-10 20:48:21 +0000114 if (dotlen > 50)
115 {
116 /* this can't be an iso net, its too long */
117 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000118 }
119
hassof390d2c2004-09-10 20:48:21 +0000120 while ((pos - dotted) < dotlen && len < 20)
121 {
122 if (*pos == '.')
123 {
124 /* we expect the . at 2, and than every 5 */
125 if ((pos - dotted) != nextdotpos)
126 {
127 len = 0;
128 break;
129 }
130 nextdotpos += 5;
131 pos++;
132 continue;
133 }
134 /* we must have at least two chars left here */
135 if (dotlen - (pos - dotted) < 2)
136 {
137 len = 0;
138 break;
139 }
140
141 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
142 {
143 memcpy (number, pos, 2);
144 pos += 2;
145 }
146 else
147 {
148 len = 0;
149 break;
150 }
151
hassof7c43dc2004-09-26 16:24:14 +0000152 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
hassof390d2c2004-09-10 20:48:21 +0000153 len++;
jardineb5d44e2003-12-23 08:09:43 +0000154 }
155
jardineb5d44e2003-12-23 08:09:43 +0000156 return len;
157}
hassof390d2c2004-09-10 20:48:21 +0000158
jardineb5d44e2003-12-23 08:09:43 +0000159/*
160 * conversion of XXXX.XXXX.XXXX to memory
161 */
162int
Josh Bailey3f045a02012-03-24 08:35:20 -0700163sysid2buff (u_char * buff, const char * dotted)
hassof390d2c2004-09-10 20:48:21 +0000164{
jardineb5d44e2003-12-23 08:09:43 +0000165 int len = 0;
Josh Bailey3f045a02012-03-24 08:35:20 -0700166 const char *pos = dotted;
jardineb5d44e2003-12-23 08:09:43 +0000167 u_char number[3];
168
169 number[2] = '\0';
170 // surely not a sysid_string if not 14 length
Paul Jakma41b36e92006-12-08 01:09:50 +0000171 if (strlen (dotted) != 14)
hassof390d2c2004-09-10 20:48:21 +0000172 {
173 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000174 }
175
hassof390d2c2004-09-10 20:48:21 +0000176 while (len < ISIS_SYS_ID_LEN)
177 {
178 if (*pos == '.')
179 {
180 /* the . is not positioned correctly */
181 if (((pos - dotted) != 4) && ((pos - dotted) != 9))
182 {
183 len = 0;
184 break;
185 }
186 pos++;
187 continue;
188 }
189 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
190 {
191 memcpy (number, pos, 2);
192 pos += 2;
193 }
194 else
195 {
196 len = 0;
197 break;
198 }
199
hassof7c43dc2004-09-26 16:24:14 +0000200 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
hassof390d2c2004-09-10 20:48:21 +0000201 len++;
202 }
jardineb5d44e2003-12-23 08:09:43 +0000203
204 return len;
205
206}
207
208/*
209 * converts the nlpids struct (filled by TLV #129)
210 * into a string
211 */
212
213char *
hassof390d2c2004-09-10 20:48:21 +0000214nlpid2string (struct nlpids *nlpids)
215{
jardineb5d44e2003-12-23 08:09:43 +0000216 char *pos = nlpidstring;
217 int i;
218
hassof390d2c2004-09-10 20:48:21 +0000219 for (i = 0; i < nlpids->count; i++)
220 {
221 switch (nlpids->nlpids[i])
222 {
223 case NLPID_IP:
224 pos += sprintf (pos, "IPv4");
225 break;
226 case NLPID_IPV6:
227 pos += sprintf (pos, "IPv6");
228 break;
229 case NLPID_SNAP:
230 pos += sprintf (pos, "SNAP");
231 break;
232 case NLPID_CLNP:
233 pos += sprintf (pos, "CLNP");
234 break;
235 case NLPID_ESIS:
236 pos += sprintf (pos, "ES-IS");
237 break;
238 default:
239 pos += sprintf (pos, "unknown");
240 break;
241 }
242 if (nlpids->count - i > 1)
243 pos += sprintf (pos, ", ");
244
jardineb5d44e2003-12-23 08:09:43 +0000245 }
jardineb5d44e2003-12-23 08:09:43 +0000246
247 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000248
jardineb5d44e2003-12-23 08:09:43 +0000249 return nlpidstring;
250}
251
252/*
253 * supports the given af ?
254 */
hassof390d2c2004-09-10 20:48:21 +0000255int
jardineb5d44e2003-12-23 08:09:43 +0000256speaks (struct nlpids *nlpids, int family)
257{
258 int i, speaks = 0;
hassof390d2c2004-09-10 20:48:21 +0000259
260 if (nlpids == (struct nlpids *) NULL)
jardineb5d44e2003-12-23 08:09:43 +0000261 return speaks;
hassof390d2c2004-09-10 20:48:21 +0000262 for (i = 0; i < nlpids->count; i++)
263 {
264 if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
265 speaks = 1;
266 if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
267 speaks = 1;
268 }
jardineb5d44e2003-12-23 08:09:43 +0000269
270 return speaks;
271}
272
jardineb5d44e2003-12-23 08:09:43 +0000273/*
274 * Returns 0 on error, IS-IS Circuit Type on ok
275 */
hassof390d2c2004-09-10 20:48:21 +0000276int
Josh Bailey3f045a02012-03-24 08:35:20 -0700277string2circuit_t (const char * str)
jardineb5d44e2003-12-23 08:09:43 +0000278{
hassof390d2c2004-09-10 20:48:21 +0000279
jardineb5d44e2003-12-23 08:09:43 +0000280 if (!str)
281 return 0;
hassof390d2c2004-09-10 20:48:21 +0000282
Paul Jakma41b36e92006-12-08 01:09:50 +0000283 if (!strcmp (str, "level-1"))
jardineb5d44e2003-12-23 08:09:43 +0000284 return IS_LEVEL_1;
285
Paul Jakma41b36e92006-12-08 01:09:50 +0000286 if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
jardineb5d44e2003-12-23 08:09:43 +0000287 return IS_LEVEL_2;
hassof390d2c2004-09-10 20:48:21 +0000288
Paul Jakma41b36e92006-12-08 01:09:50 +0000289 if (!strcmp (str, "level-1-2"))
jardineb5d44e2003-12-23 08:09:43 +0000290 return IS_LEVEL_1_AND_2;
291
292 return 0;
293}
294
295const char *
Josh Bailey3f045a02012-03-24 08:35:20 -0700296circuit_state2string (int state)
297{
298
299 switch (state)
300 {
301 case C_STATE_INIT:
302 return "Init";
303 case C_STATE_CONF:
304 return "Config";
305 case C_STATE_UP:
306 return "Up";
307 default:
308 return "Unknown";
309 }
310 return NULL;
311}
312
313const char *
314circuit_type2string (int type)
315{
316
317 switch (type)
318 {
319 case CIRCUIT_T_P2P:
320 return "p2p";
321 case CIRCUIT_T_BROADCAST:
322 return "lan";
323 case CIRCUIT_T_LOOPBACK:
324 return "loopback";
325 default:
326 return "Unknown";
327 }
328 return NULL;
329}
330
331const char *
jardineb5d44e2003-12-23 08:09:43 +0000332circuit_t2string (int circuit_t)
333{
hassof390d2c2004-09-10 20:48:21 +0000334 switch (circuit_t)
335 {
336 case IS_LEVEL_1:
337 return "L1";
338 case IS_LEVEL_2:
339 return "L2";
340 case IS_LEVEL_1_AND_2:
341 return "L1L2";
342 default:
343 return "??";
344 }
jardineb5d44e2003-12-23 08:09:43 +0000345
hassof390d2c2004-09-10 20:48:21 +0000346 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000347}
348
349const char *
350syst2string (int type)
351{
hassof390d2c2004-09-10 20:48:21 +0000352 switch (type)
353 {
354 case ISIS_SYSTYPE_ES:
355 return "ES";
356 case ISIS_SYSTYPE_IS:
357 return "IS";
358 case ISIS_SYSTYPE_L1_IS:
359 return "1";
360 case ISIS_SYSTYPE_L2_IS:
361 return "2";
362 default:
363 return "??";
364 }
jardineb5d44e2003-12-23 08:09:43 +0000365
hassof390d2c2004-09-10 20:48:21 +0000366 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000367}
368
369/*
370 * Print functions - we print to static vars
371 */
hasso1cd80842004-10-07 20:07:40 +0000372const char *
hassof390d2c2004-09-10 20:48:21 +0000373snpa_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000374{
375 int i = 0;
hassof7c43dc2004-09-26 16:24:14 +0000376 u_char *pos = (u_char *)snpa;
jardineb5d44e2003-12-23 08:09:43 +0000377
hassof390d2c2004-09-10 20:48:21 +0000378 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000379 return "unknown";
jardineb5d44e2003-12-23 08:09:43 +0000380
hassof390d2c2004-09-10 20:48:21 +0000381 while (i < ETH_ALEN - 1)
382 {
383 if (i & 1)
384 {
hassof7c43dc2004-09-26 16:24:14 +0000385 sprintf ((char *)pos, "%02x.", *(from + i));
hassof390d2c2004-09-10 20:48:21 +0000386 pos += 3;
387 }
388 else
389 {
hassof7c43dc2004-09-26 16:24:14 +0000390 sprintf ((char *)pos, "%02x", *(from + i));
hassof390d2c2004-09-10 20:48:21 +0000391 pos += 2;
392
393 }
394 i++;
jardineb5d44e2003-12-23 08:09:43 +0000395 }
jardineb5d44e2003-12-23 08:09:43 +0000396
hassof7c43dc2004-09-26 16:24:14 +0000397 sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
jardineb5d44e2003-12-23 08:09:43 +0000398 pos += 2;
399 *(pos) = '\0';
400
401 return snpa;
402}
403
hasso1cd80842004-10-07 20:07:40 +0000404const char *
hassof390d2c2004-09-10 20:48:21 +0000405sysid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000406{
407 int i = 0;
408 char *pos = sysid;
409
hassof390d2c2004-09-10 20:48:21 +0000410 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000411 return "unknown";
412
hassof390d2c2004-09-10 20:48:21 +0000413 while (i < ISIS_SYS_ID_LEN - 1)
414 {
415 if (i & 1)
416 {
417 sprintf (pos, "%02x.", *(from + i));
418 pos += 3;
419 }
420 else
421 {
422 sprintf (pos, "%02x", *(from + i));
423 pos += 2;
424
425 }
426 i++;
427 }
jardineb5d44e2003-12-23 08:09:43 +0000428
429 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
430 pos += 2;
431 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000432
jardineb5d44e2003-12-23 08:09:43 +0000433 return sysid;
434}
435
hasso1cd80842004-10-07 20:07:40 +0000436const char *
hassof390d2c2004-09-10 20:48:21 +0000437rawlspid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000438{
439 char *pos = lspid;
hassof390d2c2004-09-10 20:48:21 +0000440 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000441 return "unknown";
hassof390d2c2004-09-10 20:48:21 +0000442 memcpy (pos, sysid_print (from), 15);
jardineb5d44e2003-12-23 08:09:43 +0000443 pos += 14;
hassof390d2c2004-09-10 20:48:21 +0000444 sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
jardineb5d44e2003-12-23 08:09:43 +0000445 pos += 3;
hassof390d2c2004-09-10 20:48:21 +0000446 sprintf (pos, "-%02x", LSP_FRAGMENT (from));
jardineb5d44e2003-12-23 08:09:43 +0000447 pos += 3;
448
449 *(pos) = '\0';
450
451 return lspid;
452}
453
hasso1cd80842004-10-07 20:07:40 +0000454const char *
hassof390d2c2004-09-10 20:48:21 +0000455time2string (u_int32_t time)
456{
457 char *pos = datestring;
jardineb5d44e2003-12-23 08:09:43 +0000458 u_int32_t rest;
459
hassof390d2c2004-09-10 20:48:21 +0000460 if (time == 0)
jardineb5d44e2003-12-23 08:09:43 +0000461 return "-";
462
hassof390d2c2004-09-10 20:48:21 +0000463 if (time / SECS_PER_YEAR)
464 pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
465 rest = time % SECS_PER_YEAR;
466 if (rest / SECS_PER_MONTH)
467 pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
468 rest = rest % SECS_PER_MONTH;
469 if (rest / SECS_PER_WEEK)
470 pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
471 rest = rest % SECS_PER_WEEK;
472 if (rest / SECS_PER_DAY)
473 pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
474 rest = rest % SECS_PER_DAY;
475 if (rest / SECS_PER_HOUR)
476 pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
477 rest = rest % SECS_PER_HOUR;
478 if (rest / SECS_PER_MINUTE)
479 pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
480 rest = rest % SECS_PER_MINUTE;
481 if (rest)
482 pos += sprintf (pos, "%us", rest);
483
jardineb5d44e2003-12-23 08:09:43 +0000484 *(pos) = 0;
485
486 return datestring;
487}
488
489/*
490 * routine to decrement a timer by a random
491 * number
492 *
493 * first argument is the timer and the second is
494 * the jitter
495 */
hassof390d2c2004-09-10 20:48:21 +0000496unsigned long
jardineb5d44e2003-12-23 08:09:43 +0000497isis_jitter (unsigned long timer, unsigned long jitter)
498{
hassof390d2c2004-09-10 20:48:21 +0000499 int j, k;
jardineb5d44e2003-12-23 08:09:43 +0000500
hassof390d2c2004-09-10 20:48:21 +0000501 if (jitter >= 100)
jardineb5d44e2003-12-23 08:09:43 +0000502 return timer;
503
504 if (timer == 1)
505 return timer;
506 /*
507 * randomizing just the percent value provides
508 * no good random numbers - hence the spread
509 * to RANDOM_SPREAD (100000), which is ok as
510 * most IS-IS timers are no longer than 16 bit
511 */
512
hassof390d2c2004-09-10 20:48:21 +0000513 j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
jardineb5d44e2003-12-23 08:09:43 +0000514
hassof390d2c2004-09-10 20:48:21 +0000515 k = timer - (timer * (100 - jitter)) / 100;
jardineb5d44e2003-12-23 08:09:43 +0000516
517 timer = timer - (k * j / RANDOM_SPREAD);
518
519 return timer;
520}
521
522struct in_addr
hassof390d2c2004-09-10 20:48:21 +0000523newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
jardineb5d44e2003-12-23 08:09:43 +0000524{
hassof390d2c2004-09-10 20:48:21 +0000525 memset (&new_prefix, 0, sizeof (new_prefix));
526 memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
527 ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
jardineb5d44e2003-12-23 08:09:43 +0000528 return new_prefix;
529}
530
jardin9e867fe2003-12-23 08:56:18 +0000531/*
532 * Returns host.name if any, otherwise
533 * it returns the system hostname.
534 */
535const char *
hassof390d2c2004-09-10 20:48:21 +0000536unix_hostname (void)
jardin9e867fe2003-12-23 08:56:18 +0000537{
538 static struct utsname names;
539 const char *hostname;
jardineb5d44e2003-12-23 08:09:43 +0000540
jardin9e867fe2003-12-23 08:56:18 +0000541 hostname = host.name;
hassof390d2c2004-09-10 20:48:21 +0000542 if (!hostname)
543 {
544 uname (&names);
545 hostname = names.nodename;
546 }
jardineb5d44e2003-12-23 08:09:43 +0000547
jardin9e867fe2003-12-23 08:56:18 +0000548 return hostname;
549}
Josh Bailey3f045a02012-03-24 08:35:20 -0700550
551/*
552 * Returns the dynamic hostname associated with the passed system ID.
553 * If no dynamic hostname found then returns formatted system ID.
554 */
555const char *
556print_sys_hostname (u_char *sysid)
557{
558 struct isis_dynhn *dyn;
559
560 if (!sysid)
561 return "nullsysid";
562
563 /* For our system ID return our host name */
564 if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
565 return unix_hostname();
566
567 dyn = dynhn_find_by_id (sysid);
568 if (dyn)
569 return (const char *)dyn->name.name;
570
571 return sysid_print (sysid);
572}
573
574/*
575 * This function is a generic utility that logs data of given length.
576 * Move this to a shared lib so that any protocol can use it.
577 */
578void
579zlog_dump_data (void *data, int len)
580{
581 int i;
582 unsigned char *p;
583 unsigned char c;
584 char bytestr[4];
585 char addrstr[10];
586 char hexstr[ 16*3 + 5];
587 char charstr[16*1 + 5];
588
589 p = data;
590 memset (bytestr, 0, sizeof(bytestr));
591 memset (addrstr, 0, sizeof(addrstr));
592 memset (hexstr, 0, sizeof(hexstr));
593 memset (charstr, 0, sizeof(charstr));
594
595 for (i = 1; i <= len; i++)
596 {
597 c = *p;
598 if (isalnum (c) == 0)
599 c = '.';
600
601 /* store address for this line */
602 if ((i % 16) == 1)
603 snprintf (addrstr, sizeof(addrstr), "%p", p);
604
605 /* store hex str (for left side) */
606 snprintf (bytestr, sizeof (bytestr), "%02X ", *p);
607 strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1);
608
609 /* store char str (for right side) */
610 snprintf (bytestr, sizeof (bytestr), "%c", c);
611 strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1);
612
613 if ((i % 16) == 0)
614 {
615 /* line completed */
616 zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
617 hexstr[0] = 0;
618 charstr[0] = 0;
619 }
620 else if ((i % 8) == 0)
621 {
622 /* half line: add whitespaces */
623 strncat (hexstr, " ", sizeof (hexstr) - strlen (hexstr) - 1);
624 strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1);
625 }
626 p++; /* next byte */
627 }
628
629 /* print rest of buffer if not empty */
630 if (strlen (hexstr) > 0)
631 zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
632 return;
633}