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