Annotation of embedaddon/quagga/isisd/isis_pdu.c, revision 1.1.1.1
1.1 misho 1: /*
2: * IS-IS Rout(e)ing protocol - isis_pdu.c
3: * PDU processing
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 "memory.h"
27: #include "thread.h"
28: #include "linklist.h"
29: #include "log.h"
30: #include "stream.h"
31: #include "vty.h"
32: #include "hash.h"
33: #include "prefix.h"
34: #include "if.h"
35: #include "checksum.h"
36:
37: #include "isisd/dict.h"
38: #include "isisd/include-netbsd/iso.h"
39: #include "isisd/isis_constants.h"
40: #include "isisd/isis_common.h"
41: #include "isisd/isis_adjacency.h"
42: #include "isisd/isis_circuit.h"
43: #include "isisd/isis_network.h"
44: #include "isisd/isis_misc.h"
45: #include "isisd/isis_dr.h"
46: #include "isisd/isis_flags.h"
47: #include "isisd/isis_tlv.h"
48: #include "isisd/isisd.h"
49: #include "isisd/isis_dynhn.h"
50: #include "isisd/isis_lsp.h"
51: #include "isisd/isis_pdu.h"
52: #include "isisd/iso_checksum.h"
53: #include "isisd/isis_csm.h"
54: #include "isisd/isis_events.h"
55:
56: extern struct thread_master *master;
57: extern struct isis *isis;
58:
59: #define ISIS_MINIMUM_FIXED_HDR_LEN 15
60: #define ISIS_MIN_PDU_LEN 13 /* partial seqnum pdu with id_len=2 */
61:
62: #ifndef PNBBY
63: #define PNBBY 8
64: #endif /* PNBBY */
65:
66: /* Utility mask array. */
67: static const u_char maskbit[] = {
68: 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
69: };
70:
71: /*
72: * HELPER FUNCS
73: */
74:
75: /*
76: * Compares two sets of area addresses
77: */
78: static int
79: area_match (struct list *left, struct list *right)
80: {
81: struct area_addr *addr1, *addr2;
82: struct listnode *node1, *node2;
83:
84: for (ALL_LIST_ELEMENTS_RO (left, node1, addr1))
85: {
86: for (ALL_LIST_ELEMENTS_RO (right, node2, addr2))
87: {
88: if (addr1->addr_len == addr2->addr_len &&
89: !memcmp (addr1->area_addr, addr2->area_addr, (int) addr1->addr_len))
90: return 1; /* match */
91: }
92: }
93:
94: return 0; /* mismatch */
95: }
96:
97: /*
98: * Check if ip2 is in the ip1's network (function like Prefix.h:prefix_match() )
99: * param ip1 the IS interface ip address structure
100: * param ip2 the IIH's ip address
101: * return 0 the IIH's IP is not in the IS's subnetwork
102: * 1 the IIH's IP is in the IS's subnetwork
103: */
104: static int
105: ip_same_subnet (struct prefix_ipv4 *ip1, struct in_addr *ip2)
106: {
107: u_char *addr1, *addr2;
108: int shift, offset, offsetloop;
109: int len;
110:
111: addr1 = (u_char *) & ip1->prefix.s_addr;
112: addr2 = (u_char *) & ip2->s_addr;
113: len = ip1->prefixlen;
114:
115: shift = len % PNBBY;
116: offsetloop = offset = len / PNBBY;
117:
118: while (offsetloop--)
119: if (addr1[offsetloop] != addr2[offsetloop])
120: return 0;
121:
122: if (shift)
123: if (maskbit[shift] & (addr1[offset] ^ addr2[offset]))
124: return 0;
125:
126: return 1; /* match */
127: }
128:
129: /*
130: * Compares two set of ip addresses
131: * param left the local interface's ip addresses
132: * param right the iih interface's ip address
133: * return 0 no match;
134: * 1 match;
135: */
136: static int
137: ip_match (struct list *left, struct list *right)
138: {
139: struct prefix_ipv4 *ip1;
140: struct in_addr *ip2;
141: struct listnode *node1, *node2;
142:
143: if ((left == NULL) || (right == NULL))
144: return 0;
145:
146: for (ALL_LIST_ELEMENTS_RO (left, node1, ip1))
147: {
148: for (ALL_LIST_ELEMENTS_RO (right, node2, ip2))
149: {
150: if (ip_same_subnet (ip1, ip2))
151: {
152: return 1; /* match */
153: }
154: }
155:
156: }
157: return 0;
158: }
159:
160: /*
161: * Checks whether we should accept a PDU of given level
162: */
163: static int
164: accept_level (int level, int circuit_t)
165: {
166: int retval = ((circuit_t & level) == level); /* simple approach */
167:
168: return retval;
169: }
170:
171: int
172: authentication_check (struct isis_passwd *one, struct isis_passwd *theother)
173: {
174: if (one->type != theother->type)
175: {
176: zlog_warn ("Unsupported authentication type %d", theother->type);
177: return 1; /* Auth fail (different authentication types) */
178: }
179: switch (one->type)
180: {
181: case ISIS_PASSWD_TYPE_CLEARTXT:
182: if (one->len != theother->len)
183: return 1; /* Auth fail () - passwd len mismatch */
184: return memcmp (one->passwd, theother->passwd, one->len);
185: break;
186: default:
187: zlog_warn ("Unsupported authentication type");
188: break;
189: }
190: return 0; /* Auth pass */
191: }
192:
193: /*
194: * Processing helper functions
195: */
196: static void
197: tlvs_to_adj_nlpids (struct tlvs *tlvs, struct isis_adjacency *adj)
198: {
199: int i;
200: struct nlpids *tlv_nlpids;
201:
202: if (tlvs->nlpids)
203: {
204:
205: tlv_nlpids = tlvs->nlpids;
206:
207: adj->nlpids.count = tlv_nlpids->count;
208:
209: for (i = 0; i < tlv_nlpids->count; i++)
210: {
211: adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i];
212: }
213: }
214: }
215:
216: static void
217: del_ip_addr (void *val)
218: {
219: XFREE (MTYPE_ISIS_TMP, val);
220: }
221:
222: static void
223: tlvs_to_adj_ipv4_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)
224: {
225: struct listnode *node;
226: struct in_addr *ipv4_addr, *malloced;
227:
228: if (adj->ipv4_addrs)
229: {
230: adj->ipv4_addrs->del = del_ip_addr;
231: list_delete (adj->ipv4_addrs);
232: }
233: adj->ipv4_addrs = list_new ();
234: if (tlvs->ipv4_addrs)
235: {
236: for (ALL_LIST_ELEMENTS_RO (tlvs->ipv4_addrs, node, ipv4_addr))
237: {
238: malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in_addr));
239: memcpy (malloced, ipv4_addr, sizeof (struct in_addr));
240: listnode_add (adj->ipv4_addrs, malloced);
241: }
242: }
243: }
244:
245: #ifdef HAVE_IPV6
246: static void
247: tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)
248: {
249: struct listnode *node;
250: struct in6_addr *ipv6_addr, *malloced;
251:
252: if (adj->ipv6_addrs)
253: {
254: adj->ipv6_addrs->del = del_ip_addr;
255: list_delete (adj->ipv6_addrs);
256: }
257: adj->ipv6_addrs = list_new ();
258: if (tlvs->ipv6_addrs)
259: {
260: for (ALL_LIST_ELEMENTS_RO (tlvs->ipv6_addrs, node, ipv6_addr))
261: {
262: malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in6_addr));
263: memcpy (malloced, ipv6_addr, sizeof (struct in6_addr));
264: listnode_add (adj->ipv6_addrs, malloced);
265: }
266: }
267:
268: }
269: #endif /* HAVE_IPV6 */
270:
271: /*
272: * RECEIVE SIDE
273: */
274:
275: /*
276: * Process P2P IIH
277: * ISO - 10589
278: * Section 8.2.5 - Receiving point-to-point IIH PDUs
279: *
280: */
281: static int
282: process_p2p_hello (struct isis_circuit *circuit)
283: {
284: int retval = ISIS_OK;
285: struct isis_p2p_hello_hdr *hdr;
286: struct isis_adjacency *adj;
287: u_int32_t expected = 0, found;
288: struct tlvs tlvs;
289:
290: if ((stream_get_endp (circuit->rcv_stream) -
291: stream_get_getp (circuit->rcv_stream)) < ISIS_P2PHELLO_HDRLEN)
292: {
293: zlog_warn ("Packet too short");
294: return ISIS_WARNING;
295: }
296:
297: /* 8.2.5.1 PDU acceptance tests */
298:
299: /* 8.2.5.1 a) external domain untrue */
300: /* FIXME: not useful at all? */
301:
302: /* 8.2.5.1 b) ID Length mismatch */
303: /* checked at the handle_pdu */
304:
305: /* 8.2.5.2 IIH PDU Processing */
306:
307: /* 8.2.5.2 a) 1) Maximum Area Addresses */
308: /* Already checked, and can also be ommited */
309:
310: /*
311: * Get the header
312: */
313: hdr = (struct isis_p2p_hello_hdr *) STREAM_PNT (circuit->rcv_stream);
314: circuit->rcv_stream->getp += ISIS_P2PHELLO_HDRLEN;
315:
316: /* hdr.circuit_t = stream_getc (stream);
317: stream_get (hdr.source_id, stream, ISIS_SYS_ID_LEN);
318: hdr.hold_time = stream_getw (stream);
319: hdr.pdu_len = stream_getw (stream);
320: hdr.local_id = stream_getc (stream); */
321:
322: /*
323: * My interpertation of the ISO, if no adj exists we will create one for
324: * the circuit
325: */
326:
327: if (isis->debugs & DEBUG_ADJ_PACKETS)
328: {
329: zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s,"
330: " cir id %02d, length %d",
331: circuit->area->area_tag, circuit->interface->name,
332: circuit_t2string (circuit->circuit_is_type),
333: circuit->circuit_id, ntohs (hdr->pdu_len));
334: }
335:
336: adj = circuit->u.p2p.neighbor;
337: if (!adj)
338: {
339: adj = isis_new_adj (hdr->source_id, NULL, 0, circuit);
340: if (adj == NULL)
341: return ISIS_ERROR;
342: circuit->u.p2p.neighbor = adj;
343: isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
344: adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
345: }
346:
347: /* 8.2.6 Monitoring point-to-point adjacencies */
348: adj->hold_time = ntohs (hdr->hold_time);
349: adj->last_upd = time (NULL);
350:
351: /*
352: * Lets get the TLVS now
353: */
354: expected |= TLVFLAG_AREA_ADDRS;
355: expected |= TLVFLAG_AUTH_INFO;
356: expected |= TLVFLAG_NLPID;
357: expected |= TLVFLAG_IPV4_ADDR;
358: expected |= TLVFLAG_IPV6_ADDR;
359:
360: retval = parse_tlvs (circuit->area->area_tag,
361: STREAM_PNT (circuit->rcv_stream),
362: ntohs (hdr->pdu_len) - ISIS_P2PHELLO_HDRLEN
363: - ISIS_FIXED_HDR_LEN, &expected, &found, &tlvs);
364:
365: if (retval > ISIS_WARNING)
366: {
367: free_tlvs (&tlvs);
368: return retval;
369: };
370:
371: /* 8.2.5.1 c) Authentication */
372: if (circuit->passwd.type)
373: {
374: if (!(found & TLVFLAG_AUTH_INFO) ||
375: authentication_check (&circuit->passwd, &tlvs.auth_info))
376: {
377: isis_event_auth_failure (circuit->area->area_tag,
378: "P2P hello authentication failure",
379: hdr->source_id);
380: return ISIS_OK;
381: }
382: }
383:
384: /* we do this now because the adj may not survive till the end... */
385:
386: /* we need to copy addresses to the adj */
387: tlvs_to_adj_ipv4_addrs (&tlvs, adj);
388:
389: #ifdef HAVE_IPV6
390: tlvs_to_adj_ipv6_addrs (&tlvs, adj);
391: #endif /* HAVE_IPV6 */
392:
393: /* lets take care of the expiry */
394: THREAD_TIMER_OFF (adj->t_expire);
395: THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
396: (long) adj->hold_time);
397:
398: /* 8.2.5.2 a) a match was detected */
399: if (area_match (circuit->area->area_addrs, tlvs.area_addrs))
400: {
401: /* 8.2.5.2 a) 2) If the system is L1 - table 5 */
402: if (circuit->area->is_type == IS_LEVEL_1)
403: {
404: switch (hdr->circuit_t)
405: {
406: case IS_LEVEL_1:
407: case IS_LEVEL_1_AND_2:
408: if (adj->adj_state != ISIS_ADJ_UP)
409: {
410: /* (4) adj state up */
411: isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
412: /* (5) adj usage level 1 */
413: adj->adj_usage = ISIS_ADJ_LEVEL1;
414: }
415: else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
416: {
417: ; /* accept */
418: }
419: break;
420: case IS_LEVEL_2:
421: if (adj->adj_state != ISIS_ADJ_UP)
422: {
423: /* (7) reject - wrong system type event */
424: zlog_warn ("wrongSystemType");
425: return ISIS_WARNING; /* Reject */
426: }
427: else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
428: {
429: /* (6) down - wrong system */
430: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
431: }
432: break;
433: }
434: }
435:
436: /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */
437: if (circuit->area->is_type == IS_LEVEL_1_AND_2)
438: {
439: switch (hdr->circuit_t)
440: {
441: case IS_LEVEL_1:
442: if (adj->adj_state != ISIS_ADJ_UP)
443: {
444: /* (6) adj state up */
445: isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
446: /* (7) adj usage level 1 */
447: adj->adj_usage = ISIS_ADJ_LEVEL1;
448: }
449: else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
450: {
451: ; /* accept */
452: }
453: else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
454: (adj->adj_usage == ISIS_ADJ_LEVEL2))
455: {
456: /* (8) down - wrong system */
457: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
458: }
459: break;
460: case IS_LEVEL_2:
461: if (adj->adj_state != ISIS_ADJ_UP)
462: {
463: /* (6) adj state up */
464: isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
465: /* (9) adj usage level 2 */
466: adj->adj_usage = ISIS_ADJ_LEVEL2;
467: }
468: else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
469: (adj->adj_usage == ISIS_ADJ_LEVEL1AND2))
470: {
471: /* (8) down - wrong system */
472: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
473: }
474: else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
475: {
476: ; /* Accept */
477: }
478: break;
479: case IS_LEVEL_1_AND_2:
480: if (adj->adj_state != ISIS_ADJ_UP)
481: {
482: /* (6) adj state up */
483: isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
484: /* (10) adj usage level 1 */
485: adj->adj_usage = ISIS_ADJ_LEVEL1AND2;
486: }
487: else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
488: (adj->adj_usage == ISIS_ADJ_LEVEL2))
489: {
490: /* (8) down - wrong system */
491: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
492: }
493: else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
494: {
495: ; /* Accept */
496: }
497: break;
498: }
499: }
500:
501: /* 8.2.5.2 a) 4) If the system is L2 - table 7 */
502: if (circuit->area->is_type == IS_LEVEL_2)
503: {
504: switch (hdr->circuit_t)
505: {
506: case IS_LEVEL_1:
507: if (adj->adj_state != ISIS_ADJ_UP)
508: {
509: /* (5) reject - wrong system type event */
510: zlog_warn ("wrongSystemType");
511: return ISIS_WARNING; /* Reject */
512: }
513: else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
514: (adj->adj_usage == ISIS_ADJ_LEVEL2))
515: {
516: /* (6) down - wrong system */
517: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
518: }
519: break;
520: case IS_LEVEL_1_AND_2:
521: case IS_LEVEL_2:
522: if (adj->adj_state != ISIS_ADJ_UP)
523: {
524: /* (7) adj state up */
525: isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
526: /* (8) adj usage level 2 */
527: adj->adj_usage = ISIS_ADJ_LEVEL2;
528: }
529: else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
530: {
531: /* (6) down - wrong system */
532: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
533: }
534: else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
535: {
536: ; /* Accept */
537: }
538: break;
539: }
540: }
541: }
542: /* 8.2.5.2 b) if no match was detected */
543: else
544: {
545: if (circuit->area->is_type == IS_LEVEL_1)
546: {
547: /* 8.2.5.2 b) 1) is_type L1 and adj is not up */
548: if (adj->adj_state != ISIS_ADJ_UP)
549: {
550: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
551: /* 8.2.5.2 b) 2)is_type L1 and adj is up */
552: }
553: else
554: {
555: isis_adj_state_change (adj, ISIS_ADJ_DOWN,
556: "Down - Area Mismatch");
557: }
558: }
559: /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */
560: else
561: {
562: switch (hdr->circuit_t)
563: {
564: case IS_LEVEL_1:
565: if (adj->adj_state != ISIS_ADJ_UP)
566: {
567: /* (6) reject - Area Mismatch event */
568: zlog_warn ("AreaMismatch");
569: return ISIS_WARNING; /* Reject */
570: }
571: else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
572: {
573: /* (7) down - area mismatch */
574: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
575:
576: }
577: else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
578: (adj->adj_usage == ISIS_ADJ_LEVEL2))
579: {
580: /* (7) down - wrong system */
581: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
582: }
583: break;
584: case IS_LEVEL_1_AND_2:
585: case IS_LEVEL_2:
586: if (adj->adj_state != ISIS_ADJ_UP)
587: {
588: /* (8) adj state up */
589: isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
590: /* (9) adj usage level 2 */
591: adj->adj_usage = ISIS_ADJ_LEVEL2;
592: }
593: else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
594: {
595: /* (7) down - wrong system */
596: isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
597: }
598: else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
599: {
600: if (hdr->circuit_t == IS_LEVEL_2)
601: {
602: /* (7) down - wrong system */
603: isis_adj_state_change (adj, ISIS_ADJ_DOWN,
604: "Wrong System");
605: }
606: else
607: {
608: /* (7) down - area mismatch */
609: isis_adj_state_change (adj, ISIS_ADJ_DOWN,
610: "Area Mismatch");
611: }
612: }
613: else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
614: {
615: ; /* Accept */
616: }
617: break;
618: }
619: }
620: }
621: /* 8.2.5.2 c) if the action was up - comparing circuit IDs */
622: /* FIXME - Missing parts */
623:
624: /* some of my own understanding of the ISO, why the heck does
625: * it not say what should I change the system_type to...
626: */
627: switch (adj->adj_usage)
628: {
629: case ISIS_ADJ_LEVEL1:
630: adj->sys_type = ISIS_SYSTYPE_L1_IS;
631: break;
632: case ISIS_ADJ_LEVEL2:
633: adj->sys_type = ISIS_SYSTYPE_L2_IS;
634: break;
635: case ISIS_ADJ_LEVEL1AND2:
636: adj->sys_type = ISIS_SYSTYPE_L2_IS;
637: break;
638: case ISIS_ADJ_NONE:
639: adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
640: break;
641: }
642:
643: adj->circuit_t = hdr->circuit_t;
644: adj->level = hdr->circuit_t;
645:
646: free_tlvs (&tlvs);
647:
648: return retval;
649: }
650:
651: /*
652: * Process IS-IS LAN Level 1/2 Hello PDU
653: */
654: static int
655: process_lan_hello (int level, struct isis_circuit *circuit, u_char * ssnpa)
656: {
657: int retval = ISIS_OK;
658: struct isis_lan_hello_hdr hdr;
659: struct isis_adjacency *adj;
660: u_int32_t expected = 0, found;
661: struct tlvs tlvs;
662: u_char *snpa;
663: struct listnode *node;
664:
665: if ((stream_get_endp (circuit->rcv_stream) -
666: stream_get_getp (circuit->rcv_stream)) < ISIS_LANHELLO_HDRLEN)
667: {
668: zlog_warn ("Packet too short");
669: return ISIS_WARNING;
670: }
671:
672: if (circuit->ext_domain)
673: {
674: zlog_debug ("level %d LAN Hello received over circuit with "
675: "externalDomain = true", level);
676: return ISIS_WARNING;
677: }
678:
679: if (!accept_level (level, circuit->circuit_is_type))
680: {
681: if (isis->debugs & DEBUG_ADJ_PACKETS)
682: {
683: zlog_debug ("ISIS-Adj (%s): Interface level mismatch, %s",
684: circuit->area->area_tag, circuit->interface->name);
685: }
686: return ISIS_WARNING;
687: }
688:
689: #if 0
690: /* Cisco's debug message compatability */
691: if (!accept_level (level, circuit->area->is_type))
692: {
693: if (isis->debugs & DEBUG_ADJ_PACKETS)
694: {
695: zlog_debug ("ISIS-Adj (%s): is type mismatch",
696: circuit->area->area_tag);
697: }
698: return ISIS_WARNING;
699: }
700: #endif
701: /*
702: * Fill the header
703: */
704: hdr.circuit_t = stream_getc (circuit->rcv_stream);
705: stream_get (hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
706: hdr.hold_time = stream_getw (circuit->rcv_stream);
707: hdr.pdu_len = stream_getw (circuit->rcv_stream);
708: hdr.prio = stream_getc (circuit->rcv_stream);
709: stream_get (hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1);
710:
711: if (hdr.circuit_t != IS_LEVEL_1 && hdr.circuit_t != IS_LEVEL_2 &&
712: hdr.circuit_t != IS_LEVEL_1_AND_2)
713: {
714: zlog_warn ("Level %d LAN Hello with Circuit Type %d", level,
715: hdr.circuit_t);
716: return ISIS_ERROR;
717: }
718: /*
719: * Then get the tlvs
720: */
721: expected |= TLVFLAG_AUTH_INFO;
722: expected |= TLVFLAG_AREA_ADDRS;
723: expected |= TLVFLAG_LAN_NEIGHS;
724: expected |= TLVFLAG_NLPID;
725: expected |= TLVFLAG_IPV4_ADDR;
726: expected |= TLVFLAG_IPV6_ADDR;
727:
728: retval = parse_tlvs (circuit->area->area_tag,
729: STREAM_PNT (circuit->rcv_stream),
730: hdr.pdu_len - ISIS_LANHELLO_HDRLEN -
731: ISIS_FIXED_HDR_LEN, &expected, &found, &tlvs);
732:
733: if (retval > ISIS_WARNING)
734: {
735: zlog_warn ("parse_tlvs() failed");
736: goto out;
737: }
738:
739: if (!(found & TLVFLAG_AREA_ADDRS))
740: {
741: zlog_warn ("No Area addresses TLV in Level %d LAN IS to IS hello",
742: level);
743: retval = ISIS_WARNING;
744: goto out;
745: }
746:
747: if (circuit->passwd.type)
748: {
749: if (!(found & TLVFLAG_AUTH_INFO) ||
750: authentication_check (&circuit->passwd, &tlvs.auth_info))
751: {
752: isis_event_auth_failure (circuit->area->area_tag,
753: "LAN hello authentication failure",
754: hdr.source_id);
755: retval = ISIS_WARNING;
756: goto out;
757: }
758: }
759:
760: /*
761: * Accept the level 1 adjacency only if a match between local and
762: * remote area addresses is found
763: */
764: if (level == 1 && !area_match (circuit->area->area_addrs, tlvs.area_addrs))
765: {
766: if (isis->debugs & DEBUG_ADJ_PACKETS)
767: {
768: zlog_debug ("ISIS-Adj (%s): Area mismatch, level %d IIH on %s",
769: circuit->area->area_tag, level,
770: circuit->interface->name);
771: }
772: retval = ISIS_OK;
773: goto out;
774: }
775:
776: /*
777: * it's own IIH PDU - discard silently
778: */
779: if (!memcmp (circuit->u.bc.snpa, ssnpa, ETH_ALEN))
780: {
781: zlog_debug ("ISIS-Adj (%s): it's own IIH PDU - discarded",
782: circuit->area->area_tag);
783:
784: retval = ISIS_OK;
785: goto out;
786: }
787:
788: /*
789: * check if it's own interface ip match iih ip addrs
790: */
791: if (!(found & TLVFLAG_IPV4_ADDR)
792: || !ip_match (circuit->ip_addrs, tlvs.ipv4_addrs))
793: {
794: zlog_debug
795: ("ISIS-Adj: No usable IP interface addresses in LAN IIH from %s\n",
796: circuit->interface->name);
797: retval = ISIS_WARNING;
798: goto out;
799: }
800:
801: adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]);
802: if (!adj)
803: {
804: /*
805: * Do as in 8.4.2.5
806: */
807: adj = isis_new_adj (hdr.source_id, ssnpa, level, circuit);
808: if (adj == NULL)
809: {
810: retval = ISIS_ERROR;
811: goto out;
812: }
813:
814: adj->level = level;
815: isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
816:
817: if (level == 1)
818: {
819: adj->sys_type = ISIS_SYSTYPE_L1_IS;
820: }
821: else
822: {
823: adj->sys_type = ISIS_SYSTYPE_L2_IS;
824: }
825: list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
826: isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
827: circuit->u.bc.lan_neighs[level - 1]);
828: }
829:
830: if(adj->dis_record[level-1].dis==ISIS_IS_DIS)
831: switch (level)
832: {
833: case 1:
834: if (memcmp (circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1))
835: {
836: thread_add_event (master, isis_event_dis_status_change, circuit, 0);
837: memcpy (&circuit->u.bc.l1_desig_is, hdr.lan_id,
838: ISIS_SYS_ID_LEN + 1);
839: }
840: break;
841: case 2:
842: if (memcmp (circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1))
843: {
844: thread_add_event (master, isis_event_dis_status_change, circuit, 0);
845: memcpy (&circuit->u.bc.l2_desig_is, hdr.lan_id,
846: ISIS_SYS_ID_LEN + 1);
847: }
848: break;
849: }
850:
851: adj->hold_time = hdr.hold_time;
852: adj->last_upd = time (NULL);
853: adj->prio[level - 1] = hdr.prio;
854:
855: memcpy (adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
856:
857: /* which protocol are spoken ??? */
858: if (found & TLVFLAG_NLPID)
859: tlvs_to_adj_nlpids (&tlvs, adj);
860:
861: /* we need to copy addresses to the adj */
862: if (found & TLVFLAG_IPV4_ADDR)
863: tlvs_to_adj_ipv4_addrs (&tlvs, adj);
864:
865: #ifdef HAVE_IPV6
866: if (found & TLVFLAG_IPV6_ADDR)
867: tlvs_to_adj_ipv6_addrs (&tlvs, adj);
868: #endif /* HAVE_IPV6 */
869:
870: adj->circuit_t = hdr.circuit_t;
871:
872: /* lets take care of the expiry */
873: THREAD_TIMER_OFF (adj->t_expire);
874: THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
875: (long) adj->hold_time);
876:
877: /*
878: * If the snpa for this circuit is found from LAN Neighbours TLV
879: * we have two-way communication -> adjacency can be put to state "up"
880: */
881:
882: if (found & TLVFLAG_LAN_NEIGHS)
883: {
884: if (adj->adj_state != ISIS_ADJ_UP)
885: {
886: for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa))
887: if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN))
888: {
889: isis_adj_state_change (adj, ISIS_ADJ_UP,
890: "own SNPA found in LAN Neighbours TLV");
891: }
892: }
893: }
894:
895: out:
896: /* DEBUG_ADJ_PACKETS */
897: if (isis->debugs & DEBUG_ADJ_PACKETS)
898: {
899: /* FIXME: is this place right? fix missing info */
900: zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, "
901: "cirID %u, length %ld",
902: circuit->area->area_tag,
903: level, snpa_print (ssnpa), circuit->interface->name,
904: circuit_t2string (circuit->circuit_is_type),
905: circuit->circuit_id,
906: /* FIXME: use %z when we stop supporting old compilers. */
907: (unsigned long) stream_get_endp (circuit->rcv_stream));
908: }
909:
910: free_tlvs (&tlvs);
911:
912: return retval;
913: }
914:
915: /*
916: * Process Level 1/2 Link State
917: * ISO - 10589
918: * Section 7.3.15.1 - Action on receipt of a link state PDU
919: */
920: static int
921: process_lsp (int level, struct isis_circuit *circuit, u_char * ssnpa)
922: {
923: struct isis_link_state_hdr *hdr;
924: struct isis_adjacency *adj = NULL;
925: struct isis_lsp *lsp, *lsp0 = NULL;
926: int retval = ISIS_OK, comp = 0;
927: u_char lspid[ISIS_SYS_ID_LEN + 2];
928: struct isis_passwd *passwd;
929:
930: /* Sanity check - FIXME: move to correct place */
931: if ((stream_get_endp (circuit->rcv_stream) -
932: stream_get_getp (circuit->rcv_stream)) < ISIS_LSP_HDR_LEN)
933: {
934: zlog_warn ("Packet too short");
935: return ISIS_WARNING;
936: }
937:
938: /* Reference the header */
939: hdr = (struct isis_link_state_hdr *) STREAM_PNT (circuit->rcv_stream);
940:
941: if (isis->debugs & DEBUG_UPDATE_PACKETS)
942: {
943: zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, "
944: "lifetime %us, len %lu, on %s",
945: circuit->area->area_tag,
946: level,
947: rawlspid_print (hdr->lsp_id),
948: ntohl (hdr->seq_num),
949: ntohs (hdr->checksum),
950: ntohs (hdr->rem_lifetime),
951: /* FIXME: use %z when we stop supporting old compilers. */
952: (unsigned long) stream_get_endp (circuit->rcv_stream),
953: circuit->interface->name);
954: }
955:
956: assert (ntohs (hdr->pdu_len) > ISIS_LSP_HDR_LEN);
957:
958: /* Checksum sanity check - FIXME: move to correct place */
959: /* 12 = sysid+pdu+remtime */
960: if (iso_csum_verify (STREAM_PNT (circuit->rcv_stream) + 4,
961: ntohs (hdr->pdu_len) - 12, &hdr->checksum))
962: {
963: zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x",
964: circuit->area->area_tag,
965: rawlspid_print (hdr->lsp_id), ntohs (hdr->checksum));
966:
967: return ISIS_WARNING;
968: }
969:
970: /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */
971: if (circuit->ext_domain)
972: {
973: zlog_debug
974: ("ISIS-Upd (%s): LSP %s received at level %d over circuit with "
975: "externalDomain = true", circuit->area->area_tag,
976: rawlspid_print (hdr->lsp_id), level);
977:
978: return ISIS_WARNING;
979: }
980:
981: /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */
982: if (!accept_level (level, circuit->circuit_is_type))
983: {
984: zlog_debug ("ISIS-Upd (%s): LSP %s received at level %d over circuit of"
985: " type %s",
986: circuit->area->area_tag,
987: rawlspid_print (hdr->lsp_id),
988: level, circuit_t2string (circuit->circuit_is_type));
989:
990: return ISIS_WARNING;
991: }
992:
993: /* 7.3.15.1 a) 4 - need to make sure IDLength matches */
994:
995: /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use 3 */
996:
997: /* 7.3.15.1 a) 7 - password check */
998: (level == ISIS_LEVEL1) ? (passwd = &circuit->area->area_passwd) :
999: (passwd = &circuit->area->domain_passwd);
1000: if (passwd->type)
1001: {
1002: if (isis_lsp_authinfo_check (circuit->rcv_stream, circuit->area,
1003: ntohs (hdr->pdu_len), passwd))
1004: {
1005: isis_event_auth_failure (circuit->area->area_tag,
1006: "LSP authentication failure", hdr->lsp_id);
1007: return ISIS_WARNING;
1008: }
1009: }
1010: /* Find the LSP in our database and compare it to this Link State header */
1011: lsp = lsp_search (hdr->lsp_id, circuit->area->lspdb[level - 1]);
1012: if (lsp)
1013: comp = lsp_compare (circuit->area->area_tag, lsp, hdr->seq_num,
1014: hdr->checksum, hdr->rem_lifetime);
1015: if (lsp && (lsp->own_lsp
1016: #ifdef TOPOLOGY_GENERATE
1017: || lsp->from_topology
1018: #endif /* TOPOLOGY_GENERATE */
1019: ))
1020: goto dontcheckadj;
1021:
1022: /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same level */
1023: /* for broadcast circuits, snpa should be compared */
1024: /* FIXME : Point To Point */
1025:
1026: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
1027: {
1028: adj = isis_adj_lookup_snpa (ssnpa, circuit->u.bc.adjdb[level - 1]);
1029: if (!adj)
1030: {
1031: zlog_debug ("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, "
1032: "lifetime %us on %s",
1033: circuit->area->area_tag,
1034: rawlspid_print (hdr->lsp_id),
1035: ntohl (hdr->seq_num),
1036: ntohs (hdr->checksum),
1037: ntohs (hdr->rem_lifetime), circuit->interface->name);
1038: return ISIS_WARNING; /* Silently discard */
1039: }
1040: }
1041:
1042: /* for non broadcast, we just need to find same level adj */
1043: else
1044: {
1045: /* If no adj, or no sharing of level */
1046: if (!circuit->u.p2p.neighbor)
1047: {
1048: return ISIS_OK; /* Silently discard */
1049: }
1050: else
1051: {
1052: if (((level == 1) &&
1053: (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL2)) ||
1054: ((level == 2) &&
1055: (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1)))
1056: return ISIS_WARNING; /* Silently discard */
1057: }
1058: }
1059: dontcheckadj:
1060: /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented */
1061:
1062: /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented */
1063:
1064: /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do it */
1065:
1066: /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */
1067: if (hdr->rem_lifetime == 0)
1068: {
1069: if (!lsp)
1070: {
1071: /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't save */
1072: /* only needed on explicit update, eg - p2p */
1073: if (circuit->circ_type == CIRCUIT_T_P2P)
1074: ack_lsp (hdr, circuit, level);
1075: return retval; /* FIXME: do we need a purge? */
1076: }
1077: else
1078: {
1079: if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
1080: {
1081: /* LSP by some other system -> do 7.3.16.4 b) */
1082: /* 7.3.16.4 b) 1) */
1083: if (comp == LSP_NEWER)
1084: {
1085: lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area,
1086: level);
1087: /* ii */
1088: ISIS_FLAGS_SET_ALL (lsp->SRMflags);
1089: /* iii */
1090: ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
1091: /* v */
1092: ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */
1093: /* iv */
1094: if (circuit->circ_type != CIRCUIT_T_BROADCAST)
1095: ISIS_SET_FLAG (lsp->SSNflags, circuit);
1096:
1097: } /* 7.3.16.4 b) 2) */
1098: else if (comp == LSP_EQUAL)
1099: {
1100: /* i */
1101: ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
1102: /* ii */
1103: if (circuit->circ_type != CIRCUIT_T_BROADCAST)
1104: ISIS_SET_FLAG (lsp->SSNflags, circuit);
1105: } /* 7.3.16.4 b) 3) */
1106: else
1107: {
1108: ISIS_SET_FLAG (lsp->SRMflags, circuit);
1109: ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
1110: }
1111: }
1112: else
1113: {
1114: /* our own LSP -> 7.3.16.4 c) */
1115: if (LSP_PSEUDO_ID (lsp->lsp_header->lsp_id) !=
1116: circuit->circuit_id
1117: || (LSP_PSEUDO_ID (lsp->lsp_header->lsp_id) ==
1118: circuit->circuit_id
1119: && circuit->u.bc.is_dr[level - 1] == 1))
1120: {
1121: lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1);
1122: if (isis->debugs & DEBUG_UPDATE_PACKETS)
1123: zlog_debug ("LSP LEN: %d",
1124: ntohs (lsp->lsp_header->pdu_len));
1125: fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
1126: ntohs (lsp->lsp_header->pdu_len) - 12, 12);
1127: ISIS_FLAGS_SET_ALL (lsp->SRMflags);
1128: if (isis->debugs & DEBUG_UPDATE_PACKETS)
1129: zlog_debug ("ISIS-Upd (%s): (1) re-originating LSP %s new "
1130: "seq 0x%08x", circuit->area->area_tag,
1131: rawlspid_print (hdr->lsp_id),
1132: ntohl (lsp->lsp_header->seq_num));
1133: lsp->lsp_header->rem_lifetime =
1134: htons (isis_jitter
1135: (circuit->area->max_lsp_lifetime[level - 1],
1136: MAX_AGE_JITTER));
1137: }
1138: else
1139: {
1140: /* Got purge for own pseudo-lsp, and we are not DR */
1141: lsp_purge_dr (lsp->lsp_header->lsp_id, circuit, level);
1142: }
1143: }
1144: }
1145: return retval;
1146: }
1147: /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a
1148: * purge */
1149: if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
1150: {
1151: if (!lsp)
1152: {
1153: /* 7.3.16.4: initiate a purge */
1154: lsp_purge_non_exist (hdr, circuit->area);
1155: return ISIS_OK;
1156: }
1157: /* 7.3.15.1 d) - If this is our own lsp and we have it */
1158:
1159: /* In 7.3.16.1, If an Intermediate system R somewhere in the domain
1160: * has information that the current sequence number for source S is
1161: * "greater" than that held by S, ... */
1162:
1163: else if (ntohl (hdr->seq_num) > ntohl (lsp->lsp_header->seq_num))
1164: {
1165: /* 7.3.16.1 */
1166: lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1);
1167:
1168: fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
1169: ntohs (lsp->lsp_header->pdu_len) - 12, 12);
1170:
1171: ISIS_FLAGS_SET_ALL (lsp->SRMflags);
1172: if (isis->debugs & DEBUG_UPDATE_PACKETS)
1173: zlog_debug ("ISIS-Upd (%s): (2) re-originating LSP %s new seq "
1174: "0x%08x", circuit->area->area_tag,
1175: rawlspid_print (hdr->lsp_id),
1176: ntohl (lsp->lsp_header->seq_num));
1177: lsp->lsp_header->rem_lifetime =
1178: htons (isis_jitter
1179: (circuit->area->max_lsp_lifetime[level - 1],
1180: MAX_AGE_JITTER));
1181: }
1182: }
1183: else
1184: {
1185: /* 7.3.15.1 e) - This lsp originated on another system */
1186:
1187: /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */
1188: if ((!lsp || comp == LSP_NEWER))
1189: {
1190: /* i */
1191: if (lsp)
1192: {
1193: #ifdef EXTREME_DEBUG
1194: zlog_debug ("level %d number is - %ld", level,
1195: circuit->area->lspdb[level - 1]->dict_nodecount);
1196: #endif /* EXTREME DEBUG */
1197: lsp_search_and_destroy (hdr->lsp_id,
1198: circuit->area->lspdb[level - 1]);
1199: /* exists, so we overwrite */
1200: #ifdef EXTREME_DEBUG
1201: zlog_debug ("level %d number is - %ld", level,
1202: circuit->area->lspdb[level - 1]->dict_nodecount);
1203: #endif /* EXTREME DEBUG */
1204: }
1205: /*
1206: * If this lsp is a frag, need to see if we have zero lsp present
1207: */
1208: if (LSP_FRAGMENT (hdr->lsp_id) != 0)
1209: {
1210: memcpy (lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1);
1211: LSP_FRAGMENT (lspid) = 0;
1212: lsp0 = lsp_search (lspid, circuit->area->lspdb[level - 1]);
1213: if (!lsp0)
1214: {
1215: zlog_debug ("Got lsp frag, while zero lsp not database");
1216: return ISIS_OK;
1217: }
1218: }
1219: lsp =
1220: lsp_new_from_stream_ptr (circuit->rcv_stream,
1221: ntohs (hdr->pdu_len), lsp0,
1222: circuit->area);
1223: lsp->level = level;
1224: lsp->adj = adj;
1225: lsp_insert (lsp, circuit->area->lspdb[level - 1]);
1226: /* ii */
1227: ISIS_FLAGS_SET_ALL (lsp->SRMflags);
1228: /* iii */
1229: ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
1230:
1231: /* iv */
1232: if (circuit->circ_type != CIRCUIT_T_BROADCAST)
1233: ISIS_SET_FLAG (lsp->SSNflags, circuit);
1234: /* FIXME: v) */
1235: }
1236: /* 7.3.15.1 e) 2) LSP equal to the one in db */
1237: else if (comp == LSP_EQUAL)
1238: {
1239: ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
1240: lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area, level);
1241: if (circuit->circ_type != CIRCUIT_T_BROADCAST)
1242: {
1243: ISIS_SET_FLAG (lsp->SSNflags, circuit);
1244: }
1245: }
1246: /* 7.3.15.1 e) 3) LSP older than the one in db */
1247: else
1248: {
1249: ISIS_SET_FLAG (lsp->SRMflags, circuit);
1250: ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
1251: }
1252: }
1253: if (lsp)
1254: lsp->adj = adj;
1255: return retval;
1256: }
1257:
1258: /*
1259: * Process Sequence Numbers
1260: * ISO - 10589
1261: * Section 7.3.15.2 - Action on receipt of a sequence numbers PDU
1262: */
1263:
1264: static int
1265: process_snp (int snp_type, int level, struct isis_circuit *circuit,
1266: u_char * ssnpa)
1267: {
1268: int retval = ISIS_OK;
1269: int cmp, own_lsp;
1270: char typechar = ' ';
1271: int len;
1272: struct isis_adjacency *adj;
1273: struct isis_complete_seqnum_hdr *chdr = NULL;
1274: struct isis_partial_seqnum_hdr *phdr = NULL;
1275: uint32_t found = 0, expected = 0;
1276: struct isis_lsp *lsp;
1277: struct lsp_entry *entry;
1278: struct listnode *node, *nnode;
1279: struct listnode *node2, *nnode2;
1280: struct tlvs tlvs;
1281: struct list *lsp_list = NULL;
1282: struct isis_passwd *passwd;
1283:
1284: if (snp_type == ISIS_SNP_CSNP_FLAG)
1285: {
1286: /* getting the header info */
1287: typechar = 'C';
1288: chdr =
1289: (struct isis_complete_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream);
1290: circuit->rcv_stream->getp += ISIS_CSNP_HDRLEN;
1291: len = ntohs (chdr->pdu_len);
1292: if (len < ISIS_CSNP_HDRLEN)
1293: {
1294: zlog_warn ("Received a CSNP with bogus length!");
1295: return ISIS_OK;
1296: }
1297: }
1298: else
1299: {
1300: typechar = 'P';
1301: phdr =
1302: (struct isis_partial_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream);
1303: circuit->rcv_stream->getp += ISIS_PSNP_HDRLEN;
1304: len = ntohs (phdr->pdu_len);
1305: if (len < ISIS_PSNP_HDRLEN)
1306: {
1307: zlog_warn ("Received a CSNP with bogus length!");
1308: return ISIS_OK;
1309: }
1310: }
1311:
1312: /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */
1313: if (circuit->ext_domain)
1314: {
1315:
1316: zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
1317: "skipping: circuit externalDomain = true",
1318: circuit->area->area_tag,
1319: level, typechar, circuit->interface->name);
1320:
1321: return ISIS_OK;
1322: }
1323:
1324: /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */
1325: if (!accept_level (level, circuit->circuit_is_type))
1326: {
1327:
1328: zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
1329: "skipping: circuit type %s does not match level %d",
1330: circuit->area->area_tag,
1331: level,
1332: typechar,
1333: circuit->interface->name,
1334: circuit_t2string (circuit->circuit_is_type), level);
1335:
1336: return ISIS_OK;
1337: }
1338:
1339: /* 7.3.15.2 a) 4 - not applicable for CSNP only PSNPs on broadcast */
1340: if ((snp_type == ISIS_SNP_PSNP_FLAG) &&
1341: (circuit->circ_type == CIRCUIT_T_BROADCAST))
1342: {
1343: if (!circuit->u.bc.is_dr[level - 1])
1344: {
1345:
1346: zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, "
1347: "skipping: we are not the DIS",
1348: circuit->area->area_tag,
1349: level,
1350: typechar, snpa_print (ssnpa), circuit->interface->name);
1351:
1352: return ISIS_OK;
1353: }
1354: }
1355:
1356: /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked */
1357:
1358: /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use 3
1359: * - already checked */
1360:
1361: /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same level */
1362: /* for broadcast circuits, snpa should be compared */
1363: /* FIXME : Do we need to check SNPA? */
1364: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
1365: {
1366: if (snp_type == ISIS_SNP_CSNP_FLAG)
1367: {
1368: adj =
1369: isis_adj_lookup (chdr->source_id, circuit->u.bc.adjdb[level - 1]);
1370: }
1371: else
1372: {
1373: /* a psnp on a broadcast, how lovely of Juniper :) */
1374: adj =
1375: isis_adj_lookup (phdr->source_id, circuit->u.bc.adjdb[level - 1]);
1376: }
1377: if (!adj)
1378: return ISIS_OK; /* Silently discard */
1379: }
1380: else
1381: {
1382: if (!circuit->u.p2p.neighbor)
1383: return ISIS_OK; /* Silently discard */
1384: }
1385:
1386: /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented */
1387:
1388: /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented */
1389:
1390: memset (&tlvs, 0, sizeof (struct tlvs));
1391:
1392: /* parse the SNP */
1393: expected |= TLVFLAG_LSP_ENTRIES;
1394: expected |= TLVFLAG_AUTH_INFO;
1395: retval = parse_tlvs (circuit->area->area_tag,
1396: STREAM_PNT (circuit->rcv_stream),
1397: len - circuit->rcv_stream->getp,
1398: &expected, &found, &tlvs);
1399:
1400: if (retval > ISIS_WARNING)
1401: {
1402: zlog_warn ("something went very wrong processing SNP");
1403: free_tlvs (&tlvs);
1404: return retval;
1405: }
1406:
1407: if (level == 1)
1408: passwd = &circuit->area->area_passwd;
1409: else
1410: passwd = &circuit->area->domain_passwd;
1411:
1412: if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV))
1413: {
1414: if (passwd->type)
1415: {
1416: if (!(found & TLVFLAG_AUTH_INFO) ||
1417: authentication_check (passwd, &tlvs.auth_info))
1418: {
1419: isis_event_auth_failure (circuit->area->area_tag,
1420: "SNP authentication" " failure",
1421: phdr ? phdr->source_id : chdr->source_id);
1422: return ISIS_OK;
1423: }
1424: }
1425: }
1426:
1427: /* debug isis snp-packets */
1428: if (isis->debugs & DEBUG_SNP_PACKETS)
1429: {
1430: zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s",
1431: circuit->area->area_tag,
1432: level,
1433: typechar, snpa_print (ssnpa), circuit->interface->name);
1434: if (tlvs.lsp_entries)
1435: {
1436: for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry))
1437: {
1438: zlog_debug ("ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x,"
1439: " cksum 0x%04x, lifetime %us",
1440: circuit->area->area_tag,
1441: typechar,
1442: rawlspid_print (entry->lsp_id),
1443: ntohl (entry->seq_num),
1444: ntohs (entry->checksum), ntohs (entry->rem_lifetime));
1445: }
1446: }
1447: }
1448:
1449: /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */
1450: if (tlvs.lsp_entries)
1451: {
1452: for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry))
1453: {
1454: lsp = lsp_search (entry->lsp_id, circuit->area->lspdb[level - 1]);
1455: own_lsp = !memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
1456: if (lsp)
1457: {
1458: /* 7.3.15.2 b) 1) is this LSP newer */
1459: cmp = lsp_compare (circuit->area->area_tag, lsp, entry->seq_num,
1460: entry->checksum, entry->rem_lifetime);
1461: /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */
1462: if (cmp == LSP_EQUAL)
1463: {
1464: if (circuit->circ_type != CIRCUIT_T_BROADCAST)
1465: ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
1466: /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM */
1467: }
1468: else if (cmp == LSP_OLDER)
1469: {
1470: ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
1471: ISIS_SET_FLAG (lsp->SRMflags, circuit);
1472: }
1473: else
1474: {
1475: /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM
1476: * on p2p */
1477: if (own_lsp)
1478: {
1479: lsp_inc_seqnum (lsp, ntohl (entry->seq_num));
1480: ISIS_SET_FLAG (lsp->SRMflags, circuit);
1481: }
1482: else
1483: {
1484: ISIS_SET_FLAG (lsp->SSNflags, circuit);
1485: if (circuit->circ_type != CIRCUIT_T_BROADCAST)
1486: ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
1487: }
1488: }
1489: }
1490: else
1491: {
1492: /* 7.3.15.2 b) 5) if it was not found, and all of those are not 0,
1493: * insert it and set SSN on it */
1494: if (entry->rem_lifetime && entry->checksum && entry->seq_num &&
1495: memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
1496: {
1497: lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime),
1498: 0, 0, entry->checksum, level);
1499: lsp_insert (lsp, circuit->area->lspdb[level - 1]);
1500: ISIS_SET_FLAG (lsp->SSNflags, circuit);
1501: }
1502: }
1503: }
1504: }
1505:
1506: /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported */
1507: if (snp_type == ISIS_SNP_CSNP_FLAG)
1508: {
1509: /*
1510: * Build a list from our own LSP db bounded with start_ and stop_lsp_id
1511: */
1512: lsp_list = list_new ();
1513: lsp_build_list_nonzero_ht (chdr->start_lsp_id, chdr->stop_lsp_id,
1514: lsp_list, circuit->area->lspdb[level - 1]);
1515:
1516: /* Fixme: Find a better solution */
1517: if (tlvs.lsp_entries)
1518: {
1519: for (ALL_LIST_ELEMENTS (tlvs.lsp_entries, node, nnode, entry))
1520: {
1521: for (ALL_LIST_ELEMENTS (lsp_list, node2, nnode2, lsp))
1522: {
1523: if (lsp_id_cmp (lsp->lsp_header->lsp_id, entry->lsp_id) == 0)
1524: {
1525: list_delete_node (lsp_list, node2);
1526: break;
1527: }
1528: }
1529: }
1530: }
1531: /* on remaining LSPs we set SRM (neighbor knew not of) */
1532: for (ALL_LIST_ELEMENTS_RO (lsp_list, node, lsp))
1533: {
1534: ISIS_SET_FLAG (lsp->SRMflags, circuit);
1535: }
1536: /* lets free it */
1537: list_free (lsp_list);
1538: }
1539:
1540: free_tlvs (&tlvs);
1541: return retval;
1542: }
1543:
1544: static int
1545: process_csnp (int level, struct isis_circuit *circuit, u_char * ssnpa)
1546: {
1547: /* Sanity check - FIXME: move to correct place */
1548: if ((stream_get_endp (circuit->rcv_stream) -
1549: stream_get_getp (circuit->rcv_stream)) < ISIS_CSNP_HDRLEN)
1550: {
1551: zlog_warn ("Packet too short ( < %d)", ISIS_CSNP_HDRLEN);
1552: return ISIS_WARNING;
1553: }
1554:
1555: return process_snp (ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa);
1556: }
1557:
1558: static int
1559: process_psnp (int level, struct isis_circuit *circuit, u_char * ssnpa)
1560: {
1561: if ((stream_get_endp (circuit->rcv_stream) -
1562: stream_get_getp (circuit->rcv_stream)) < ISIS_PSNP_HDRLEN)
1563: {
1564: zlog_warn ("Packet too short");
1565: return ISIS_WARNING;
1566: }
1567:
1568: return process_snp (ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa);
1569: }
1570:
1571: /*
1572: * Process ISH
1573: * ISO - 10589
1574: * Section 8.2.2 - Receiving ISH PDUs by an intermediate system
1575: * FIXME: sample packet dump, need to figure 0x81 - looks like NLPid
1576: * 0x82 0x15 0x01 0x00 0x04 0x01 0x2c 0x59
1577: * 0x38 0x08 0x47 0x00 0x01 0x00 0x02 0x00
1578: * 0x03 0x00 0x81 0x01 0xcc
1579: */
1580: static int
1581: process_is_hello (struct isis_circuit *circuit)
1582: {
1583: struct isis_adjacency *adj;
1584: int retval = ISIS_OK;
1585: u_char neigh_len;
1586: u_char *sysid;
1587:
1588: /* In this point in time we are not yet able to handle is_hellos
1589: * on lan - Sorry juniper...
1590: */
1591: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
1592: return retval;
1593:
1594: neigh_len = stream_getc (circuit->rcv_stream);
1595: sysid = STREAM_PNT (circuit->rcv_stream) + neigh_len - 1 - ISIS_SYS_ID_LEN;
1596: adj = circuit->u.p2p.neighbor;
1597: if (!adj)
1598: {
1599: /* 8.2.2 */
1600: adj = isis_new_adj (sysid, NULL, 0, circuit);
1601: if (adj == NULL)
1602: return ISIS_ERROR;
1603:
1604: isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
1605: adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
1606: circuit->u.p2p.neighbor = adj;
1607: }
1608: /* 8.2.2 a) */
1609: if ((adj->adj_state == ISIS_ADJ_UP) && memcmp (adj->sysid, sysid,
1610: ISIS_SYS_ID_LEN))
1611: {
1612: /* 8.2.2 a) 1) FIXME: adjStateChange(down) event */
1613: /* 8.2.2 a) 2) delete the adj */
1614: XFREE (MTYPE_ISIS_ADJACENCY, adj);
1615: /* 8.2.2 a) 3) create a new adj */
1616: adj = isis_new_adj (sysid, NULL, 0, circuit);
1617: if (adj == NULL)
1618: return ISIS_ERROR;
1619:
1620: /* 8.2.2 a) 3) i */
1621: isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
1622: /* 8.2.2 a) 3) ii */
1623: adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
1624: /* 8.2.2 a) 4) quite meaningless */
1625: }
1626: /* 8.2.2 b) ignore on condition */
1627: if ((adj->adj_state == ISIS_ADJ_INITIALIZING) &&
1628: (adj->sys_type == ISIS_SYSTYPE_IS))
1629: {
1630: /* do nothing */
1631: }
1632: else
1633: {
1634: /* 8.2.2 c) respond with a p2p IIH */
1635: send_hello (circuit, 1);
1636: }
1637: /* 8.2.2 d) type is IS */
1638: adj->sys_type = ISIS_SYSTYPE_IS;
1639: /* 8.2.2 e) FIXME: Circuit type of? */
1640:
1641: return retval;
1642: }
1643:
1644: /*
1645: * PDU Dispatcher
1646: */
1647:
1648: static int
1649: isis_handle_pdu (struct isis_circuit *circuit, u_char * ssnpa)
1650: {
1651: struct isis_fixed_hdr *hdr;
1652: struct esis_fixed_hdr *esis_hdr;
1653:
1654: int retval = ISIS_OK;
1655:
1656: /*
1657: * Let's first read data from stream to the header
1658: */
1659: hdr = (struct isis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream);
1660:
1661: if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS))
1662: {
1663: zlog_warn ("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp);
1664: return ISIS_ERROR;
1665: }
1666:
1667: /* now we need to know if this is an ISO 9542 packet and
1668: * take real good care of it, waaa!
1669: */
1670: if (hdr->idrp == ISO9542_ESIS)
1671: {
1672: esis_hdr = (struct esis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream);
1673: stream_set_getp (circuit->rcv_stream, ESIS_FIXED_HDR_LEN);
1674: /* FIXME: Need to do some acceptence tests */
1675: /* example length... */
1676: switch (esis_hdr->pdu_type)
1677: {
1678: case ESH_PDU:
1679: /* FIXME */
1680: break;
1681: case ISH_PDU:
1682: zlog_debug ("AN ISH PDU!!");
1683: retval = process_is_hello (circuit);
1684: break;
1685: default:
1686: return ISIS_ERROR;
1687: }
1688: return retval;
1689: }
1690: else
1691: {
1692: stream_set_getp (circuit->rcv_stream, ISIS_FIXED_HDR_LEN);
1693: }
1694: /*
1695: * and then process it
1696: */
1697:
1698: if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN)
1699: {
1700: zlog_err ("Fixed header length = %d", hdr->length);
1701: return ISIS_ERROR;
1702: }
1703:
1704: if (hdr->version1 != 1)
1705: {
1706: zlog_warn ("Unsupported ISIS version %u", hdr->version1);
1707: return ISIS_WARNING;
1708: }
1709: /* either 6 or 0 */
1710: if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN))
1711: {
1712: zlog_err
1713: ("IDFieldLengthMismatch: ID Length field in a received PDU %u, "
1714: "while the parameter for this IS is %u", hdr->id_len,
1715: ISIS_SYS_ID_LEN);
1716: return ISIS_ERROR;
1717: }
1718:
1719: if (hdr->version2 != 1)
1720: {
1721: zlog_warn ("Unsupported ISIS version %u", hdr->version2);
1722: return ISIS_WARNING;
1723: }
1724: /* either 3 or 0 */
1725: if ((hdr->max_area_addrs != 0)
1726: && (hdr->max_area_addrs != isis->max_area_addrs))
1727: {
1728: zlog_err ("maximumAreaAddressesMismatch: maximumAreaAdresses in a "
1729: "received PDU %u while the parameter for this IS is %u",
1730: hdr->max_area_addrs, isis->max_area_addrs);
1731: return ISIS_ERROR;
1732: }
1733:
1734: switch (hdr->pdu_type)
1735: {
1736: case L1_LAN_HELLO:
1737: retval = process_lan_hello (ISIS_LEVEL1, circuit, ssnpa);
1738: break;
1739: case L2_LAN_HELLO:
1740: retval = process_lan_hello (ISIS_LEVEL2, circuit, ssnpa);
1741: break;
1742: case P2P_HELLO:
1743: retval = process_p2p_hello (circuit);
1744: break;
1745: case L1_LINK_STATE:
1746: retval = process_lsp (ISIS_LEVEL1, circuit, ssnpa);
1747: break;
1748: case L2_LINK_STATE:
1749: retval = process_lsp (ISIS_LEVEL2, circuit, ssnpa);
1750: break;
1751: case L1_COMPLETE_SEQ_NUM:
1752: retval = process_csnp (ISIS_LEVEL1, circuit, ssnpa);
1753: break;
1754: case L2_COMPLETE_SEQ_NUM:
1755: retval = process_csnp (ISIS_LEVEL2, circuit, ssnpa);
1756: break;
1757: case L1_PARTIAL_SEQ_NUM:
1758: retval = process_psnp (ISIS_LEVEL1, circuit, ssnpa);
1759: break;
1760: case L2_PARTIAL_SEQ_NUM:
1761: retval = process_psnp (ISIS_LEVEL2, circuit, ssnpa);
1762: break;
1763: default:
1764: return ISIS_ERROR;
1765: }
1766:
1767: return retval;
1768: }
1769:
1770: #ifdef GNU_LINUX
1771: int
1772: isis_receive (struct thread *thread)
1773: {
1774: struct isis_circuit *circuit;
1775: u_char ssnpa[ETH_ALEN];
1776: int retval;
1777:
1778: /*
1779: * Get the circuit
1780: */
1781: circuit = THREAD_ARG (thread);
1782: assert (circuit);
1783:
1784: if (!circuit->area)
1785: return ISIS_OK;
1786:
1787: if (circuit->rcv_stream == NULL)
1788: circuit->rcv_stream = stream_new (ISO_MTU (circuit));
1789: else
1790: stream_reset (circuit->rcv_stream);
1791:
1792: retval = circuit->rx (circuit, ssnpa);
1793: circuit->t_read = NULL;
1794:
1795: if (retval == ISIS_OK)
1796: retval = isis_handle_pdu (circuit, ssnpa);
1797:
1798: /*
1799: * prepare for next packet.
1800: */
1801: THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
1802: circuit->fd);
1803:
1804: return retval;
1805: }
1806:
1807: #else
1808: int
1809: isis_receive (struct thread *thread)
1810: {
1811: struct isis_circuit *circuit;
1812: u_char ssnpa[ETH_ALEN];
1813: int retval;
1814:
1815: /*
1816: * Get the circuit
1817: */
1818: circuit = THREAD_ARG (thread);
1819: assert (circuit);
1820:
1821: circuit->t_read = NULL;
1822:
1823: if (circuit->rcv_stream == NULL)
1824: circuit->rcv_stream = stream_new (ISO_MTU (circuit));
1825: else
1826: stream_reset (circuit->rcv_stream);
1827:
1828: retval = circuit->rx (circuit, ssnpa);
1829:
1830: if (retval == ISIS_OK)
1831: retval = isis_handle_pdu (circuit, ssnpa);
1832:
1833: /*
1834: * prepare for next packet.
1835: */
1836: circuit->t_read = thread_add_timer_msec (master, isis_receive, circuit,
1837: listcount
1838: (circuit->area->circuit_list) *
1839: 100);
1840:
1841: return retval;
1842: }
1843:
1844: #endif
1845:
1846: /* filling of the fixed isis header */
1847: void
1848: fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type)
1849: {
1850: memset (hdr, 0, sizeof (struct isis_fixed_hdr));
1851:
1852: hdr->idrp = ISO10589_ISIS;
1853:
1854: switch (pdu_type)
1855: {
1856: case L1_LAN_HELLO:
1857: case L2_LAN_HELLO:
1858: hdr->length = ISIS_LANHELLO_HDRLEN;
1859: break;
1860: case P2P_HELLO:
1861: hdr->length = ISIS_P2PHELLO_HDRLEN;
1862: break;
1863: case L1_LINK_STATE:
1864: case L2_LINK_STATE:
1865: hdr->length = ISIS_LSP_HDR_LEN;
1866: break;
1867: case L1_COMPLETE_SEQ_NUM:
1868: case L2_COMPLETE_SEQ_NUM:
1869: hdr->length = ISIS_CSNP_HDRLEN;
1870: break;
1871: case L1_PARTIAL_SEQ_NUM:
1872: case L2_PARTIAL_SEQ_NUM:
1873: hdr->length = ISIS_PSNP_HDRLEN;
1874: break;
1875: default:
1876: zlog_warn ("fill_fixed_hdr(): unknown pdu type %d", pdu_type);
1877: return;
1878: }
1879: hdr->length += ISIS_FIXED_HDR_LEN;
1880: hdr->pdu_type = pdu_type;
1881: hdr->version1 = 1;
1882: hdr->id_len = 0; /* ISIS_SYS_ID_LEN - 0==6 */
1883: hdr->version2 = 1;
1884: hdr->max_area_addrs = 0; /* isis->max_area_addrs - 0==3 */
1885: }
1886:
1887: /*
1888: * SEND SIDE
1889: */
1890: static void
1891: fill_fixed_hdr_andstream (struct isis_fixed_hdr *hdr, u_char pdu_type,
1892: struct stream *stream)
1893: {
1894: fill_fixed_hdr (hdr, pdu_type);
1895:
1896: stream_putc (stream, hdr->idrp);
1897: stream_putc (stream, hdr->length);
1898: stream_putc (stream, hdr->version1);
1899: stream_putc (stream, hdr->id_len);
1900: stream_putc (stream, hdr->pdu_type);
1901: stream_putc (stream, hdr->version2);
1902: stream_putc (stream, hdr->reserved);
1903: stream_putc (stream, hdr->max_area_addrs);
1904:
1905: return;
1906: }
1907:
1908: int
1909: send_hello (struct isis_circuit *circuit, int level)
1910: {
1911: struct isis_fixed_hdr fixed_hdr;
1912: struct isis_lan_hello_hdr hello_hdr;
1913: struct isis_p2p_hello_hdr p2p_hello_hdr;
1914:
1915: u_int32_t interval;
1916: unsigned long len_pointer, length;
1917: int retval;
1918:
1919: if (circuit->interface->mtu == 0)
1920: {
1921: zlog_warn ("circuit has zero MTU");
1922: return ISIS_WARNING;
1923: }
1924:
1925: if (!circuit->snd_stream)
1926: circuit->snd_stream = stream_new (ISO_MTU (circuit));
1927: else
1928: stream_reset (circuit->snd_stream);
1929:
1930: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
1931: if (level == 1)
1932: fill_fixed_hdr_andstream (&fixed_hdr, L1_LAN_HELLO,
1933: circuit->snd_stream);
1934: else
1935: fill_fixed_hdr_andstream (&fixed_hdr, L2_LAN_HELLO,
1936: circuit->snd_stream);
1937: else
1938: fill_fixed_hdr_andstream (&fixed_hdr, P2P_HELLO, circuit->snd_stream);
1939:
1940: /*
1941: * Fill LAN Level 1 or 2 Hello PDU header
1942: */
1943: memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr));
1944: interval = circuit->hello_multiplier[level - 1] *
1945: circuit->hello_interval[level - 1];
1946: /* If we are the DIS then hello interval is divided by three, as is the hold-timer */
1947: if (circuit->u.bc.is_dr[level - 1])
1948: interval=interval/3;
1949: if (interval > USHRT_MAX)
1950: interval = USHRT_MAX;
1951: hello_hdr.circuit_t = circuit->circuit_is_type;
1952: memcpy (hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN);
1953: hello_hdr.hold_time = htons ((u_int16_t) interval);
1954:
1955: hello_hdr.pdu_len = 0; /* Update the PDU Length later */
1956: len_pointer = stream_get_endp (circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN;
1957:
1958: /* copy the shared part of the hello to the p2p hello if needed */
1959: if (circuit->circ_type == CIRCUIT_T_P2P)
1960: {
1961: memcpy (&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN);
1962: p2p_hello_hdr.local_id = circuit->circuit_id;
1963: /* FIXME: need better understanding */
1964: stream_put (circuit->snd_stream, &p2p_hello_hdr, ISIS_P2PHELLO_HDRLEN);
1965: }
1966: else
1967: {
1968: hello_hdr.prio = circuit->u.bc.priority[level - 1];
1969: if (level == 1 && circuit->u.bc.l1_desig_is)
1970: {
1971: memcpy (hello_hdr.lan_id, circuit->u.bc.l1_desig_is,
1972: ISIS_SYS_ID_LEN + 1);
1973: }
1974: else if (level == 2 && circuit->u.bc.l2_desig_is)
1975: {
1976: memcpy (hello_hdr.lan_id, circuit->u.bc.l2_desig_is,
1977: ISIS_SYS_ID_LEN + 1);
1978: }
1979: stream_put (circuit->snd_stream, &hello_hdr, ISIS_LANHELLO_HDRLEN);
1980: }
1981:
1982: /*
1983: * Then the variable length part
1984: */
1985: /* add circuit password */
1986: if (circuit->passwd.type)
1987: if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len,
1988: circuit->passwd.passwd, circuit->snd_stream))
1989: return ISIS_WARNING;
1990: /* Area Addresses TLV */
1991: assert (circuit->area);
1992: if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0)
1993: if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream))
1994: return ISIS_WARNING;
1995:
1996: /* LAN Neighbors TLV */
1997: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
1998: {
1999: if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0)
2000: if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0],
2001: circuit->snd_stream))
2002: return ISIS_WARNING;
2003: if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0)
2004: if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1],
2005: circuit->snd_stream))
2006: return ISIS_WARNING;
2007: }
2008:
2009: /* Protocols Supported TLV */
2010: if (circuit->nlpids.count > 0)
2011: if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream))
2012: return ISIS_WARNING;
2013: /* IP interface Address TLV */
2014: if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0)
2015: if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream))
2016: return ISIS_WARNING;
2017:
2018: #ifdef HAVE_IPV6
2019: /* IPv6 Interface Address TLV */
2020: if (circuit->ipv6_router && circuit->ipv6_link &&
2021: circuit->ipv6_link->count > 0)
2022: if (tlv_add_ipv6_addrs (circuit->ipv6_link, circuit->snd_stream))
2023: return ISIS_WARNING;
2024: #endif /* HAVE_IPV6 */
2025:
2026: if (circuit->u.bc.pad_hellos)
2027: if (tlv_add_padding (circuit->snd_stream))
2028: return ISIS_WARNING;
2029:
2030: length = stream_get_endp (circuit->snd_stream);
2031: /* Update PDU length */
2032: stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length);
2033:
2034: retval = circuit->tx (circuit, level);
2035: if (retval)
2036: zlog_warn ("sending of LAN Level %d Hello failed", level);
2037:
2038: /* DEBUG_ADJ_PACKETS */
2039: if (isis->debugs & DEBUG_ADJ_PACKETS)
2040: {
2041: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
2042: {
2043: zlog_debug ("ISIS-Adj (%s): Sent L%d LAN IIH on %s, length %ld",
2044: circuit->area->area_tag, level, circuit->interface->name,
2045: /* FIXME: use %z when we stop supporting old compilers. */
2046: (unsigned long) STREAM_SIZE (circuit->snd_stream));
2047: }
2048: else
2049: {
2050: zlog_debug ("ISIS-Adj (%s): Sent P2P IIH on %s, length %ld",
2051: circuit->area->area_tag, circuit->interface->name,
2052: /* FIXME: use %z when we stop supporting old compilers. */
2053: (unsigned long) STREAM_SIZE (circuit->snd_stream));
2054: }
2055: }
2056:
2057: return retval;
2058: }
2059:
2060: static int
2061: send_lan_hello (struct isis_circuit *circuit, int level)
2062: {
2063: return send_hello (circuit, level);
2064: }
2065:
2066: int
2067: send_lan_l1_hello (struct thread *thread)
2068: {
2069: struct isis_circuit *circuit;
2070: int retval;
2071: unsigned long next_hello;
2072:
2073: circuit = THREAD_ARG (thread);
2074: assert (circuit);
2075:
2076: if (!circuit->area) {
2077: return ISIS_OK;
2078: }
2079:
2080: /* Pseudonode sends hellos three times more than the other nodes */
2081: if (circuit->u.bc.is_dr[0])
2082: next_hello=circuit->hello_interval[0]/3+1;
2083: else
2084: next_hello=circuit->hello_interval[0];
2085:
2086: circuit->u.bc.t_send_lan_hello[0] = NULL;
2087:
2088: if (circuit->u.bc.run_dr_elect[0])
2089: retval = isis_dr_elect (circuit, 1);
2090:
2091: retval = send_lan_hello (circuit, 1);
2092:
2093: /* set next timer thread */
2094: THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0],
2095: send_lan_l1_hello, circuit,
2096: isis_jitter (next_hello, IIH_JITTER));
2097:
2098: return retval;
2099: }
2100:
2101: int
2102: send_lan_l2_hello (struct thread *thread)
2103: {
2104: struct isis_circuit *circuit;
2105: int retval;
2106: unsigned long next_hello;
2107:
2108: circuit = THREAD_ARG (thread);
2109: assert (circuit);
2110:
2111: if (!circuit->area) {
2112: return ISIS_OK;
2113: }
2114:
2115: /* Pseudonode sends hellos three times more than the other nodes */
2116: if (circuit->u.bc.is_dr[1])
2117: next_hello=circuit->hello_interval[1]/3+1;
2118: else
2119: next_hello=circuit->hello_interval[1];
2120:
2121: circuit->u.bc.t_send_lan_hello[1] = NULL;
2122:
2123: if (circuit->u.bc.run_dr_elect[1])
2124: retval = isis_dr_elect (circuit, 2);
2125:
2126: retval = send_lan_hello (circuit, 2);
2127:
2128: /* set next timer thread */
2129: THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[1],
2130: send_lan_l2_hello, circuit,
2131: isis_jitter (next_hello, IIH_JITTER));
2132:
2133: return retval;
2134: }
2135:
2136: int
2137: send_p2p_hello (struct thread *thread)
2138: {
2139: struct isis_circuit *circuit;
2140:
2141: circuit = THREAD_ARG (thread);
2142: assert (circuit);
2143: circuit->u.p2p.t_send_p2p_hello = NULL;
2144:
2145: send_hello (circuit, 1);
2146:
2147: /* set next timer thread */
2148: THREAD_TIMER_ON (master, circuit->u.p2p.t_send_p2p_hello, send_p2p_hello,
2149: circuit, isis_jitter (circuit->hello_interval[1],
2150: IIH_JITTER));
2151:
2152: return ISIS_OK;
2153: }
2154:
2155: static int
2156: build_csnp (int level, u_char * start, u_char * stop, struct list *lsps,
2157: struct isis_circuit *circuit)
2158: {
2159: struct isis_fixed_hdr fixed_hdr;
2160: struct isis_passwd *passwd;
2161: int retval = ISIS_OK;
2162: unsigned long lenp;
2163: u_int16_t length;
2164:
2165: if (level == 1)
2166: fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM,
2167: circuit->snd_stream);
2168: else
2169: fill_fixed_hdr_andstream (&fixed_hdr, L2_COMPLETE_SEQ_NUM,
2170: circuit->snd_stream);
2171:
2172: /*
2173: * Fill Level 1 or 2 Complete Sequence Numbers header
2174: */
2175:
2176: lenp = stream_get_endp (circuit->snd_stream);
2177: stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */
2178: /* no need to send the source here, it is always us if we csnp */
2179: stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
2180: /* with zero circuit id - ref 9.10, 9.11 */
2181: stream_putc (circuit->snd_stream, 0x00);
2182:
2183: stream_put (circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2);
2184: stream_put (circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2);
2185:
2186: /*
2187: * And TLVs
2188: */
2189: if (level == 1)
2190: passwd = &circuit->area->area_passwd;
2191: else
2192: passwd = &circuit->area->domain_passwd;
2193:
2194: if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
2195: if (passwd->type)
2196: retval = tlv_add_authinfo (passwd->type, passwd->len,
2197: passwd->passwd, circuit->snd_stream);
2198:
2199: if (!retval && lsps)
2200: {
2201: retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
2202: }
2203: length = (u_int16_t) stream_get_endp (circuit->snd_stream);
2204: assert (length >= ISIS_CSNP_HDRLEN);
2205: /* Update PU length */
2206: stream_putw_at (circuit->snd_stream, lenp, length);
2207:
2208: return retval;
2209: }
2210:
2211: /*
2212: * FIXME: support multiple CSNPs
2213: */
2214:
2215: int
2216: send_csnp (struct isis_circuit *circuit, int level)
2217: {
2218: int retval = ISIS_OK;
2219: u_char start[ISIS_SYS_ID_LEN + 2];
2220: u_char stop[ISIS_SYS_ID_LEN + 2];
2221: struct list *list = NULL;
2222: struct listnode *node;
2223: struct isis_lsp *lsp;
2224:
2225: memset (start, 0x00, ISIS_SYS_ID_LEN + 2);
2226: memset (stop, 0xff, ISIS_SYS_ID_LEN + 2);
2227:
2228: if (circuit->area->lspdb[level - 1] &&
2229: dict_count (circuit->area->lspdb[level - 1]) > 0)
2230: {
2231: list = list_new ();
2232: lsp_build_list (start, stop, list, circuit->area->lspdb[level - 1]);
2233:
2234: if (circuit->snd_stream == NULL)
2235: circuit->snd_stream = stream_new (ISO_MTU (circuit));
2236: else
2237: stream_reset (circuit->snd_stream);
2238:
2239: retval = build_csnp (level, start, stop, list, circuit);
2240:
2241: if (isis->debugs & DEBUG_SNP_PACKETS)
2242: {
2243: zlog_debug ("ISIS-Snp (%s): Sent L%d CSNP on %s, length %ld",
2244: circuit->area->area_tag, level, circuit->interface->name,
2245: /* FIXME: use %z when we stop supporting old compilers. */
2246: (unsigned long) STREAM_SIZE (circuit->snd_stream));
2247: for (ALL_LIST_ELEMENTS_RO (list, node, lsp))
2248: {
2249: zlog_debug ("ISIS-Snp (%s): CSNP entry %s, seq 0x%08x,"
2250: " cksum 0x%04x, lifetime %us",
2251: circuit->area->area_tag,
2252: rawlspid_print (lsp->lsp_header->lsp_id),
2253: ntohl (lsp->lsp_header->seq_num),
2254: ntohs (lsp->lsp_header->checksum),
2255: ntohs (lsp->lsp_header->rem_lifetime));
2256: }
2257: }
2258:
2259: list_delete (list);
2260:
2261: if (retval == ISIS_OK)
2262: retval = circuit->tx (circuit, level);
2263: }
2264: return retval;
2265: }
2266:
2267: int
2268: send_l1_csnp (struct thread *thread)
2269: {
2270: struct isis_circuit *circuit;
2271: int retval = ISIS_OK;
2272:
2273: circuit = THREAD_ARG (thread);
2274: assert (circuit);
2275:
2276: circuit->t_send_csnp[0] = NULL;
2277:
2278: if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0])
2279: {
2280: send_csnp (circuit, 1);
2281: }
2282: /* set next timer thread */
2283: THREAD_TIMER_ON (master, circuit->t_send_csnp[0], send_l1_csnp, circuit,
2284: isis_jitter (circuit->csnp_interval[0], CSNP_JITTER));
2285:
2286: return retval;
2287: }
2288:
2289: int
2290: send_l2_csnp (struct thread *thread)
2291: {
2292: struct isis_circuit *circuit;
2293: int retval = ISIS_OK;
2294:
2295: circuit = THREAD_ARG (thread);
2296: assert (circuit);
2297:
2298: circuit->t_send_csnp[1] = NULL;
2299:
2300: if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1])
2301: {
2302: send_csnp (circuit, 2);
2303: }
2304: /* set next timer thread */
2305: THREAD_TIMER_ON (master, circuit->t_send_csnp[1], send_l2_csnp, circuit,
2306: isis_jitter (circuit->csnp_interval[1], CSNP_JITTER));
2307:
2308: return retval;
2309: }
2310:
2311: static int
2312: build_psnp (int level, struct isis_circuit *circuit, struct list *lsps)
2313: {
2314: struct isis_fixed_hdr fixed_hdr;
2315: unsigned long lenp;
2316: u_int16_t length;
2317: int retval = 0;
2318: struct isis_lsp *lsp;
2319: struct isis_passwd *passwd;
2320: struct listnode *node;
2321:
2322: if (level == 1)
2323: fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
2324: circuit->snd_stream);
2325: else
2326: fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM,
2327: circuit->snd_stream);
2328:
2329: /*
2330: * Fill Level 1 or 2 Partial Sequence Numbers header
2331: */
2332: lenp = stream_get_endp (circuit->snd_stream);
2333: stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */
2334: stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
2335: stream_putc (circuit->snd_stream, circuit->idx);
2336:
2337: /*
2338: * And TLVs
2339: */
2340:
2341: if (level == 1)
2342: passwd = &circuit->area->area_passwd;
2343: else
2344: passwd = &circuit->area->domain_passwd;
2345:
2346: if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
2347: if (passwd->type)
2348: retval = tlv_add_authinfo (passwd->type, passwd->len,
2349: passwd->passwd, circuit->snd_stream);
2350:
2351: if (!retval && lsps)
2352: {
2353: retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
2354: }
2355:
2356: if (isis->debugs & DEBUG_SNP_PACKETS)
2357: {
2358: for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp))
2359: {
2360: zlog_debug ("ISIS-Snp (%s): PSNP entry %s, seq 0x%08x,"
2361: " cksum 0x%04x, lifetime %us",
2362: circuit->area->area_tag,
2363: rawlspid_print (lsp->lsp_header->lsp_id),
2364: ntohl (lsp->lsp_header->seq_num),
2365: ntohs (lsp->lsp_header->checksum),
2366: ntohs (lsp->lsp_header->rem_lifetime));
2367: }
2368: }
2369:
2370: length = (u_int16_t) stream_get_endp (circuit->snd_stream);
2371: assert (length >= ISIS_PSNP_HDRLEN);
2372: /* Update PDU length */
2373: stream_putw_at (circuit->snd_stream, lenp, length);
2374:
2375: return ISIS_OK;
2376: }
2377:
2378: /*
2379: * 7.3.15.4 action on expiration of partial SNP interval
2380: * level 1
2381: */
2382: static int
2383: send_psnp (int level, struct isis_circuit *circuit)
2384: {
2385: int retval = ISIS_OK;
2386: struct isis_lsp *lsp;
2387: struct list *list = NULL;
2388: struct listnode *node;
2389:
2390: if ((circuit->circ_type == CIRCUIT_T_BROADCAST &&
2391: !circuit->u.bc.is_dr[level - 1]) ||
2392: circuit->circ_type != CIRCUIT_T_BROADCAST)
2393: {
2394:
2395: if (circuit->area->lspdb[level - 1] &&
2396: dict_count (circuit->area->lspdb[level - 1]) > 0)
2397: {
2398: list = list_new ();
2399: lsp_build_list_ssn (circuit, list, circuit->area->lspdb[level - 1]);
2400:
2401: if (listcount (list) > 0)
2402: {
2403: if (circuit->snd_stream == NULL)
2404: circuit->snd_stream = stream_new (ISO_MTU (circuit));
2405: else
2406: stream_reset (circuit->snd_stream);
2407:
2408:
2409: if (isis->debugs & DEBUG_SNP_PACKETS)
2410: zlog_debug ("ISIS-Snp (%s): Sent L%d PSNP on %s, length %ld",
2411: circuit->area->area_tag, level,
2412: circuit->interface->name,
2413: /* FIXME: use %z when we stop supporting old
2414: * compilers. */
2415: (unsigned long) STREAM_SIZE (circuit->snd_stream));
2416:
2417: retval = build_psnp (level, circuit, list);
2418: if (retval == ISIS_OK)
2419: retval = circuit->tx (circuit, level);
2420:
2421: if (retval == ISIS_OK)
2422: {
2423: /*
2424: * sending succeeded, we can clear SSN flags of this circuit
2425: * for the LSPs in list
2426: */
2427: for (ALL_LIST_ELEMENTS_RO (list, node, lsp))
2428: ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
2429: }
2430: }
2431: list_delete (list);
2432: }
2433: }
2434:
2435: return retval;
2436: }
2437:
2438: int
2439: send_l1_psnp (struct thread *thread)
2440: {
2441:
2442: struct isis_circuit *circuit;
2443: int retval = ISIS_OK;
2444:
2445: circuit = THREAD_ARG (thread);
2446: assert (circuit);
2447:
2448: circuit->t_send_psnp[0] = NULL;
2449:
2450: send_psnp (1, circuit);
2451: /* set next timer thread */
2452: THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
2453: isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
2454:
2455: return retval;
2456: }
2457:
2458: /*
2459: * 7.3.15.4 action on expiration of partial SNP interval
2460: * level 2
2461: */
2462: int
2463: send_l2_psnp (struct thread *thread)
2464: {
2465: struct isis_circuit *circuit;
2466: int retval = ISIS_OK;
2467:
2468: circuit = THREAD_ARG (thread);
2469: assert (circuit);
2470:
2471: circuit->t_send_psnp[1] = NULL;
2472:
2473: send_psnp (2, circuit);
2474:
2475: /* set next timer thread */
2476: THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
2477: isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
2478:
2479: return retval;
2480: }
2481:
2482: /*
2483: * ISO 10589 - 7.3.14.3
2484: */
2485: int
2486: send_lsp (struct thread *thread)
2487: {
2488: struct isis_circuit *circuit;
2489: struct isis_lsp *lsp;
2490: struct listnode *node;
2491: int retval = 0;
2492:
2493: circuit = THREAD_ARG (thread);
2494: assert (circuit);
2495:
2496: if (circuit->state == C_STATE_UP)
2497: {
2498: lsp = listgetdata ((node = listhead (circuit->lsp_queue)));
2499:
2500: /*
2501: * Do not send if levels do not match
2502: */
2503: if (!(lsp->level & circuit->circuit_is_type))
2504: goto dontsend;
2505:
2506: /*
2507: * Do not send if we do not have adjacencies in state up on the circuit
2508: */
2509: if (circuit->upadjcount[lsp->level - 1] == 0)
2510: goto dontsend;
2511: /* only send if it needs sending */
2512: if ((time (NULL) - lsp->last_sent) >=
2513: circuit->area->lsp_gen_interval[lsp->level - 1])
2514: {
2515:
2516: if (isis->debugs & DEBUG_UPDATE_PACKETS)
2517: {
2518: zlog_debug
2519: ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x,"
2520: " lifetime %us on %s", circuit->area->area_tag, lsp->level,
2521: rawlspid_print (lsp->lsp_header->lsp_id),
2522: ntohl (lsp->lsp_header->seq_num),
2523: ntohs (lsp->lsp_header->checksum),
2524: ntohs (lsp->lsp_header->rem_lifetime),
2525: circuit->interface->name);
2526: }
2527: /* copy our lsp to the send buffer */
2528: stream_copy (circuit->snd_stream, lsp->pdu);
2529:
2530: retval = circuit->tx (circuit, lsp->level);
2531:
2532: /*
2533: * If the sending succeeded, we can del the lsp from circuits
2534: * lsp_queue
2535: */
2536: if (retval == ISIS_OK)
2537: {
2538: list_delete_node (circuit->lsp_queue, node);
2539:
2540: /*
2541: * On broadcast circuits also the SRMflag can be cleared
2542: */
2543: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
2544: ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
2545:
2546: if (flags_any_set (lsp->SRMflags) == 0)
2547: {
2548: /*
2549: * need to remember when we were last sent
2550: */
2551: lsp->last_sent = time (NULL);
2552: }
2553: }
2554: else
2555: {
2556: zlog_debug ("sending of level %d link state failed", lsp->level);
2557: }
2558: }
2559: else
2560: {
2561: /* my belief is that if it wasn't his time, the lsp can be removed
2562: * from the queue
2563: */
2564: dontsend:
2565: list_delete_node (circuit->lsp_queue, node);
2566: }
2567: #if 0
2568: /*
2569: * If there are still LSPs send next one after lsp-interval (33 msecs)
2570: */
2571: if (listcount (circuit->lsp_queue) > 0)
2572: thread_add_timer (master, send_lsp, circuit, 1);
2573: #endif
2574: }
2575:
2576: return retval;
2577: }
2578:
2579: int
2580: ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
2581: int level)
2582: {
2583: unsigned long lenp;
2584: int retval;
2585: u_int16_t length;
2586: struct isis_fixed_hdr fixed_hdr;
2587:
2588: if (!circuit->snd_stream)
2589: circuit->snd_stream = stream_new (ISO_MTU (circuit));
2590: else
2591: stream_reset (circuit->snd_stream);
2592:
2593: // fill_llc_hdr (stream);
2594: if (level == 1)
2595: fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
2596: circuit->snd_stream);
2597: else
2598: fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM,
2599: circuit->snd_stream);
2600:
2601:
2602: lenp = stream_get_endp (circuit->snd_stream);
2603: stream_putw (circuit->snd_stream, 0); /* PDU length */
2604: stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
2605: stream_putc (circuit->snd_stream, circuit->idx);
2606: stream_putc (circuit->snd_stream, 9); /* code */
2607: stream_putc (circuit->snd_stream, 16); /* len */
2608:
2609: stream_putw (circuit->snd_stream, ntohs (hdr->rem_lifetime));
2610: stream_put (circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2);
2611: stream_putl (circuit->snd_stream, ntohl (hdr->seq_num));
2612: stream_putw (circuit->snd_stream, ntohs (hdr->checksum));
2613:
2614: length = (u_int16_t) stream_get_endp (circuit->snd_stream);
2615: /* Update PDU length */
2616: stream_putw_at (circuit->snd_stream, lenp, length);
2617:
2618: retval = circuit->tx (circuit, level);
2619:
2620: return retval;
2621: }
2622:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>