isis_misc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  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. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. #include <zebra.h>
  23. #include "stream.h"
  24. #include "vty.h"
  25. #include "hash.h"
  26. #include "if.h"
  27. #include "command.h"
  28. #include "isisd/dict.h"
  29. #include "isisd/isis_constants.h"
  30. #include "isisd/isis_common.h"
  31. #include "isisd/isis_flags.h"
  32. #include "isisd/isis_circuit.h"
  33. #include "isisd/isis_csm.h"
  34. #include "isisd/isisd.h"
  35. #include "isisd/isis_misc.h"
  36. #include "isisd/isis_tlv.h"
  37. #include "isisd/isis_lsp.h"
  38. #include "isisd/isis_constants.h"
  39. #include "isisd/isis_adjacency.h"
  40. #include "isisd/isis_dynhn.h"
  41. /* staticly assigned vars for printing purposes */
  42. struct in_addr new_prefix;
  43. /* len of xxxx.xxxx.xxxx + place for #0 termination */
  44. char sysid[15];
  45. /* len of xxxx.xxxx.xxxx + place for #0 termination */
  46. char snpa[15];
  47. /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
  48. char isonet[51];
  49. /* + place for #0 termination */
  50. /* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
  51. char lspid[21];
  52. /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
  53. char datestring[20];
  54. char nlpidstring[30];
  55. /*
  56. * This converts the isonet to its printable format
  57. */
  58. const char *
  59. isonet_print (const u_char * from, int len)
  60. {
  61. int i = 0;
  62. char *pos = isonet;
  63. if (!from)
  64. return "unknown";
  65. while (i < len)
  66. {
  67. if (i & 1)
  68. {
  69. sprintf (pos, "%02x", *(from + i));
  70. pos += 2;
  71. }
  72. else
  73. {
  74. if (i == (len - 1))
  75. { /* No dot at the end of address */
  76. sprintf (pos, "%02x", *(from + i));
  77. pos += 2;
  78. }
  79. else
  80. {
  81. sprintf (pos, "%02x.", *(from + i));
  82. pos += 3;
  83. }
  84. }
  85. i++;
  86. }
  87. *(pos) = '\0';
  88. return isonet;
  89. }
  90. /*
  91. * Returns 0 on error, length of buff on ok
  92. * extract dot from the dotted str, and insert all the number in a buff
  93. */
  94. int
  95. dotformat2buff (u_char * buff, const char * dotted)
  96. {
  97. int dotlen, len = 0;
  98. const char *pos = dotted;
  99. u_char number[3];
  100. int nextdotpos = 2;
  101. number[2] = '\0';
  102. dotlen = strlen(dotted);
  103. if (dotlen > 50)
  104. {
  105. /* this can't be an iso net, its too long */
  106. return 0;
  107. }
  108. while ((pos - dotted) < dotlen && len < 20)
  109. {
  110. if (*pos == '.')
  111. {
  112. /* we expect the . at 2, and than every 5 */
  113. if ((pos - dotted) != nextdotpos)
  114. {
  115. len = 0;
  116. break;
  117. }
  118. nextdotpos += 5;
  119. pos++;
  120. continue;
  121. }
  122. /* we must have at least two chars left here */
  123. if (dotlen - (pos - dotted) < 2)
  124. {
  125. len = 0;
  126. break;
  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. *(buff + len) = (char) strtol ((char *)number, NULL, 16);
  139. len++;
  140. }
  141. return len;
  142. }
  143. /*
  144. * conversion of XXXX.XXXX.XXXX to memory
  145. */
  146. int
  147. sysid2buff (u_char * buff, const char * dotted)
  148. {
  149. int len = 0;
  150. const char *pos = dotted;
  151. u_char number[3];
  152. number[2] = '\0';
  153. // surely not a sysid_string if not 14 length
  154. if (strlen (dotted) != 14)
  155. {
  156. return 0;
  157. }
  158. while (len < ISIS_SYS_ID_LEN)
  159. {
  160. if (*pos == '.')
  161. {
  162. /* the . is not positioned correctly */
  163. if (((pos - dotted) != 4) && ((pos - dotted) != 9))
  164. {
  165. len = 0;
  166. break;
  167. }
  168. pos++;
  169. continue;
  170. }
  171. if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
  172. {
  173. memcpy (number, pos, 2);
  174. pos += 2;
  175. }
  176. else
  177. {
  178. len = 0;
  179. break;
  180. }
  181. *(buff + len) = (char) strtol ((char *)number, NULL, 16);
  182. len++;
  183. }
  184. return len;
  185. }
  186. /*
  187. * converts the nlpids struct (filled by TLV #129)
  188. * into a string
  189. */
  190. char *
  191. nlpid2string (struct nlpids *nlpids)
  192. {
  193. char *pos = nlpidstring;
  194. int i;
  195. for (i = 0; i < nlpids->count; i++)
  196. {
  197. switch (nlpids->nlpids[i])
  198. {
  199. case NLPID_IP:
  200. pos += sprintf (pos, "IPv4");
  201. break;
  202. case NLPID_IPV6:
  203. pos += sprintf (pos, "IPv6");
  204. break;
  205. case NLPID_SNAP:
  206. pos += sprintf (pos, "SNAP");
  207. break;
  208. case NLPID_CLNP:
  209. pos += sprintf (pos, "CLNP");
  210. break;
  211. case NLPID_ESIS:
  212. pos += sprintf (pos, "ES-IS");
  213. break;
  214. default:
  215. pos += sprintf (pos, "unknown");
  216. break;
  217. }
  218. if (nlpids->count - i > 1)
  219. pos += sprintf (pos, ", ");
  220. }
  221. *(pos) = '\0';
  222. return nlpidstring;
  223. }
  224. /*
  225. * supports the given af ?
  226. */
  227. int
  228. speaks (struct nlpids *nlpids, int family)
  229. {
  230. int i, speaks = 0;
  231. if (nlpids == (struct nlpids *) NULL)
  232. return speaks;
  233. for (i = 0; i < nlpids->count; i++)
  234. {
  235. if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
  236. speaks = 1;
  237. if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
  238. speaks = 1;
  239. }
  240. return speaks;
  241. }
  242. /*
  243. * Returns 0 on error, IS-IS Circuit Type on ok
  244. */
  245. int
  246. string2circuit_t (const char * str)
  247. {
  248. if (!str)
  249. return 0;
  250. if (!strcmp (str, "level-1"))
  251. return IS_LEVEL_1;
  252. if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
  253. return IS_LEVEL_2;
  254. if (!strcmp (str, "level-1-2"))
  255. return IS_LEVEL_1_AND_2;
  256. return 0;
  257. }
  258. const char *
  259. circuit_state2string (int state)
  260. {
  261. switch (state)
  262. {
  263. case C_STATE_INIT:
  264. return "Init";
  265. case C_STATE_CONF:
  266. return "Config";
  267. case C_STATE_UP:
  268. return "Up";
  269. default:
  270. return "Unknown";
  271. }
  272. return NULL;
  273. }
  274. const char *
  275. circuit_type2string (int type)
  276. {
  277. switch (type)
  278. {
  279. case CIRCUIT_T_P2P:
  280. return "p2p";
  281. case CIRCUIT_T_BROADCAST:
  282. return "lan";
  283. case CIRCUIT_T_LOOPBACK:
  284. return "loopback";
  285. default:
  286. return "Unknown";
  287. }
  288. return NULL;
  289. }
  290. const char *
  291. circuit_t2string (int circuit_t)
  292. {
  293. switch (circuit_t)
  294. {
  295. case IS_LEVEL_1:
  296. return "L1";
  297. case IS_LEVEL_2:
  298. return "L2";
  299. case IS_LEVEL_1_AND_2:
  300. return "L1L2";
  301. default:
  302. return "??";
  303. }
  304. return NULL; /* not reached */
  305. }
  306. const char *
  307. syst2string (int type)
  308. {
  309. switch (type)
  310. {
  311. case ISIS_SYSTYPE_ES:
  312. return "ES";
  313. case ISIS_SYSTYPE_IS:
  314. return "IS";
  315. case ISIS_SYSTYPE_L1_IS:
  316. return "1";
  317. case ISIS_SYSTYPE_L2_IS:
  318. return "2";
  319. default:
  320. return "??";
  321. }
  322. return NULL; /* not reached */
  323. }
  324. /*
  325. * Print functions - we print to static vars
  326. */
  327. const char *
  328. snpa_print (const u_char * from)
  329. {
  330. int i = 0;
  331. u_char *pos = (u_char *)snpa;
  332. if (!from)
  333. return "unknown";
  334. while (i < ETH_ALEN - 1)
  335. {
  336. if (i & 1)
  337. {
  338. sprintf ((char *)pos, "%02x.", *(from + i));
  339. pos += 3;
  340. }
  341. else
  342. {
  343. sprintf ((char *)pos, "%02x", *(from + i));
  344. pos += 2;
  345. }
  346. i++;
  347. }
  348. sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
  349. pos += 2;
  350. *(pos) = '\0';
  351. return snpa;
  352. }
  353. const char *
  354. sysid_print (const u_char * from)
  355. {
  356. int i = 0;
  357. char *pos = sysid;
  358. if (!from)
  359. return "unknown";
  360. while (i < ISIS_SYS_ID_LEN - 1)
  361. {
  362. if (i & 1)
  363. {
  364. sprintf (pos, "%02x.", *(from + i));
  365. pos += 3;
  366. }
  367. else
  368. {
  369. sprintf (pos, "%02x", *(from + i));
  370. pos += 2;
  371. }
  372. i++;
  373. }
  374. sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
  375. pos += 2;
  376. *(pos) = '\0';
  377. return sysid;
  378. }
  379. const char *
  380. rawlspid_print (const u_char * from)
  381. {
  382. char *pos = lspid;
  383. if (!from)
  384. return "unknown";
  385. memcpy (pos, sysid_print (from), 15);
  386. pos += 14;
  387. sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
  388. pos += 3;
  389. sprintf (pos, "-%02x", LSP_FRAGMENT (from));
  390. pos += 3;
  391. *(pos) = '\0';
  392. return lspid;
  393. }
  394. const char *
  395. time2string (u_int32_t time)
  396. {
  397. char *pos = datestring;
  398. u_int32_t rest;
  399. if (time == 0)
  400. return "-";
  401. if (time / SECS_PER_YEAR)
  402. pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
  403. rest = time % SECS_PER_YEAR;
  404. if (rest / SECS_PER_MONTH)
  405. pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
  406. rest = rest % SECS_PER_MONTH;
  407. if (rest / SECS_PER_WEEK)
  408. pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
  409. rest = rest % SECS_PER_WEEK;
  410. if (rest / SECS_PER_DAY)
  411. pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
  412. rest = rest % SECS_PER_DAY;
  413. if (rest / SECS_PER_HOUR)
  414. pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
  415. rest = rest % SECS_PER_HOUR;
  416. if (rest / SECS_PER_MINUTE)
  417. pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
  418. rest = rest % SECS_PER_MINUTE;
  419. if (rest)
  420. pos += sprintf (pos, "%us", rest);
  421. *(pos) = 0;
  422. return datestring;
  423. }
  424. /*
  425. * routine to decrement a timer by a random
  426. * number
  427. *
  428. * first argument is the timer and the second is
  429. * the jitter
  430. */
  431. unsigned long
  432. isis_jitter (unsigned long timer, unsigned long jitter)
  433. {
  434. int j, k;
  435. if (jitter >= 100)
  436. return timer;
  437. if (timer == 1)
  438. return timer;
  439. /*
  440. * randomizing just the percent value provides
  441. * no good random numbers - hence the spread
  442. * to RANDOM_SPREAD (100000), which is ok as
  443. * most IS-IS timers are no longer than 16 bit
  444. */
  445. j = 1 + (int) ((RANDOM_SPREAD * random ()) / (RAND_MAX + 1.0));
  446. k = timer - (timer * (100 - jitter)) / 100;
  447. timer = timer - (k * j / RANDOM_SPREAD);
  448. return timer;
  449. }
  450. struct in_addr
  451. newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
  452. {
  453. memset (&new_prefix, 0, sizeof (new_prefix));
  454. memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
  455. ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
  456. return new_prefix;
  457. }
  458. /*
  459. * Returns host.name if any, otherwise
  460. * it returns the system hostname.
  461. */
  462. const char *
  463. unix_hostname (void)
  464. {
  465. static struct utsname names;
  466. const char *hostname;
  467. hostname = host.name;
  468. if (!hostname)
  469. {
  470. uname (&names);
  471. hostname = names.nodename;
  472. }
  473. return hostname;
  474. }
  475. /*
  476. * Returns the dynamic hostname associated with the passed system ID.
  477. * If no dynamic hostname found then returns formatted system ID.
  478. */
  479. const char *
  480. print_sys_hostname (const u_char *sysid)
  481. {
  482. struct isis_dynhn *dyn;
  483. if (!sysid)
  484. return "nullsysid";
  485. /* For our system ID return our host name */
  486. if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
  487. return unix_hostname();
  488. dyn = dynhn_find_by_id (sysid);
  489. if (dyn)
  490. return (const char *)dyn->name.name;
  491. return sysid_print (sysid);
  492. }
  493. /*
  494. * This function is a generic utility that logs data of given length.
  495. * Move this to a shared lib so that any protocol can use it.
  496. */
  497. void
  498. zlog_dump_data (void *data, int len)
  499. {
  500. int i;
  501. unsigned char *p;
  502. unsigned char c;
  503. char bytestr[4];
  504. char addrstr[10];
  505. char hexstr[ 16*3 + 5];
  506. char charstr[16*1 + 5];
  507. p = data;
  508. memset (bytestr, 0, sizeof(bytestr));
  509. memset (addrstr, 0, sizeof(addrstr));
  510. memset (hexstr, 0, sizeof(hexstr));
  511. memset (charstr, 0, sizeof(charstr));
  512. for (i = 1; i <= len; i++)
  513. {
  514. c = *p;
  515. if (isalnum (c) == 0)
  516. c = '.';
  517. /* store address for this line */
  518. if ((i % 16) == 1)
  519. snprintf (addrstr, sizeof(addrstr), "%p", p);
  520. /* store hex str (for left side) */
  521. snprintf (bytestr, sizeof (bytestr), "%02X ", *p);
  522. strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1);
  523. /* store char str (for right side) */
  524. snprintf (bytestr, sizeof (bytestr), "%c", c);
  525. strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1);
  526. if ((i % 16) == 0)
  527. {
  528. /* line completed */
  529. zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
  530. hexstr[0] = 0;
  531. charstr[0] = 0;
  532. }
  533. else if ((i % 8) == 0)
  534. {
  535. /* half line: add whitespaces */
  536. strncat (hexstr, " ", sizeof (hexstr) - strlen (hexstr) - 1);
  537. strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1);
  538. }
  539. p++; /* next byte */
  540. }
  541. /* print rest of buffer if not empty */
  542. if (strlen (hexstr) > 0)
  543. zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
  544. return;
  545. }