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