isis_tlv.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197
  1. /*
  2. * IS-IS Rout(e)ing protocol - isis_tlv.c
  3. * IS-IS TLV related 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 "log.h"
  24. #include "linklist.h"
  25. #include "stream.h"
  26. #include "memory.h"
  27. #include "prefix.h"
  28. #include "vty.h"
  29. #include "if.h"
  30. #include "isisd/dict.h"
  31. #include "isisd/isis_constants.h"
  32. #include "isisd/isis_common.h"
  33. #include "isisd/isis_flags.h"
  34. #include "isisd/isis_circuit.h"
  35. #include "isisd/isis_tlv.h"
  36. #include "isisd/isisd.h"
  37. #include "isisd/isis_dynhn.h"
  38. #include "isisd/isis_misc.h"
  39. #include "isisd/isis_pdu.h"
  40. #include "isisd/isis_lsp.h"
  41. #include "isisd/isis_te.h"
  42. void
  43. free_tlv (void *val)
  44. {
  45. XFREE (MTYPE_ISIS_TLV, val);
  46. return;
  47. }
  48. /*
  49. * Called after parsing of a PDU. There shouldn't be any tlv's left, so this
  50. * is only a caution to avoid memory leaks
  51. */
  52. void
  53. free_tlvs (struct tlvs *tlvs)
  54. {
  55. if (tlvs->area_addrs)
  56. list_delete (tlvs->area_addrs);
  57. if (tlvs->is_neighs)
  58. list_delete (tlvs->is_neighs);
  59. if (tlvs->te_is_neighs)
  60. list_delete (tlvs->te_is_neighs);
  61. if (tlvs->es_neighs)
  62. list_delete (tlvs->es_neighs);
  63. if (tlvs->lsp_entries)
  64. list_delete (tlvs->lsp_entries);
  65. if (tlvs->prefix_neighs)
  66. list_delete (tlvs->prefix_neighs);
  67. if (tlvs->lan_neighs)
  68. list_delete (tlvs->lan_neighs);
  69. if (tlvs->ipv4_addrs)
  70. list_delete (tlvs->ipv4_addrs);
  71. if (tlvs->ipv4_int_reachs)
  72. list_delete (tlvs->ipv4_int_reachs);
  73. if (tlvs->ipv4_ext_reachs)
  74. list_delete (tlvs->ipv4_ext_reachs);
  75. if (tlvs->te_ipv4_reachs)
  76. list_delete (tlvs->te_ipv4_reachs);
  77. #ifdef HAVE_IPV6
  78. if (tlvs->ipv6_addrs)
  79. list_delete (tlvs->ipv6_addrs);
  80. if (tlvs->ipv6_reachs)
  81. list_delete (tlvs->ipv6_reachs);
  82. #endif /* HAVE_IPV6 */
  83. memset (tlvs, 0, sizeof (struct tlvs));
  84. return;
  85. }
  86. /*
  87. * Parses the tlvs found in the variant length part of the PDU.
  88. * Caller tells with flags in "expected" which TLV's it is interested in.
  89. */
  90. int
  91. parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
  92. u_int32_t * found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset)
  93. {
  94. u_char type, length;
  95. struct lan_neigh *lan_nei;
  96. struct area_addr *area_addr;
  97. struct is_neigh *is_nei;
  98. struct te_is_neigh *te_is_nei;
  99. struct es_neigh *es_nei;
  100. struct lsp_entry *lsp_entry;
  101. struct in_addr *ipv4_addr;
  102. struct ipv4_reachability *ipv4_reach;
  103. struct te_ipv4_reachability *te_ipv4_reach;
  104. #ifdef HAVE_IPV6
  105. struct in6_addr *ipv6_addr;
  106. struct ipv6_reachability *ipv6_reach;
  107. int prefix_octets;
  108. #endif /* HAVE_IPV6 */
  109. int value_len, retval = ISIS_OK;
  110. u_char *start = stream, *pnt = stream, *endpnt;
  111. *found = 0;
  112. memset (tlvs, 0, sizeof (struct tlvs));
  113. while (pnt < stream + size - 2)
  114. {
  115. type = *pnt;
  116. length = *(pnt + 1);
  117. pnt += 2;
  118. value_len = 0;
  119. if (pnt + length > stream + size)
  120. {
  121. zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
  122. "boundaries", areatag, type, length);
  123. retval = ISIS_WARNING;
  124. break;
  125. }
  126. switch (type)
  127. {
  128. case AREA_ADDRESSES:
  129. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  130. * | Address Length |
  131. * +-------+-------+-------+-------+-------+-------+-------+-------+
  132. * | Area Address |
  133. * +-------+-------+-------+-------+-------+-------+-------+-------+
  134. * : :
  135. */
  136. *found |= TLVFLAG_AREA_ADDRS;
  137. #ifdef EXTREME_TLV_DEBUG
  138. zlog_debug ("TLV Area Adresses len %d", length);
  139. #endif /* EXTREME_TLV_DEBUG */
  140. if (*expected & TLVFLAG_AREA_ADDRS)
  141. {
  142. while (length > value_len)
  143. {
  144. area_addr = (struct area_addr *) pnt;
  145. value_len += area_addr->addr_len + 1;
  146. pnt += area_addr->addr_len + 1;
  147. if (!tlvs->area_addrs)
  148. tlvs->area_addrs = list_new ();
  149. listnode_add (tlvs->area_addrs, area_addr);
  150. }
  151. }
  152. else
  153. {
  154. pnt += length;
  155. }
  156. break;
  157. case IS_NEIGHBOURS:
  158. *found |= TLVFLAG_IS_NEIGHS;
  159. #ifdef EXTREME_TLV_DEBUG
  160. zlog_debug ("ISIS-TLV (%s): IS Neighbours length %d",
  161. areatag, length);
  162. #endif /* EXTREME_TLV_DEBUG */
  163. if (TLVFLAG_IS_NEIGHS & *expected)
  164. {
  165. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  166. * | Virtual Flag |
  167. * +-------+-------+-------+-------+-------+-------+-------+-------+
  168. */
  169. pnt++;
  170. value_len++;
  171. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  172. * | 0 | I/E | Default Metric |
  173. * +-------+-------+-------+-------+-------+-------+-------+-------+
  174. * | S | I/E | Delay Metric |
  175. * +-------+-------+-------+-------+-------+-------+-------+-------+
  176. * | S | I/E | Expense Metric |
  177. * +-------+-------+-------+-------+-------+-------+-------+-------+
  178. * | S | I/E | Error Metric |
  179. * +-------+-------+-------+-------+-------+-------+-------+-------+
  180. * | Neighbour ID |
  181. * +---------------------------------------------------------------+
  182. * : :
  183. */
  184. while (length > value_len)
  185. {
  186. is_nei = (struct is_neigh *) pnt;
  187. value_len += 4 + ISIS_SYS_ID_LEN + 1;
  188. pnt += 4 + ISIS_SYS_ID_LEN + 1;
  189. if (!tlvs->is_neighs)
  190. tlvs->is_neighs = list_new ();
  191. listnode_add (tlvs->is_neighs, is_nei);
  192. }
  193. }
  194. else
  195. {
  196. pnt += length;
  197. }
  198. break;
  199. case TE_IS_NEIGHBOURS:
  200. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  201. * | Neighbour ID | 7
  202. * +---------------------------------------------------------------+
  203. * | TE Metric | 3
  204. * +---------------------------------------------------------------+
  205. * | SubTLVs Length | 1
  206. * +---------------------------------------------------------------+
  207. * : :
  208. */
  209. *found |= TLVFLAG_TE_IS_NEIGHS;
  210. #ifdef EXTREME_TLV_DEBUG
  211. zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
  212. areatag, length);
  213. #endif /* EXTREME_TLV_DEBUG */
  214. if (TLVFLAG_TE_IS_NEIGHS & *expected)
  215. {
  216. while (length > value_len)
  217. {
  218. te_is_nei = (struct te_is_neigh *) pnt;
  219. value_len += IS_NEIGHBOURS_LEN;
  220. pnt += IS_NEIGHBOURS_LEN;
  221. /* FIXME - subtlvs are handled here, for now we skip */
  222. /* FIXME: All TE SubTLVs are not necessary present in LSP PDU. */
  223. /* So, it must be copied in a new te_is_neigh structure */
  224. /* rather than just initialize pointer to the original LSP PDU */
  225. /* to avoid consider the rest of lspdu as subTLVs or buffer overflow */
  226. if (IS_MPLS_TE(isisMplsTE))
  227. {
  228. struct te_is_neigh *new = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh));
  229. memcpy(new->neigh_id, te_is_nei->neigh_id, ISIS_SYS_ID_LEN + 1);
  230. memcpy(new->te_metric, te_is_nei->te_metric, 3);
  231. new->sub_tlvs_length = te_is_nei->sub_tlvs_length;
  232. memcpy(new->sub_tlvs, pnt, te_is_nei->sub_tlvs_length);
  233. te_is_nei = new;
  234. }
  235. /* Skip SUB TLVs payload */
  236. value_len += te_is_nei->sub_tlvs_length;
  237. pnt += te_is_nei->sub_tlvs_length;
  238. if (!tlvs->te_is_neighs)
  239. tlvs->te_is_neighs = list_new ();
  240. listnode_add (tlvs->te_is_neighs, te_is_nei);
  241. }
  242. }
  243. else
  244. {
  245. pnt += length;
  246. }
  247. break;
  248. case ES_NEIGHBOURS:
  249. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  250. * | 0 | I/E | Default Metric |
  251. * +-------+-------+-------+-------+-------+-------+-------+-------+
  252. * | S | I/E | Delay Metric |
  253. * +-------+-------+-------+-------+-------+-------+-------+-------+
  254. * | S | I/E | Expense Metric |
  255. * +-------+-------+-------+-------+-------+-------+-------+-------+
  256. * | S | I/E | Error Metric |
  257. * +-------+-------+-------+-------+-------+-------+-------+-------+
  258. * | Neighbour ID |
  259. * +---------------------------------------------------------------+
  260. * | Neighbour ID |
  261. * +---------------------------------------------------------------+
  262. * : :
  263. */
  264. #ifdef EXTREME_TLV_DEBUG
  265. zlog_debug ("ISIS-TLV (%s): ES Neighbours length %d",
  266. areatag, length);
  267. #endif /* EXTREME_TLV_DEBUG */
  268. *found |= TLVFLAG_ES_NEIGHS;
  269. if (*expected & TLVFLAG_ES_NEIGHS)
  270. {
  271. es_nei = (struct es_neigh *) pnt;
  272. value_len += 4;
  273. pnt += 4;
  274. while (length > value_len)
  275. {
  276. /* FIXME FIXME FIXME - add to the list */
  277. /* sys_id->id = pnt; */
  278. value_len += ISIS_SYS_ID_LEN;
  279. pnt += ISIS_SYS_ID_LEN;
  280. /* if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid; */
  281. }
  282. if (!tlvs->es_neighs)
  283. tlvs->es_neighs = list_new ();
  284. listnode_add (tlvs->es_neighs, es_nei);
  285. }
  286. else
  287. {
  288. pnt += length;
  289. }
  290. break;
  291. case LAN_NEIGHBOURS:
  292. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  293. * | LAN Address |
  294. * +-------+-------+-------+-------+-------+-------+-------+-------+
  295. * : :
  296. */
  297. *found |= TLVFLAG_LAN_NEIGHS;
  298. #ifdef EXTREME_TLV_DEBUG
  299. zlog_debug ("ISIS-TLV (%s): LAN Neigbours length %d",
  300. areatag, length);
  301. #endif /* EXTREME_TLV_DEBUG */
  302. if (TLVFLAG_LAN_NEIGHS & *expected)
  303. {
  304. while (length > value_len)
  305. {
  306. lan_nei = (struct lan_neigh *) pnt;
  307. if (!tlvs->lan_neighs)
  308. tlvs->lan_neighs = list_new ();
  309. listnode_add (tlvs->lan_neighs, lan_nei);
  310. value_len += ETH_ALEN;
  311. pnt += ETH_ALEN;
  312. }
  313. }
  314. else
  315. {
  316. pnt += length;
  317. }
  318. break;
  319. case PADDING:
  320. #ifdef EXTREME_TLV_DEBUG
  321. zlog_debug ("TLV padding %d", length);
  322. #endif /* EXTREME_TLV_DEBUG */
  323. pnt += length;
  324. break;
  325. case LSP_ENTRIES:
  326. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  327. * | Remaining Lifetime | 2
  328. * +-------+-------+-------+-------+-------+-------+-------+-------+
  329. * | LSP ID | id+2
  330. * +-------+-------+-------+-------+-------+-------+-------+-------+
  331. * | LSP Sequence Number | 4
  332. * +-------+-------+-------+-------+-------+-------+-------+-------+
  333. * | Checksum | 2
  334. * +-------+-------+-------+-------+-------+-------+-------+-------+
  335. */
  336. #ifdef EXTREME_TLV_DEBUG
  337. zlog_debug ("ISIS-TLV (%s): LSP Entries length %d", areatag, length);
  338. #endif /* EXTREME_TLV_DEBUG */
  339. *found |= TLVFLAG_LSP_ENTRIES;
  340. if (TLVFLAG_LSP_ENTRIES & *expected)
  341. {
  342. while (length > value_len)
  343. {
  344. lsp_entry = (struct lsp_entry *) pnt;
  345. value_len += 10 + ISIS_SYS_ID_LEN;
  346. pnt += 10 + ISIS_SYS_ID_LEN;
  347. if (!tlvs->lsp_entries)
  348. tlvs->lsp_entries = list_new ();
  349. listnode_add (tlvs->lsp_entries, lsp_entry);
  350. }
  351. }
  352. else
  353. {
  354. pnt += length;
  355. }
  356. break;
  357. case CHECKSUM:
  358. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  359. * | 16 bit fletcher CHECKSUM |
  360. * +-------+-------+-------+-------+-------+-------+-------+-------+
  361. * : :
  362. */
  363. *found |= TLVFLAG_CHECKSUM;
  364. #ifdef EXTREME_TLV_DEBUG
  365. zlog_debug ("ISIS-TLV (%s): Checksum length %d", areatag, length);
  366. #endif /* EXTREME_TLV_DEBUG */
  367. if (*expected & TLVFLAG_CHECKSUM)
  368. {
  369. tlvs->checksum = (struct checksum *) pnt;
  370. }
  371. pnt += length;
  372. break;
  373. case PROTOCOLS_SUPPORTED:
  374. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  375. * | NLPID |
  376. * +-------+-------+-------+-------+-------+-------+-------+-------+
  377. * : :
  378. */
  379. *found |= TLVFLAG_NLPID;
  380. #ifdef EXTREME_TLV_DEBUG
  381. zlog_debug ("ISIS-TLV (%s): Protocols Supported length %d",
  382. areatag, length);
  383. #endif /* EXTREME_TLV_DEBUG */
  384. if (*expected & TLVFLAG_NLPID)
  385. {
  386. tlvs->nlpids = (struct nlpids *) (pnt - 1);
  387. }
  388. pnt += length;
  389. break;
  390. case IPV4_ADDR:
  391. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  392. * + IP version 4 address + 4
  393. * +-------+-------+-------+-------+-------+-------+-------+-------+
  394. * : :
  395. */
  396. *found |= TLVFLAG_IPV4_ADDR;
  397. #ifdef EXTREME_TLV_DEBUG
  398. zlog_debug ("ISIS-TLV (%s): IPv4 Address length %d",
  399. areatag, length);
  400. #endif /* EXTREME_TLV_DEBUG */
  401. if (*expected & TLVFLAG_IPV4_ADDR)
  402. {
  403. while (length > value_len)
  404. {
  405. ipv4_addr = (struct in_addr *) pnt;
  406. #ifdef EXTREME_TLV_DEBUG
  407. zlog_debug ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag,
  408. inet_ntoa (*ipv4_addr), pnt);
  409. #endif /* EXTREME_TLV_DEBUG */
  410. if (!tlvs->ipv4_addrs)
  411. tlvs->ipv4_addrs = list_new ();
  412. listnode_add (tlvs->ipv4_addrs, ipv4_addr);
  413. value_len += 4;
  414. pnt += 4;
  415. }
  416. }
  417. else
  418. {
  419. pnt += length;
  420. }
  421. break;
  422. case AUTH_INFO:
  423. *found |= TLVFLAG_AUTH_INFO;
  424. #ifdef EXTREME_TLV_DEBUG
  425. zlog_debug ("ISIS-TLV (%s): IS-IS Authentication Information",
  426. areatag);
  427. #endif
  428. if (*expected & TLVFLAG_AUTH_INFO)
  429. {
  430. tlvs->auth_info.type = *pnt;
  431. if (length == 0)
  432. {
  433. zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) "
  434. "incorrect.", areatag, type, length);
  435. return ISIS_WARNING;
  436. }
  437. --length;
  438. tlvs->auth_info.len = length;
  439. pnt++;
  440. memcpy (tlvs->auth_info.passwd, pnt, length);
  441. /* Return the authentication tlv pos for later computation
  442. * of MD5 (RFC 5304, 2)
  443. */
  444. if (auth_tlv_offset)
  445. *auth_tlv_offset += (pnt - start - 3);
  446. pnt += length;
  447. }
  448. else
  449. {
  450. pnt += length;
  451. }
  452. break;
  453. case DYNAMIC_HOSTNAME:
  454. *found |= TLVFLAG_DYN_HOSTNAME;
  455. #ifdef EXTREME_TLV_DEBUG
  456. zlog_debug ("ISIS-TLV (%s): Dynamic Hostname length %d",
  457. areatag, length);
  458. #endif /* EXTREME_TLV_DEBUG */
  459. if (*expected & TLVFLAG_DYN_HOSTNAME)
  460. {
  461. /* the length is also included in the pointed struct */
  462. tlvs->hostname = (struct hostname *) (pnt - 1);
  463. }
  464. pnt += length;
  465. break;
  466. case TE_ROUTER_ID:
  467. /* +---------------------------------------------------------------+
  468. * + Router ID + 4
  469. * +---------------------------------------------------------------+
  470. */
  471. *found |= TLVFLAG_TE_ROUTER_ID;
  472. #ifdef EXTREME_TLV_DEBUG
  473. zlog_debug ("ISIS-TLV (%s): TE Router ID %d", areatag, length);
  474. #endif /* EXTREME_TLV_DEBUG */
  475. if (*expected & TLVFLAG_TE_ROUTER_ID)
  476. tlvs->router_id = (struct te_router_id *) (pnt);
  477. pnt += length;
  478. break;
  479. case IPV4_INT_REACHABILITY:
  480. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  481. * | 0 | I/E | Default Metric | 1
  482. * +-------+-------+-------+-------+-------+-------+-------+-------+
  483. * | S | I/E | Delay Metric | 1
  484. * +-------+-------+-------+-------+-------+-------+-------+-------+
  485. * | S | I/E | Expense Metric | 1
  486. * +-------+-------+-------+-------+-------+-------+-------+-------+
  487. * | S | I/E | Error Metric | 1
  488. * +-------+-------+-------+-------+-------+-------+-------+-------+
  489. * | ip address | 4
  490. * +---------------------------------------------------------------+
  491. * | address mask | 4
  492. * +---------------------------------------------------------------+
  493. * : :
  494. */
  495. *found |= TLVFLAG_IPV4_INT_REACHABILITY;
  496. #ifdef EXTREME_TLV_DEBUG
  497. zlog_debug ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
  498. areatag, length);
  499. #endif /* EXTREME_TLV_DEBUG */
  500. if (*expected & TLVFLAG_IPV4_INT_REACHABILITY)
  501. {
  502. while (length > value_len)
  503. {
  504. ipv4_reach = (struct ipv4_reachability *) pnt;
  505. if (!tlvs->ipv4_int_reachs)
  506. tlvs->ipv4_int_reachs = list_new ();
  507. listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
  508. value_len += 12;
  509. pnt += 12;
  510. }
  511. }
  512. else
  513. {
  514. pnt += length;
  515. }
  516. break;
  517. case IPV4_EXT_REACHABILITY:
  518. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  519. * | 0 | I/E | Default Metric | 1
  520. * +-------+-------+-------+-------+-------+-------+-------+-------+
  521. * | S | I/E | Delay Metric | 1
  522. * +-------+-------+-------+-------+-------+-------+-------+-------+
  523. * | S | I/E | Expense Metric | 1
  524. * +-------+-------+-------+-------+-------+-------+-------+-------+
  525. * | S | I/E | Error Metric | 1
  526. * +-------+-------+-------+-------+-------+-------+-------+-------+
  527. * | ip address | 4
  528. * +---------------------------------------------------------------+
  529. * | address mask | 4
  530. * +---------------------------------------------------------------+
  531. * : :
  532. */
  533. *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
  534. #ifdef EXTREME_TLV_DEBUG
  535. zlog_debug ("ISIS-TLV (%s): IPv4 external Reachability length %d",
  536. areatag, length);
  537. #endif /* EXTREME_TLV_DEBUG */
  538. if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY)
  539. {
  540. while (length > value_len)
  541. {
  542. ipv4_reach = (struct ipv4_reachability *) pnt;
  543. if (!tlvs->ipv4_ext_reachs)
  544. tlvs->ipv4_ext_reachs = list_new ();
  545. listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
  546. value_len += 12;
  547. pnt += 12;
  548. }
  549. }
  550. else
  551. {
  552. pnt += length;
  553. }
  554. break;
  555. case TE_IPV4_REACHABILITY:
  556. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  557. * | TE Metric | 4
  558. * +-------+-------+-------+-------+-------+-------+-------+-------+
  559. * | U/D | sTLV? | Prefix Mask Len | 1
  560. * +-------+-------+-------+-------+-------+-------+-------+-------+
  561. * | Prefix | 0-4
  562. * +---------------------------------------------------------------+
  563. * | sub tlvs |
  564. * +---------------------------------------------------------------+
  565. * : :
  566. */
  567. *found |= TLVFLAG_TE_IPV4_REACHABILITY;
  568. #ifdef EXTREME_TLV_DEBUG
  569. zlog_debug ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
  570. areatag, length);
  571. #endif /* EXTREME_TLV_DEBUG */
  572. endpnt = pnt + length;
  573. if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
  574. {
  575. while (length > value_len)
  576. {
  577. te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
  578. if ((te_ipv4_reach->control & 0x3F) > IPV4_MAX_BITLEN)
  579. {
  580. zlog_warn ("ISIS-TLV (%s): invalid IPv4 extended reach"
  581. "ability prefix length %d", areatag,
  582. te_ipv4_reach->control & 0x3F);
  583. retval = ISIS_WARNING;
  584. break;
  585. }
  586. if (!tlvs->te_ipv4_reachs)
  587. tlvs->te_ipv4_reachs = list_new ();
  588. listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
  589. /* this trickery is permitable since no subtlvs are defined */
  590. value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
  591. ((((te_ipv4_reach->control & 0x3F) -
  592. 1) >> 3) + 1) : 0);
  593. pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
  594. ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
  595. }
  596. }
  597. pnt = endpnt;
  598. break;
  599. #ifdef HAVE_IPV6
  600. case IPV6_ADDR:
  601. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  602. * + IP version 6 address + 16
  603. * +-------+-------+-------+-------+-------+-------+-------+-------+
  604. * : :
  605. */
  606. *found |= TLVFLAG_IPV6_ADDR;
  607. #ifdef EXTREME_TLV_DEBUG
  608. zlog_debug ("ISIS-TLV (%s): IPv6 Address length %d",
  609. areatag, length);
  610. #endif /* EXTREME_TLV_DEBUG */
  611. if (*expected & TLVFLAG_IPV6_ADDR)
  612. {
  613. while (length > value_len)
  614. {
  615. ipv6_addr = (struct in6_addr *) pnt;
  616. if (!tlvs->ipv6_addrs)
  617. tlvs->ipv6_addrs = list_new ();
  618. listnode_add (tlvs->ipv6_addrs, ipv6_addr);
  619. value_len += 16;
  620. pnt += 16;
  621. }
  622. }
  623. else
  624. {
  625. pnt += length;
  626. }
  627. break;
  628. case IPV6_REACHABILITY:
  629. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  630. * | Default Metric | 4
  631. * +-------+-------+-------+-------+-------+-------+-------+-------+
  632. * | Control Informantion |
  633. * +---------------------------------------------------------------+
  634. * | IPv6 Prefix Length |--+
  635. * +---------------------------------------------------------------+ |
  636. * | IPv6 Prefix |<-+
  637. * +---------------------------------------------------------------+
  638. */
  639. *found |= TLVFLAG_IPV6_REACHABILITY;
  640. endpnt = pnt + length;
  641. if (*expected & TLVFLAG_IPV6_REACHABILITY)
  642. {
  643. while (length > value_len)
  644. {
  645. ipv6_reach = (struct ipv6_reachability *) pnt;
  646. if (ipv6_reach->prefix_len > IPV6_MAX_BITLEN)
  647. {
  648. zlog_warn ("ISIS-TLV (%s): invalid IPv6 extended reach"
  649. "ability prefix length %d", areatag,
  650. ipv6_reach->prefix_len);
  651. retval = ISIS_WARNING;
  652. break;
  653. }
  654. prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
  655. value_len += prefix_octets + 6;
  656. pnt += prefix_octets + 6;
  657. /* FIXME: sub-tlvs */
  658. if (!tlvs->ipv6_reachs)
  659. tlvs->ipv6_reachs = list_new ();
  660. listnode_add (tlvs->ipv6_reachs, ipv6_reach);
  661. }
  662. }
  663. pnt = endpnt;
  664. break;
  665. #endif /* HAVE_IPV6 */
  666. case WAY3_HELLO:
  667. /* +---------------------------------------------------------------+
  668. * | Adjacency state | 1
  669. * +---------------------------------------------------------------+
  670. * | Extended Local Circuit ID | 4
  671. * +---------------------------------------------------------------+
  672. * | Neighbor System ID (If known) | 0-8
  673. * (probably 6)
  674. * +---------------------------------------------------------------+
  675. * | Neighbor Local Circuit ID (If known) | 4
  676. * +---------------------------------------------------------------+
  677. */
  678. *found |= TLVFLAG_3WAY_HELLO;
  679. if (*expected & TLVFLAG_3WAY_HELLO)
  680. {
  681. while (length > value_len)
  682. {
  683. /* FIXME: make this work */
  684. /* Adjacency State (one octet):
  685. 0 = Up
  686. 1 = Initializing
  687. 2 = Down
  688. Extended Local Circuit ID (four octets)
  689. Neighbor System ID if known (zero to eight octets)
  690. Neighbor Extended Local Circuit ID (four octets, if Neighbor
  691. System ID is present) */
  692. pnt += length;
  693. value_len += length;
  694. }
  695. }
  696. else
  697. {
  698. pnt += length;
  699. }
  700. break;
  701. case GRACEFUL_RESTART:
  702. /* +-------+-------+-------+-------+-------+-------+-------+-------+
  703. * | Reserved | SA | RA | RR | 1
  704. * +-------+-------+-------+-------+-------+-------+-------+-------+
  705. * | Remaining Time | 2
  706. * +---------------------------------------------------------------+
  707. * | Restarting Neighbor ID (If known) | 0-8
  708. * +---------------------------------------------------------------+
  709. */
  710. *found |= TLVFLAG_GRACEFUL_RESTART;
  711. if (*expected & TLVFLAG_GRACEFUL_RESTART)
  712. {
  713. /* FIXME: make this work */
  714. }
  715. pnt += length;
  716. break;
  717. default:
  718. zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
  719. areatag, type, length);
  720. pnt += length;
  721. break;
  722. }
  723. }
  724. return retval;
  725. }
  726. int
  727. add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
  728. {
  729. if ((stream_get_size (stream) - stream_get_endp (stream)) <
  730. (((unsigned)len) + 2))
  731. {
  732. zlog_warn ("No room for TLV of type %d "
  733. "(total size %d available %d required %d)",
  734. tag, (int)stream_get_size (stream),
  735. (int)(stream_get_size (stream) - stream_get_endp (stream)),
  736. len+2);
  737. return ISIS_WARNING;
  738. }
  739. stream_putc (stream, tag); /* TAG */
  740. stream_putc (stream, len); /* LENGTH */
  741. stream_put (stream, value, (int) len); /* VALUE */
  742. #ifdef EXTREME_DEBUG
  743. zlog_debug ("Added TLV %d len %d", tag, len);
  744. #endif /* EXTREME DEBUG */
  745. return ISIS_OK;
  746. }
  747. int
  748. tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
  749. {
  750. struct listnode *node;
  751. struct area_addr *area_addr;
  752. u_char value[255];
  753. u_char *pos = value;
  754. for (ALL_LIST_ELEMENTS_RO (area_addrs, node, area_addr))
  755. {
  756. if (pos - value + area_addr->addr_len > 255)
  757. goto err;
  758. *pos = area_addr->addr_len;
  759. pos++;
  760. memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
  761. pos += area_addr->addr_len;
  762. }
  763. return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
  764. err:
  765. zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
  766. return ISIS_WARNING;
  767. }
  768. int
  769. tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
  770. {
  771. struct listnode *node;
  772. struct is_neigh *is_neigh;
  773. u_char value[255];
  774. u_char *pos = value;
  775. int retval;
  776. *pos = 0; /*is_neigh->virtual; */
  777. pos++;
  778. for (ALL_LIST_ELEMENTS_RO (is_neighs, node, is_neigh))
  779. {
  780. if (pos - value + IS_NEIGHBOURS_LEN > 255)
  781. {
  782. retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
  783. if (retval != ISIS_OK)
  784. return retval;
  785. pos = value;
  786. }
  787. *pos = is_neigh->metrics.metric_default;
  788. pos++;
  789. *pos = is_neigh->metrics.metric_delay;
  790. pos++;
  791. *pos = is_neigh->metrics.metric_expense;
  792. pos++;
  793. *pos = is_neigh->metrics.metric_error;
  794. pos++;
  795. memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
  796. pos += ISIS_SYS_ID_LEN + 1;
  797. }
  798. return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
  799. }
  800. int
  801. tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream)
  802. {
  803. struct listnode *node;
  804. struct te_is_neigh *te_is_neigh;
  805. u_char value[255];
  806. u_char *pos = value;
  807. int retval;
  808. for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
  809. {
  810. /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */
  811. if (pos - value + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > 255)
  812. {
  813. retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
  814. if (retval != ISIS_OK)
  815. return retval;
  816. pos = value;
  817. }
  818. memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
  819. pos += ISIS_SYS_ID_LEN + 1;
  820. memcpy (pos, te_is_neigh->te_metric, 3);
  821. pos += 3;
  822. /* Set the total size of Sub TLVs */
  823. *pos = te_is_neigh->sub_tlvs_length;
  824. pos++;
  825. /* Copy Sub TLVs if any */
  826. if (te_is_neigh->sub_tlvs_length > 0)
  827. {
  828. memcpy (pos, te_is_neigh->sub_tlvs, te_is_neigh->sub_tlvs_length);
  829. pos += te_is_neigh->sub_tlvs_length;
  830. }
  831. }
  832. return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
  833. }
  834. int
  835. tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
  836. {
  837. struct listnode *node;
  838. u_char *snpa;
  839. u_char value[255];
  840. u_char *pos = value;
  841. int retval;
  842. for (ALL_LIST_ELEMENTS_RO (lan_neighs, node, snpa))
  843. {
  844. if (pos - value + ETH_ALEN > 255)
  845. {
  846. retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
  847. if (retval != ISIS_OK)
  848. return retval;
  849. pos = value;
  850. }
  851. memcpy (pos, snpa, ETH_ALEN);
  852. pos += ETH_ALEN;
  853. }
  854. return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
  855. }
  856. int
  857. tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
  858. {
  859. return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
  860. }
  861. int
  862. tlv_add_authinfo (u_char auth_type, u_char auth_len, u_char *auth_value,
  863. struct stream *stream)
  864. {
  865. u_char value[255];
  866. u_char *pos = value;
  867. *pos++ = auth_type;
  868. memcpy (pos, auth_value, auth_len);
  869. return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
  870. }
  871. int
  872. tlv_add_checksum (struct checksum *checksum, struct stream *stream)
  873. {
  874. u_char value[255];
  875. u_char *pos = value;
  876. return add_tlv (CHECKSUM, pos - value, value, stream);
  877. }
  878. int
  879. tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
  880. {
  881. struct listnode *node;
  882. struct prefix_ipv4 *ipv4;
  883. u_char value[255];
  884. u_char *pos = value;
  885. for (ALL_LIST_ELEMENTS_RO (ip_addrs, node, ipv4))
  886. {
  887. if (pos - value + IPV4_MAX_BYTELEN > 255)
  888. {
  889. /* RFC 1195 s4.2: only one tuple of 63 allowed. */
  890. zlog_warn ("tlv_add_ip_addrs(): cutting off at 63 IP addresses");
  891. break;
  892. }
  893. *(u_int32_t *) pos = ipv4->prefix.s_addr;
  894. pos += IPV4_MAX_BYTELEN;
  895. }
  896. return add_tlv (IPV4_ADDR, pos - value, value, stream);
  897. }
  898. /* Used to add TLV containing just one IPv4 address - either IPv4 address TLV
  899. * (in case of LSP) or TE router ID TLV. */
  900. int
  901. tlv_add_in_addr (struct in_addr *addr, struct stream *stream, u_char tag)
  902. {
  903. u_char value[255];
  904. u_char *pos = value;
  905. memcpy (pos, addr, IPV4_MAX_BYTELEN);
  906. pos += IPV4_MAX_BYTELEN;
  907. return add_tlv (tag, pos - value, value, stream);
  908. }
  909. int
  910. tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
  911. {
  912. return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
  913. stream);
  914. }
  915. int
  916. tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
  917. {
  918. struct listnode *node;
  919. struct isis_lsp *lsp;
  920. u_char value[255];
  921. u_char *pos = value;
  922. int retval;
  923. for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp))
  924. {
  925. if (pos - value + LSP_ENTRIES_LEN > 255)
  926. {
  927. retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
  928. if (retval != ISIS_OK)
  929. return retval;
  930. pos = value;
  931. }
  932. *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
  933. pos += 2;
  934. memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
  935. pos += ISIS_SYS_ID_LEN + 2;
  936. *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
  937. pos += 4;
  938. *((u_int16_t *) pos) = lsp->lsp_header->checksum;
  939. pos += 2;
  940. }
  941. return add_tlv (LSP_ENTRIES, pos - value, value, stream);
  942. }
  943. static int
  944. tlv_add_ipv4_reachs (u_char tag, struct list *ipv4_reachs, struct stream *stream)
  945. {
  946. struct listnode *node;
  947. struct ipv4_reachability *reach;
  948. u_char value[255];
  949. u_char *pos = value;
  950. int retval;
  951. for (ALL_LIST_ELEMENTS_RO (ipv4_reachs, node, reach))
  952. {
  953. if (pos - value + IPV4_REACH_LEN > 255)
  954. {
  955. retval =
  956. add_tlv (tag, pos - value, value, stream);
  957. if (retval != ISIS_OK)
  958. return retval;
  959. pos = value;
  960. }
  961. *pos = reach->metrics.metric_default;
  962. pos++;
  963. *pos = reach->metrics.metric_delay;
  964. pos++;
  965. *pos = reach->metrics.metric_expense;
  966. pos++;
  967. *pos = reach->metrics.metric_error;
  968. pos++;
  969. *(u_int32_t *) pos = reach->prefix.s_addr;
  970. pos += IPV4_MAX_BYTELEN;
  971. *(u_int32_t *) pos = reach->mask.s_addr;
  972. pos += IPV4_MAX_BYTELEN;
  973. }
  974. return add_tlv (tag, pos - value, value, stream);
  975. }
  976. int
  977. tlv_add_ipv4_int_reachs (struct list *ipv4_reachs, struct stream *stream)
  978. {
  979. return tlv_add_ipv4_reachs(IPV4_INT_REACHABILITY, ipv4_reachs, stream);
  980. }
  981. int
  982. tlv_add_ipv4_ext_reachs (struct list *ipv4_reachs, struct stream *stream)
  983. {
  984. return tlv_add_ipv4_reachs(IPV4_EXT_REACHABILITY, ipv4_reachs, stream);
  985. }
  986. int
  987. tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
  988. {
  989. struct listnode *node;
  990. struct te_ipv4_reachability *te_reach;
  991. u_char value[255];
  992. u_char *pos = value;
  993. u_char prefix_size;
  994. int retval;
  995. for (ALL_LIST_ELEMENTS_RO (te_ipv4_reachs, node, te_reach))
  996. {
  997. prefix_size = ((((te_reach->control & 0x3F) - 1) >> 3) + 1);
  998. if (pos - value + (5 + prefix_size) > 255)
  999. {
  1000. retval =
  1001. add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
  1002. if (retval != ISIS_OK)
  1003. return retval;
  1004. pos = value;
  1005. }
  1006. *(u_int32_t *) pos = te_reach->te_metric;
  1007. pos += 4;
  1008. *pos = te_reach->control;
  1009. pos++;
  1010. memcpy (pos, &te_reach->prefix_start, prefix_size);
  1011. pos += prefix_size;
  1012. }
  1013. return add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
  1014. }
  1015. #ifdef HAVE_IPV6
  1016. int
  1017. tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
  1018. {
  1019. struct listnode *node;
  1020. struct prefix_ipv6 *ipv6;
  1021. u_char value[255];
  1022. u_char *pos = value;
  1023. int retval;
  1024. for (ALL_LIST_ELEMENTS_RO (ipv6_addrs, node, ipv6))
  1025. {
  1026. if (pos - value + IPV6_MAX_BYTELEN > 255)
  1027. {
  1028. retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
  1029. if (retval != ISIS_OK)
  1030. return retval;
  1031. pos = value;
  1032. }
  1033. memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
  1034. pos += IPV6_MAX_BYTELEN;
  1035. }
  1036. return add_tlv (IPV6_ADDR, pos - value, value, stream);
  1037. }
  1038. int
  1039. tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
  1040. {
  1041. struct listnode *node;
  1042. struct ipv6_reachability *ip6reach;
  1043. u_char value[255];
  1044. u_char *pos = value;
  1045. int retval, prefix_octets;
  1046. for (ALL_LIST_ELEMENTS_RO (ipv6_reachs, node, ip6reach))
  1047. {
  1048. if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
  1049. {
  1050. retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
  1051. if (retval != ISIS_OK)
  1052. return retval;
  1053. pos = value;
  1054. }
  1055. *(uint32_t *) pos = ip6reach->metric;
  1056. pos += 4;
  1057. *pos = ip6reach->control_info;
  1058. pos++;
  1059. prefix_octets = ((ip6reach->prefix_len + 7) / 8);
  1060. *pos = ip6reach->prefix_len;
  1061. pos++;
  1062. memcpy (pos, ip6reach->prefix, prefix_octets);
  1063. pos += prefix_octets;
  1064. }
  1065. return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
  1066. }
  1067. #endif /* HAVE_IPV6 */
  1068. int
  1069. tlv_add_padding (struct stream *stream)
  1070. {
  1071. int fullpads, i, left;
  1072. /*
  1073. * How many times can we add full padding ?
  1074. */
  1075. fullpads = (stream_get_size (stream) - stream_get_endp (stream)) / 257;
  1076. for (i = 0; i < fullpads; i++)
  1077. {
  1078. if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
  1079. goto err;
  1080. if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
  1081. goto err;
  1082. stream_put (stream, NULL, 255); /* zero padding */
  1083. }
  1084. left = stream_get_size (stream) - stream_get_endp (stream);
  1085. if (left < 2)
  1086. return ISIS_OK;
  1087. if (left == 2)
  1088. {
  1089. stream_putc (stream, PADDING);
  1090. stream_putc (stream, 0);
  1091. return ISIS_OK;
  1092. }
  1093. stream_putc (stream, PADDING);
  1094. stream_putc (stream, left - 2);
  1095. stream_put (stream, NULL, left-2);
  1096. return ISIS_OK;
  1097. err:
  1098. zlog_warn ("tlv_add_padding(): no room for tlv");
  1099. return ISIS_WARNING;
  1100. }