]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_message.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / ospf6d / ospf6_message.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2003 Yasuhiro Ohara
4 */
5
6 #include <zebra.h>
7
8 #include "memory.h"
9 #include "log.h"
10 #include "vty.h"
11 #include "command.h"
12 #include "thread.h"
13 #include "linklist.h"
14 #include "lib_errors.h"
15 #include "checksum.h"
16 #include "network.h"
17
18 #include "ospf6_proto.h"
19 #include "ospf6_lsa.h"
20 #include "ospf6_lsdb.h"
21 #include "ospf6_top.h"
22 #include "ospf6_network.h"
23 #include "ospf6_message.h"
24
25 #include "ospf6_area.h"
26 #include "ospf6_neighbor.h"
27 #include "ospf6_interface.h"
28
29 /* for structures and macros ospf6_lsa_examin() needs */
30 #include "ospf6_abr.h"
31 #include "ospf6_asbr.h"
32 #include "ospf6_intra.h"
33
34 #include "ospf6_flood.h"
35 #include "ospf6d.h"
36 #include "ospf6_gr.h"
37 #include <netinet/ip6.h>
38 #include "lib/libospf.h"
39 #include "lib/keychain.h"
40 #include "ospf6_auth_trailer.h"
41
42 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message");
43 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet");
44 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6 FIFO queue");
45
46 unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
47
48 const char *ospf6_message_type(int type)
49 {
50 switch (type) {
51 case OSPF6_MESSAGE_TYPE_HELLO:
52 return "Hello";
53 case OSPF6_MESSAGE_TYPE_DBDESC:
54 return "DbDesc";
55 case OSPF6_MESSAGE_TYPE_LSREQ:
56 return "LSReq";
57 case OSPF6_MESSAGE_TYPE_LSUPDATE:
58 return "LSUpdate";
59 case OSPF6_MESSAGE_TYPE_LSACK:
60 return "LSAck";
61 case OSPF6_MESSAGE_TYPE_UNKNOWN:
62 default:
63 return "unknown";
64 }
65 }
66
67 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
68 packets of particular types, offset is the "type" field. */
69 const uint16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] = {
70 0,
71 OSPF6_HELLO_MIN_SIZE,
72 OSPF6_DB_DESC_MIN_SIZE,
73 OSPF6_LS_REQ_MIN_SIZE,
74 OSPF6_LS_UPD_MIN_SIZE,
75 OSPF6_LS_ACK_MIN_SIZE};
76
77 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
78 types, offset is the "LSA function code" portion of "LSA type" field. */
79 const uint16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] = {
80 0,
81 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
82 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
83 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
84 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
85 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
86 /* 0x2006 */ 0,
87 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
88 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
89 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
90 /* 0x200a */ 0,
91 /* 0x000b */ OSPF6_GRACE_LSA_MIN_SIZE};
92
93 /* print functions */
94
95 static void ospf6_header_print(struct ospf6_header *oh)
96 {
97 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh->version,
98 oh->type, ntohs(oh->length), &oh->router_id);
99 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh->area_id,
100 ntohs(oh->checksum), oh->instance_id);
101 }
102
103 void ospf6_hello_print(struct ospf6_header *oh, int action)
104 {
105 struct ospf6_hello *hello;
106 char options[32];
107 char *p;
108
109 ospf6_header_print(oh);
110 assert(oh->type == OSPF6_MESSAGE_TYPE_HELLO);
111
112 hello = (struct ospf6_hello *)((caddr_t)oh
113 + sizeof(struct ospf6_header));
114
115 ospf6_options_printbuf(hello->options, options, sizeof(options));
116
117 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
118 (unsigned long)ntohl(hello->interface_id), hello->priority,
119 options);
120 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
121 ntohs(hello->hello_interval), ntohs(hello->dead_interval));
122 zlog_debug(" DR:%pI4 BDR:%pI4", &hello->drouter, &hello->bdrouter);
123
124 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
125 && action == OSPF6_ACTION_RECV)
126 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
127 && action == OSPF6_ACTION_SEND)) {
128
129 for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
130 p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
131 p += sizeof(uint32_t))
132 zlog_debug(" Neighbor: %pI4", (in_addr_t *)p);
133
134 assert(p == OSPF6_MESSAGE_END(oh));
135 }
136 }
137
138 void ospf6_dbdesc_print(struct ospf6_header *oh, int action)
139 {
140 struct ospf6_dbdesc *dbdesc;
141 char options[32];
142 char *p;
143
144 ospf6_header_print(oh);
145 assert(oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
146
147 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
148 + sizeof(struct ospf6_header));
149
150 ospf6_options_printbuf(dbdesc->options, options, sizeof(options));
151
152 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc->reserved1,
153 options, ntohs(dbdesc->ifmtu));
154 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc->reserved2,
155 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
156 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
157 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
158 (unsigned long)ntohl(dbdesc->seqnum));
159
160 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
161 && action == OSPF6_ACTION_RECV)
162 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
163 && action == OSPF6_ACTION_SEND)) {
164
165 for (p = (char *)((caddr_t)dbdesc
166 + sizeof(struct ospf6_dbdesc));
167 p + sizeof(struct ospf6_lsa_header)
168 <= OSPF6_MESSAGE_END(oh);
169 p += sizeof(struct ospf6_lsa_header))
170 ospf6_lsa_header_print_raw(
171 (struct ospf6_lsa_header *)p);
172
173 assert(p == OSPF6_MESSAGE_END(oh));
174 }
175 }
176
177 void ospf6_lsreq_print(struct ospf6_header *oh, int action)
178 {
179 char *p;
180
181 ospf6_header_print(oh);
182 assert(oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
183
184 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
185 && action == OSPF6_ACTION_RECV)
186 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
187 && action == OSPF6_ACTION_SEND)) {
188
189 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
190 p + sizeof(struct ospf6_lsreq_entry)
191 <= OSPF6_MESSAGE_END(oh);
192 p += sizeof(struct ospf6_lsreq_entry)) {
193 struct ospf6_lsreq_entry *e =
194 (struct ospf6_lsreq_entry *)p;
195
196 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
197 ospf6_lstype_name(e->type), &e->id,
198 &e->adv_router);
199 }
200
201 assert(p == OSPF6_MESSAGE_END(oh));
202 }
203 }
204
205 void ospf6_lsupdate_print(struct ospf6_header *oh, int action)
206 {
207 struct ospf6_lsupdate *lsupdate;
208 unsigned long num;
209 char *p;
210
211 ospf6_header_print(oh);
212 assert(oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
213
214 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
215 + sizeof(struct ospf6_header));
216
217 num = ntohl(lsupdate->lsa_number);
218 zlog_debug(" Number of LSA: %ld", num);
219
220 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
221 && action == OSPF6_ACTION_RECV)
222 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
223 && action == OSPF6_ACTION_SEND)) {
224
225 for (p = (char *)((caddr_t)lsupdate
226 + sizeof(struct ospf6_lsupdate));
227 p < OSPF6_MESSAGE_END(oh)
228 && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
229 p += OSPF6_LSA_SIZE(p)) {
230 ospf6_lsa_header_print_raw(
231 (struct ospf6_lsa_header *)p);
232 }
233
234 assert(p == OSPF6_MESSAGE_END(oh));
235 }
236 }
237
238 void ospf6_lsack_print(struct ospf6_header *oh, int action)
239 {
240 char *p;
241
242 ospf6_header_print(oh);
243 assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK);
244
245 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
246 && action == OSPF6_ACTION_RECV)
247 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
248 && action == OSPF6_ACTION_SEND)) {
249
250 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
251 p + sizeof(struct ospf6_lsa_header)
252 <= OSPF6_MESSAGE_END(oh);
253 p += sizeof(struct ospf6_lsa_header))
254 ospf6_lsa_header_print_raw(
255 (struct ospf6_lsa_header *)p);
256
257 assert(p == OSPF6_MESSAGE_END(oh));
258 }
259 }
260
261 static struct ospf6_packet *ospf6_packet_new(size_t size)
262 {
263 struct ospf6_packet *new;
264
265 new = XCALLOC(MTYPE_OSPF6_PACKET, sizeof(struct ospf6_packet));
266 new->s = stream_new(size);
267
268 return new;
269 }
270
271 static void ospf6_packet_free(struct ospf6_packet *op)
272 {
273 if (op->s)
274 stream_free(op->s);
275
276 XFREE(MTYPE_OSPF6_PACKET, op);
277 }
278
279 struct ospf6_fifo *ospf6_fifo_new(void)
280 {
281 struct ospf6_fifo *new;
282
283 new = XCALLOC(MTYPE_OSPF6_FIFO, sizeof(struct ospf6_fifo));
284 return new;
285 }
286
287 /* Add new packet to fifo. */
288 static void ospf6_fifo_push(struct ospf6_fifo *fifo, struct ospf6_packet *op)
289 {
290 if (fifo->tail)
291 fifo->tail->next = op;
292 else
293 fifo->head = op;
294
295 fifo->tail = op;
296
297 fifo->count++;
298 }
299
300 /* Add new packet to head of fifo. */
301 static void ospf6_fifo_push_head(struct ospf6_fifo *fifo,
302 struct ospf6_packet *op)
303 {
304 op->next = fifo->head;
305
306 if (fifo->tail == NULL)
307 fifo->tail = op;
308
309 fifo->head = op;
310
311 fifo->count++;
312 }
313
314 /* Delete first packet from fifo. */
315 static struct ospf6_packet *ospf6_fifo_pop(struct ospf6_fifo *fifo)
316 {
317 struct ospf6_packet *op;
318
319 op = fifo->head;
320
321 if (op) {
322 fifo->head = op->next;
323
324 if (fifo->head == NULL)
325 fifo->tail = NULL;
326
327 fifo->count--;
328 }
329
330 return op;
331 }
332
333 /* Return first fifo entry. */
334 static struct ospf6_packet *ospf6_fifo_head(struct ospf6_fifo *fifo)
335 {
336 return fifo->head;
337 }
338
339 /* Flush ospf packet fifo. */
340 void ospf6_fifo_flush(struct ospf6_fifo *fifo)
341 {
342 struct ospf6_packet *op;
343 struct ospf6_packet *next;
344
345 for (op = fifo->head; op; op = next) {
346 next = op->next;
347 ospf6_packet_free(op);
348 }
349 fifo->head = fifo->tail = NULL;
350 fifo->count = 0;
351 }
352
353 /* Free ospf packet fifo. */
354 void ospf6_fifo_free(struct ospf6_fifo *fifo)
355 {
356 ospf6_fifo_flush(fifo);
357
358 XFREE(MTYPE_OSPF6_FIFO, fifo);
359 }
360
361 static void ospf6_packet_add(struct ospf6_interface *oi,
362 struct ospf6_packet *op)
363 {
364 /* Add packet to end of queue. */
365 ospf6_fifo_push(oi->obuf, op);
366
367 /* Debug of packet fifo*/
368 /* ospf_fifo_debug (oi->obuf); */
369 }
370
371 static void ospf6_packet_add_top(struct ospf6_interface *oi,
372 struct ospf6_packet *op)
373 {
374 /* Add packet to head of queue. */
375 ospf6_fifo_push_head(oi->obuf, op);
376
377 /* Debug of packet fifo*/
378 /* ospf_fifo_debug (oi->obuf); */
379 }
380
381 static void ospf6_packet_delete(struct ospf6_interface *oi)
382 {
383 struct ospf6_packet *op;
384
385 op = ospf6_fifo_pop(oi->obuf);
386
387 if (op)
388 ospf6_packet_free(op);
389 }
390
391
392 static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
393 struct ospf6_interface *oi,
394 struct ospf6_header *oh)
395 {
396 struct ospf6_hello *hello;
397 struct ospf6_neighbor *on;
398 char *p;
399 int twoway = 0;
400 int neighborchange = 0;
401 int neighbor_ifindex_change = 0;
402 int backupseen = 0;
403 int64_t latency = 0;
404 struct timeval timestamp;
405
406 monotime(&timestamp);
407 hello = (struct ospf6_hello *)((caddr_t)oh
408 + sizeof(struct ospf6_header));
409
410 /* HelloInterval check */
411 if (ntohs(hello->hello_interval) != oi->hello_interval) {
412 zlog_warn(
413 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
414 oi->interface->vrf->name, oi->interface->name,
415 oi->hello_interval, ntohs(hello->hello_interval));
416 return;
417 }
418
419 /* RouterDeadInterval check */
420 if (ntohs(hello->dead_interval) != oi->dead_interval) {
421 zlog_warn(
422 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
423 oi->interface->vrf->name, oi->interface->name,
424 oi->dead_interval, ntohs(hello->dead_interval));
425 return;
426 }
427
428 /* E-bit check */
429 if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_E)
430 != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_E)) {
431 zlog_warn("VRF %s: IF %s E-bit mismatch",
432 oi->interface->vrf->name, oi->interface->name);
433 return;
434 }
435
436 /* N-bit check */
437 if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_N)
438 != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_N)) {
439 zlog_warn("VRF %s: IF %s N-bit mismatch",
440 oi->interface->vrf->name, oi->interface->name);
441 return;
442 }
443
444 if (((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) ==
445 OSPF6_OPT_AT) &&
446 (oi->at_data.flags == 0)) ||
447 ((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) !=
448 OSPF6_OPT_AT) &&
449 (oi->at_data.flags != 0))) {
450 if (IS_OSPF6_DEBUG_AUTH_RX)
451 zlog_warn(
452 "VRF %s: IF %s AT-bit mismatch in hello packet",
453 oi->interface->vrf->name, oi->interface->name);
454 oi->at_data.rx_drop++;
455 return;
456 }
457
458 /* Find neighbor, create if not exist */
459 on = ospf6_neighbor_lookup(oh->router_id, oi);
460 if (on == NULL) {
461 on = ospf6_neighbor_create(oh->router_id, oi);
462 on->prev_drouter = on->drouter = hello->drouter;
463 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
464 on->priority = hello->priority;
465 }
466
467 /* check latency against hello period */
468 if (on->hello_in)
469 latency = monotime_since(&on->last_hello, NULL)
470 - ((int64_t)oi->hello_interval * 1000000);
471 /* log if latency exceeds the hello period */
472 if (latency > ((int64_t)oi->hello_interval * 1000000))
473 zlog_warn("%s RX %pI4 high latency %" PRId64 "us.", __func__,
474 &on->router_id, latency);
475 on->last_hello = timestamp;
476 on->hello_in++;
477
478 /* Always override neighbor's source address */
479 memcpy(&on->linklocal_addr, src, sizeof(struct in6_addr));
480
481 /* Neighbor ifindex check */
482 if (on->ifindex != (ifindex_t)ntohl(hello->interface_id)) {
483 on->ifindex = ntohl(hello->interface_id);
484 neighbor_ifindex_change++;
485 }
486
487 /* TwoWay check */
488 for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
489 p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
490 p += sizeof(uint32_t)) {
491 uint32_t *router_id = (uint32_t *)p;
492
493 if (*router_id == oi->area->ospf6->router_id)
494 twoway++;
495 }
496
497 assert(p == OSPF6_MESSAGE_END(oh));
498
499 /* RouterPriority check */
500 if (on->priority != hello->priority) {
501 on->priority = hello->priority;
502 neighborchange++;
503 }
504
505 /* DR check */
506 if (on->drouter != hello->drouter) {
507 on->prev_drouter = on->drouter;
508 on->drouter = hello->drouter;
509 if (on->prev_drouter == on->router_id
510 || on->drouter == on->router_id)
511 neighborchange++;
512 }
513
514 /* BDR check */
515 if (on->bdrouter != hello->bdrouter) {
516 on->prev_bdrouter = on->bdrouter;
517 on->bdrouter = hello->bdrouter;
518 if (on->prev_bdrouter == on->router_id
519 || on->bdrouter == on->router_id)
520 neighborchange++;
521 }
522
523 /* BackupSeen check */
524 if (oi->state == OSPF6_INTERFACE_WAITING) {
525 if (hello->bdrouter == on->router_id)
526 backupseen++;
527 else if (hello->drouter == on->router_id
528 && hello->bdrouter == htonl(0))
529 backupseen++;
530 }
531
532 oi->hello_in++;
533
534 /* Execute neighbor events */
535 thread_execute(master, hello_received, on, 0);
536 if (twoway)
537 thread_execute(master, twoway_received, on, 0);
538 else {
539 if (OSPF6_GR_IS_ACTIVE_HELPER(on)) {
540 if (IS_DEBUG_OSPF6_GR)
541 zlog_debug(
542 "%s, Received oneway hello from RESTARTER so ignore here.",
543 __PRETTY_FUNCTION__);
544 } else {
545 /* If the router is DR_OTHER, RESTARTER will not wait
546 * until it receives the hello from it if it receives
547 * from DR and BDR.
548 * So, helper might receives ONE_WAY hello from
549 * RESTARTER. So not allowing to change the state if it
550 * receives one_way hellow when it acts as HELPER for
551 * that specific neighbor.
552 */
553 thread_execute(master, oneway_received, on, 0);
554 }
555 }
556
557 if (OSPF6_GR_IS_ACTIVE_HELPER(on)) {
558 /* As per the GR Conformance Test Case 7.2. Section 3
559 * "Also, if X was the Designated Router on network segment S
560 * when the helping relationship began, Y maintains X as the
561 * Designated Router until the helping relationship is
562 * terminated."
563 * When it is a helper for this neighbor, It should not trigger
564 * the ISM Events. Also Intentionally not setting the priority
565 * and other fields so that when the neighbor exits the Grace
566 * period, it can handle if there is any change before GR and
567 * after GR.
568 */
569 if (IS_DEBUG_OSPF6_GR)
570 zlog_debug(
571 "%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
572 __PRETTY_FUNCTION__);
573
574 return;
575 }
576
577 /*
578 * RFC 3623 - Section 2:
579 * "If the restarting router determines that it was the Designated
580 * Router on a given segment prior to the restart, it elects
581 * itself as the Designated Router again. The restarting router
582 * knows that it was the Designated Router if, while the
583 * associated interface is in Waiting state, a Hello packet is
584 * received from a neighbor listing the router as the Designated
585 * Router".
586 */
587 if (oi->area->ospf6->gr_info.restart_in_progress
588 && oi->state == OSPF6_INTERFACE_WAITING
589 && hello->drouter == oi->area->ospf6->router_id)
590 oi->drouter = hello->drouter;
591
592 /* Schedule interface events */
593 if (backupseen)
594 thread_add_event(master, backup_seen, oi, 0, NULL);
595 if (neighborchange)
596 thread_add_event(master, neighbor_change, oi, 0, NULL);
597
598 if (neighbor_ifindex_change && on->state == OSPF6_NEIGHBOR_FULL)
599 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
600 }
601
602 static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
603 struct ospf6_neighbor *on)
604 {
605 struct ospf6_dbdesc *dbdesc;
606 char *p;
607
608 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
609 + sizeof(struct ospf6_header));
610
611 if (on->state < OSPF6_NEIGHBOR_INIT) {
612 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
613 zlog_debug("Neighbor state less than Init, ignore");
614 return;
615 }
616
617 switch (on->state) {
618 case OSPF6_NEIGHBOR_TWOWAY:
619 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
620 zlog_debug("Neighbor state is 2-Way, ignore");
621 return;
622
623 case OSPF6_NEIGHBOR_INIT:
624 thread_execute(master, twoway_received, on, 0);
625 if (on->state != OSPF6_NEIGHBOR_EXSTART) {
626 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
627 zlog_debug(
628 "Neighbor state is not ExStart, ignore");
629 return;
630 }
631 /* else fall through to ExStart */
632 /* fallthru */
633 case OSPF6_NEIGHBOR_EXSTART:
634 /* if neighbor obeys us as our slave, schedule negotiation_done
635 and process LSA Headers. Otherwise, ignore this message */
636 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)
637 && !CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)
638 && ntohl(dbdesc->seqnum) == on->dbdesc_seqnum) {
639 /* execute NegotiationDone */
640 thread_execute(master, negotiation_done, on, 0);
641
642 /* Record neighbor options */
643 memcpy(on->options, dbdesc->options,
644 sizeof(on->options));
645 } else {
646 zlog_warn("VRF %s: Nbr %s: Negotiation failed",
647 on->ospf6_if->interface->vrf->name, on->name);
648 return;
649 }
650 /* fall through to exchange */
651
652 case OSPF6_NEIGHBOR_EXCHANGE:
653 if (!memcmp(dbdesc, &on->dbdesc_last,
654 sizeof(struct ospf6_dbdesc))) {
655 /* Duplicated DatabaseDescription is dropped by master
656 */
657 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
658 zlog_debug(
659 "Duplicated dbdesc discarded by Master, ignore");
660 return;
661 }
662
663 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
664 zlog_warn(
665 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
666 on->name);
667 thread_add_event(master, seqnumber_mismatch, on, 0,
668 NULL);
669 return;
670 }
671
672 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
673 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
674 on->name);
675 thread_add_event(master, seqnumber_mismatch, on, 0,
676 NULL);
677 return;
678 }
679
680 if (memcmp(on->options, dbdesc->options, sizeof(on->options))) {
681 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
682 on->name);
683 thread_add_event(master, seqnumber_mismatch, on, 0,
684 NULL);
685 return;
686 }
687
688 if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum) {
689 zlog_warn(
690 "DbDesc recv: Sequence number mismatch Nbr %s (%#lx expected)",
691 on->name, (unsigned long)on->dbdesc_seqnum);
692 thread_add_event(master, seqnumber_mismatch, on, 0,
693 NULL);
694 return;
695 }
696 break;
697
698 case OSPF6_NEIGHBOR_LOADING:
699 case OSPF6_NEIGHBOR_FULL:
700 if (!memcmp(dbdesc, &on->dbdesc_last,
701 sizeof(struct ospf6_dbdesc))) {
702 /* Duplicated DatabaseDescription is dropped by master
703 */
704 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
705 zlog_debug(
706 "Duplicated dbdesc discarded by Master, ignore");
707 return;
708 }
709
710 zlog_warn(
711 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
712 ospf6_neighbor_state_str[on->state], on->name);
713 thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
714 return;
715
716 default:
717 assert(0);
718 break;
719 }
720
721 /* Process LSA headers */
722 for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
723 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
724 p += sizeof(struct ospf6_lsa_header)) {
725 struct ospf6_lsa *his, *mine;
726 struct ospf6_lsdb *lsdb = NULL;
727
728 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
729
730 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
731 zlog_debug("%s", his->name);
732
733 switch (OSPF6_LSA_SCOPE(his->header->type)) {
734 case OSPF6_SCOPE_LINKLOCAL:
735 lsdb = on->ospf6_if->lsdb;
736 break;
737 case OSPF6_SCOPE_AREA:
738 lsdb = on->ospf6_if->area->lsdb;
739 break;
740 case OSPF6_SCOPE_AS:
741 lsdb = on->ospf6_if->area->ospf6->lsdb;
742 break;
743 case OSPF6_SCOPE_RESERVED:
744 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
745 zlog_debug("Ignoring LSA of reserved scope");
746 ospf6_lsa_delete(his);
747 continue;
748 }
749
750 if (ntohs(his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL
751 && (IS_AREA_STUB(on->ospf6_if->area)
752 || IS_AREA_NSSA(on->ospf6_if->area))) {
753 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
754 zlog_debug(
755 "SeqNumMismatch (E-bit mismatch), discard");
756 ospf6_lsa_delete(his);
757 thread_add_event(master, seqnumber_mismatch, on, 0,
758 NULL);
759 return;
760 }
761
762 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
763 his->header->adv_router, lsdb);
764 if (mine == NULL) {
765 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
766 zlog_debug("Add request (No database copy)");
767 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
768 } else if (ospf6_lsa_compare(his, mine) < 0) {
769 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
770 zlog_debug("Add request (Received MoreRecent)");
771 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
772 } else {
773 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
774 zlog_debug("Discard (Existing MoreRecent)");
775 }
776 ospf6_lsa_delete(his);
777 }
778
779 assert(p == OSPF6_MESSAGE_END(oh));
780
781 /* Increment sequence number */
782 on->dbdesc_seqnum++;
783
784 /* schedule send lsreq */
785 if (on->request_list->count)
786 thread_add_event(master, ospf6_lsreq_send, on, 0,
787 &on->thread_send_lsreq);
788
789 THREAD_OFF(on->thread_send_dbdesc);
790
791 /* More bit check */
792 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT)
793 && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
794 thread_add_event(master, exchange_done, on, 0,
795 &on->thread_exchange_done);
796 else {
797 thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
798 &on->thread_send_dbdesc);
799 }
800
801 /* save last received dbdesc */
802 memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc));
803 }
804
805 static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
806 struct ospf6_neighbor *on)
807 {
808 struct ospf6_dbdesc *dbdesc;
809 char *p;
810
811 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
812 + sizeof(struct ospf6_header));
813
814 if (on->state < OSPF6_NEIGHBOR_INIT) {
815 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
816 zlog_debug("Neighbor state less than Init, ignore");
817 return;
818 }
819
820 switch (on->state) {
821 case OSPF6_NEIGHBOR_TWOWAY:
822 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
823 zlog_debug("Neighbor state is 2-Way, ignore");
824 return;
825
826 case OSPF6_NEIGHBOR_INIT:
827 thread_execute(master, twoway_received, on, 0);
828 if (on->state != OSPF6_NEIGHBOR_EXSTART) {
829 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
830 zlog_debug(
831 "Neighbor state is not ExStart, ignore");
832 return;
833 }
834 /* else fall through to ExStart */
835 /* fallthru */
836 case OSPF6_NEIGHBOR_EXSTART:
837 /* If the neighbor is Master, act as Slave. Schedule
838 negotiation_done
839 and process LSA Headers. Otherwise, ignore this message */
840 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)
841 && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT)
842 && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)
843 && ntohs(oh->length)
844 == sizeof(struct ospf6_header)
845 + sizeof(struct ospf6_dbdesc)) {
846 /* set the master/slave bit to slave */
847 UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
848
849 /* set the DD sequence number to one specified by master
850 */
851 on->dbdesc_seqnum = ntohl(dbdesc->seqnum);
852
853 /* schedule NegotiationDone */
854 thread_execute(master, negotiation_done, on, 0);
855
856 /* Record neighbor options */
857 memcpy(on->options, dbdesc->options,
858 sizeof(on->options));
859 } else {
860 zlog_warn("VRF %s: Nbr %s Negotiation failed",
861 on->ospf6_if->interface->vrf->name, on->name);
862 return;
863 }
864 break;
865
866 case OSPF6_NEIGHBOR_EXCHANGE:
867 if (!memcmp(dbdesc, &on->dbdesc_last,
868 sizeof(struct ospf6_dbdesc))) {
869 /* Duplicated DatabaseDescription causes slave to
870 * retransmit */
871 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
872 zlog_debug(
873 "Duplicated dbdesc causes retransmit");
874 THREAD_OFF(on->thread_send_dbdesc);
875 thread_add_event(master, ospf6_dbdesc_send, on, 0,
876 &on->thread_send_dbdesc);
877 return;
878 }
879
880 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
881 zlog_warn(
882 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
883 on->name);
884 thread_add_event(master, seqnumber_mismatch, on, 0,
885 NULL);
886 return;
887 }
888
889 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
890 zlog_warn(
891 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
892 on->name);
893 thread_add_event(master, seqnumber_mismatch, on, 0,
894 NULL);
895 return;
896 }
897
898 if (memcmp(on->options, dbdesc->options, sizeof(on->options))) {
899 zlog_warn(
900 "DbDesc slave recv: Option field mismatch Nbr %s",
901 on->name);
902 thread_add_event(master, seqnumber_mismatch, on, 0,
903 NULL);
904 return;
905 }
906
907 if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum + 1) {
908 zlog_warn(
909 "DbDesc slave recv: Sequence number mismatch Nbr %s (%#lx expected)",
910 on->name, (unsigned long)on->dbdesc_seqnum + 1);
911 thread_add_event(master, seqnumber_mismatch, on, 0,
912 NULL);
913 return;
914 }
915 break;
916
917 case OSPF6_NEIGHBOR_LOADING:
918 case OSPF6_NEIGHBOR_FULL:
919 if (!memcmp(dbdesc, &on->dbdesc_last,
920 sizeof(struct ospf6_dbdesc))) {
921 /* Duplicated DatabaseDescription causes slave to
922 * retransmit */
923 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
924 zlog_debug(
925 "Duplicated dbdesc causes retransmit");
926 THREAD_OFF(on->thread_send_dbdesc);
927 thread_add_event(master, ospf6_dbdesc_send, on, 0,
928 &on->thread_send_dbdesc);
929 return;
930 }
931
932 zlog_warn(
933 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
934 ospf6_neighbor_state_str[on->state], on->name);
935 thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
936 return;
937
938 default:
939 assert(0);
940 break;
941 }
942
943 /* Process LSA headers */
944 for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
945 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
946 p += sizeof(struct ospf6_lsa_header)) {
947 struct ospf6_lsa *his, *mine;
948 struct ospf6_lsdb *lsdb = NULL;
949
950 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
951
952 switch (OSPF6_LSA_SCOPE(his->header->type)) {
953 case OSPF6_SCOPE_LINKLOCAL:
954 lsdb = on->ospf6_if->lsdb;
955 break;
956 case OSPF6_SCOPE_AREA:
957 lsdb = on->ospf6_if->area->lsdb;
958 break;
959 case OSPF6_SCOPE_AS:
960 lsdb = on->ospf6_if->area->ospf6->lsdb;
961 break;
962 case OSPF6_SCOPE_RESERVED:
963 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
964 zlog_debug("Ignoring LSA of reserved scope");
965 ospf6_lsa_delete(his);
966 continue;
967 }
968
969 if (OSPF6_LSA_SCOPE(his->header->type) == OSPF6_SCOPE_AS
970 && (IS_AREA_STUB(on->ospf6_if->area)
971 || IS_AREA_NSSA(on->ospf6_if->area))) {
972 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
973 zlog_debug("E-bit mismatch with LSA Headers");
974 ospf6_lsa_delete(his);
975 thread_add_event(master, seqnumber_mismatch, on, 0,
976 NULL);
977 return;
978 }
979
980 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
981 his->header->adv_router, lsdb);
982 if (mine == NULL || ospf6_lsa_compare(his, mine) < 0) {
983 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
984 zlog_debug("Add request-list: %s", his->name);
985 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
986 }
987 ospf6_lsa_delete(his);
988 }
989
990 assert(p == OSPF6_MESSAGE_END(oh));
991
992 /* Set sequence number to Master's */
993 on->dbdesc_seqnum = ntohl(dbdesc->seqnum);
994
995 /* schedule send lsreq */
996 if (on->request_list->count)
997 thread_add_event(master, ospf6_lsreq_send, on, 0,
998 &on->thread_send_lsreq);
999
1000 THREAD_OFF(on->thread_send_dbdesc);
1001 thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
1002 &on->thread_send_dbdesc);
1003
1004 /* save last received dbdesc */
1005 memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc));
1006 }
1007
1008 static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
1009 struct ospf6_interface *oi,
1010 struct ospf6_header *oh)
1011 {
1012 struct ospf6_neighbor *on;
1013 struct ospf6_dbdesc *dbdesc;
1014
1015 on = ospf6_neighbor_lookup(oh->router_id, oi);
1016 if (on == NULL) {
1017 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1018 zlog_debug("Neighbor not found, ignore");
1019 return;
1020 }
1021
1022 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
1023 + sizeof(struct ospf6_header));
1024
1025 if (((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) ==
1026 OSPF6_OPT_AT) &&
1027 (oi->at_data.flags == 0)) ||
1028 ((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) !=
1029 OSPF6_OPT_AT) &&
1030 (oi->at_data.flags != 0))) {
1031 if (IS_OSPF6_DEBUG_AUTH_RX)
1032 zlog_warn(
1033 "VRF %s: IF %s AT-bit mismatch in dbdesc packet",
1034 oi->interface->vrf->name, oi->interface->name);
1035 oi->at_data.rx_drop++;
1036 return;
1037 }
1038
1039 /* Interface MTU check */
1040 if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
1041 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
1042 oi->interface->vrf->name, oi->interface->name,
1043 oi->ifmtu, ntohs(dbdesc->ifmtu));
1044 return;
1045 }
1046
1047 if (dbdesc->reserved1 || dbdesc->reserved2) {
1048 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1049 zlog_debug(
1050 "Non-0 reserved field in %s's DbDesc, correct",
1051 on->name);
1052 dbdesc->reserved1 = 0;
1053 dbdesc->reserved2 = 0;
1054 }
1055
1056 oi->db_desc_in++;
1057
1058 if (ntohl(oh->router_id) < ntohl(oi->area->ospf6->router_id))
1059 ospf6_dbdesc_recv_master(oh, on);
1060 else if (ntohl(oi->area->ospf6->router_id) < ntohl(oh->router_id))
1061 ospf6_dbdesc_recv_slave(oh, on);
1062 else {
1063 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1064 zlog_debug("Can't decide which is master, ignore");
1065 }
1066 }
1067
1068 static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst,
1069 struct ospf6_interface *oi,
1070 struct ospf6_header *oh)
1071 {
1072 struct ospf6_neighbor *on;
1073 char *p;
1074 struct ospf6_lsreq_entry *e;
1075 struct ospf6_lsdb *lsdb = NULL;
1076 struct ospf6_lsa *lsa;
1077
1078 on = ospf6_neighbor_lookup(oh->router_id, oi);
1079 if (on == NULL) {
1080 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1081 zlog_debug("Neighbor not found, ignore");
1082 return;
1083 }
1084
1085 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1086 && on->state != OSPF6_NEIGHBOR_LOADING
1087 && on->state != OSPF6_NEIGHBOR_FULL) {
1088 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1089 zlog_debug("Neighbor state less than Exchange, ignore");
1090 return;
1091 }
1092
1093 oi->ls_req_in++;
1094
1095 /* Process each request */
1096 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
1097 p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh);
1098 p += sizeof(struct ospf6_lsreq_entry)) {
1099 e = (struct ospf6_lsreq_entry *)p;
1100
1101 switch (OSPF6_LSA_SCOPE(e->type)) {
1102 case OSPF6_SCOPE_LINKLOCAL:
1103 lsdb = on->ospf6_if->lsdb;
1104 break;
1105 case OSPF6_SCOPE_AREA:
1106 lsdb = on->ospf6_if->area->lsdb;
1107 break;
1108 case OSPF6_SCOPE_AS:
1109 lsdb = on->ospf6_if->area->ospf6->lsdb;
1110 break;
1111 default:
1112 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1113 zlog_debug("Ignoring LSA of reserved scope");
1114 continue;
1115 }
1116
1117 /* Find database copy */
1118 lsa = ospf6_lsdb_lookup(e->type, e->id, e->adv_router, lsdb);
1119 if (lsa == NULL) {
1120 zlog_warn(
1121 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
1122 ospf6_lstype_name(e->type), &e->id,
1123 &e->adv_router);
1124 thread_add_event(master, bad_lsreq, on, 0, NULL);
1125 return;
1126 }
1127
1128 ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->lsupdate_list);
1129 }
1130
1131 assert(p == OSPF6_MESSAGE_END(oh));
1132
1133 /* schedule send lsupdate */
1134 THREAD_OFF(on->thread_send_lsupdate);
1135 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
1136 &on->thread_send_lsupdate);
1137 }
1138
1139 /* Verify, that the specified memory area contains exactly N valid IPv6
1140 prefixes as specified by RFC5340, A.4.1. */
1141 static unsigned ospf6_prefixes_examin(
1142 struct ospf6_prefix *current, /* start of buffer */
1143 unsigned length,
1144 const uint32_t req_num_pfxs /* always compared with the actual number
1145 of prefixes */
1146 )
1147 {
1148 uint8_t requested_pfx_bytes;
1149 uint32_t real_num_pfxs = 0;
1150
1151 while (length) {
1152 if (length < OSPF6_PREFIX_MIN_SIZE) {
1153 zlog_warn("%s: undersized IPv6 prefix header",
1154 __func__);
1155 return MSG_NG;
1156 }
1157 /* safe to look deeper */
1158 if (current->prefix_length > IPV6_MAX_BITLEN) {
1159 zlog_warn("%s: invalid PrefixLength (%u bits)",
1160 __func__, current->prefix_length);
1161 return MSG_NG;
1162 }
1163 /* covers both fixed- and variable-sized fields */
1164 requested_pfx_bytes =
1165 OSPF6_PREFIX_MIN_SIZE
1166 + OSPF6_PREFIX_SPACE(current->prefix_length);
1167 if (requested_pfx_bytes > length) {
1168 zlog_warn("%s: undersized IPv6 prefix", __func__);
1169 return MSG_NG;
1170 }
1171 /* next prefix */
1172 length -= requested_pfx_bytes;
1173 current = (struct ospf6_prefix *)((caddr_t)current
1174 + requested_pfx_bytes);
1175 real_num_pfxs++;
1176 }
1177 if (real_num_pfxs != req_num_pfxs) {
1178 zlog_warn(
1179 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1180 __func__, req_num_pfxs, real_num_pfxs);
1181 return MSG_NG;
1182 }
1183 return MSG_OK;
1184 }
1185
1186 /* Verify an LSA to have a valid length and dispatch further (where
1187 appropriate) to check if the contents, including nested IPv6 prefixes,
1188 is properly sized/aligned within the LSA. Note that this function gets
1189 LSA type in network byte order, uses in host byte order and passes to
1190 ospf6_lstype_name() in network byte order again. */
1191 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
1192 const uint16_t lsalen,
1193 const uint8_t headeronly)
1194 {
1195 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1196 struct ospf6_as_external_lsa *as_external_lsa;
1197 struct ospf6_link_lsa *link_lsa;
1198 unsigned exp_length;
1199 uint8_t ltindex;
1200 uint16_t lsatype;
1201
1202 /* In case an additional minimum length constraint is defined for
1203 current
1204 LSA type, make sure that this constraint is met. */
1205 lsatype = ntohs(lsah->type);
1206 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
1207 if (ltindex < OSPF6_LSTYPE_SIZE && ospf6_lsa_minlen[ltindex]
1208 && lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE) {
1209 zlog_warn("%s: undersized (%u B) LSA", __func__, lsalen);
1210 return MSG_NG;
1211 }
1212 switch (lsatype) {
1213 case OSPF6_LSTYPE_ROUTER:
1214 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1215 followed
1216 by N>=0 interface descriptions. */
1217 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE)
1218 % OSPF6_ROUTER_LSDESC_FIX_SIZE) {
1219 zlog_warn(
1220 "%s: Router LSA interface description alignment error",
1221 __func__);
1222 return MSG_NG;
1223 }
1224 break;
1225 case OSPF6_LSTYPE_NETWORK:
1226 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1227 followed by N>=0 attached router descriptions. */
1228 if ((lsalen - OSPF6_LSA_HEADER_SIZE
1229 - OSPF6_NETWORK_LSA_MIN_SIZE)
1230 % OSPF6_NETWORK_LSDESC_FIX_SIZE) {
1231 zlog_warn(
1232 "%s: Network LSA router description alignment error",
1233 __func__);
1234 return MSG_NG;
1235 }
1236 break;
1237 case OSPF6_LSTYPE_INTER_PREFIX:
1238 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1239 bytes
1240 followed by 3-4 fields of a single IPv6 prefix. */
1241 if (headeronly)
1242 break;
1243 return ospf6_prefixes_examin(
1244 (struct ospf6_prefix
1245 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE
1246 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1247 lsalen - OSPF6_LSA_HEADER_SIZE
1248 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1249 1);
1250 case OSPF6_LSTYPE_INTER_ROUTER:
1251 /* RFC5340 A.4.6, fixed-size LSA. */
1252 if (lsalen
1253 > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE) {
1254 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1255 __func__, lsalen);
1256 return MSG_NG;
1257 }
1258 break;
1259 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1260 case OSPF6_LSTYPE_TYPE_7:
1261 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1262 bytes
1263 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1264 fields:
1265 16 bytes of forwarding address, 4 bytes of external route
1266 tag,
1267 4 bytes of referenced link state ID. */
1268 if (headeronly)
1269 break;
1270 as_external_lsa =
1271 (struct ospf6_as_external_lsa
1272 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE);
1273 exp_length =
1274 OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1275 /* To find out if the last optional field (Referenced Link State
1276 ID) is
1277 assumed in this LSA, we need to access fixed fields of the
1278 IPv6
1279 prefix before ospf6_prefix_examin() confirms its sizing. */
1280 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen) {
1281 zlog_warn(
1282 "%s: AS External undersized (%u B) LSA header",
1283 __func__, lsalen);
1284 return MSG_NG;
1285 }
1286 /* forwarding address */
1287 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1288 exp_length += 16;
1289 /* external route tag */
1290 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1291 exp_length += 4;
1292 /* referenced link state ID */
1293 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1294 exp_length += 4;
1295 /* All the fixed-size fields (mandatory and optional) must fit.
1296 I.e.,
1297 this check does not include any IPv6 prefix fields. */
1298 if (exp_length > lsalen) {
1299 zlog_warn(
1300 "%s: AS External undersized (%u B) LSA header",
1301 __func__, lsalen);
1302 return MSG_NG;
1303 }
1304 /* The last call completely covers the remainder (IPv6 prefix).
1305 */
1306 return ospf6_prefixes_examin(
1307 (struct ospf6_prefix
1308 *)((caddr_t)as_external_lsa
1309 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1310 lsalen - exp_length, 1);
1311 case OSPF6_LSTYPE_LINK:
1312 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1313 followed
1314 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1315 if (headeronly)
1316 break;
1317 link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsah
1318 + OSPF6_LSA_HEADER_SIZE);
1319 return ospf6_prefixes_examin(
1320 (struct ospf6_prefix *)((caddr_t)link_lsa
1321 + OSPF6_LINK_LSA_MIN_SIZE),
1322 lsalen - OSPF6_LSA_HEADER_SIZE
1323 - OSPF6_LINK_LSA_MIN_SIZE,
1324 ntohl(link_lsa->prefix_num) /* 32 bits */
1325 );
1326 case OSPF6_LSTYPE_INTRA_PREFIX:
1327 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1328 bytes
1329 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1330 */
1331 if (headeronly)
1332 break;
1333 intra_prefix_lsa =
1334 (struct ospf6_intra_prefix_lsa
1335 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE);
1336 return ospf6_prefixes_examin(
1337 (struct ospf6_prefix
1338 *)((caddr_t)intra_prefix_lsa
1339 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1340 lsalen - OSPF6_LSA_HEADER_SIZE
1341 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1342 ntohs(intra_prefix_lsa->prefix_num) /* 16 bits */
1343 );
1344 case OSPF6_LSTYPE_GRACE_LSA:
1345 if (lsalen < OSPF6_LSA_HEADER_SIZE + GRACE_PERIOD_TLV_SIZE
1346 + GRACE_RESTART_REASON_TLV_SIZE) {
1347 if (IS_DEBUG_OSPF6_GR)
1348 zlog_debug("%s: Undersized GraceLSA.",
1349 __func__);
1350 return MSG_NG;
1351 }
1352 }
1353 /* No additional validation is possible for unknown LSA types, which are
1354 themselves valid in OPSFv3, hence the default decision is to accept.
1355 */
1356 return MSG_OK;
1357 }
1358
1359 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1360 includes verification of LSA blocks length/alignment and dispatching
1361 of deeper-level checks. */
1362 static unsigned
1363 ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
1364 size_t length, const uint8_t headeronly,
1365 /* When declared_num_lsas is not 0, compare it to the real
1366 number of LSAs
1367 and treat the difference as an error. */
1368 const uint32_t declared_num_lsas)
1369 {
1370 uint32_t counted_lsas = 0;
1371
1372 while (length) {
1373 uint16_t lsalen;
1374 if (length < OSPF6_LSA_HEADER_SIZE) {
1375 zlog_warn(
1376 "%s: undersized (%zu B) trailing (#%u) LSA header",
1377 __func__, length, counted_lsas);
1378 return MSG_NG;
1379 }
1380 /* save on ntohs() calls here and in the LSA validator */
1381 lsalen = OSPF6_LSA_SIZE(lsah);
1382 if (lsalen < OSPF6_LSA_HEADER_SIZE) {
1383 zlog_warn(
1384 "%s: malformed LSA header #%u, declared length is %u B",
1385 __func__, counted_lsas, lsalen);
1386 return MSG_NG;
1387 }
1388 if (headeronly) {
1389 /* less checks here and in ospf6_lsa_examin() */
1390 if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 1)) {
1391 zlog_warn(
1392 "%s: anomaly in header-only %s LSA #%u",
1393 __func__, ospf6_lstype_name(lsah->type),
1394 counted_lsas);
1395 return MSG_NG;
1396 }
1397 lsah = (struct ospf6_lsa_header
1398 *)((caddr_t)lsah
1399 + OSPF6_LSA_HEADER_SIZE);
1400 length -= OSPF6_LSA_HEADER_SIZE;
1401 } else {
1402 /* make sure the input buffer is deep enough before
1403 * further checks */
1404 if (lsalen > length) {
1405 zlog_warn(
1406 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1407 __func__, ospf6_lstype_name(lsah->type),
1408 counted_lsas, lsalen, length);
1409 return MSG_NG;
1410 }
1411 if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 0)) {
1412 zlog_warn("%s: anomaly in %s LSA #%u", __func__,
1413 ospf6_lstype_name(lsah->type),
1414 counted_lsas);
1415 return MSG_NG;
1416 }
1417 lsah = (struct ospf6_lsa_header *)((caddr_t)lsah
1418 + lsalen);
1419 length -= lsalen;
1420 }
1421 counted_lsas++;
1422 }
1423
1424 if (declared_num_lsas && counted_lsas != declared_num_lsas) {
1425 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1426 __func__, declared_num_lsas, counted_lsas);
1427 return MSG_NG;
1428 }
1429 return MSG_OK;
1430 }
1431
1432 /* Verify a complete OSPF packet for proper sizing/alignment. */
1433 static unsigned ospf6_packet_examin(struct ospf6_header *oh,
1434 const unsigned bytesonwire)
1435 {
1436 struct ospf6_lsupdate *lsupd;
1437 unsigned test;
1438
1439 /* length, 1st approximation */
1440 if (bytesonwire < OSPF6_HEADER_SIZE) {
1441 zlog_warn("%s: undersized (%u B) packet", __func__,
1442 bytesonwire);
1443 return MSG_NG;
1444 }
1445
1446 /* Now it is safe to access header fields. */
1447 if (bytesonwire != ntohs(oh->length)) {
1448 zlog_warn("%s: %s packet length error (%u real, %u declared)",
1449 __func__, ospf6_message_type(oh->type), bytesonwire,
1450 ntohs(oh->length));
1451 return MSG_NG;
1452 }
1453
1454 /* version check */
1455 if (oh->version != OSPFV3_VERSION) {
1456 zlog_warn("%s: invalid (%u) protocol version", __func__,
1457 oh->version);
1458 return MSG_NG;
1459 }
1460 /* length, 2nd approximation */
1461 if (oh->type < OSPF6_MESSAGE_TYPE_ALL && ospf6_packet_minlen[oh->type]
1462 && bytesonwire
1463 < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
1464 zlog_warn("%s: undersized (%u B) %s packet", __func__,
1465 bytesonwire, ospf6_message_type(oh->type));
1466 return MSG_NG;
1467 }
1468 /* type-specific deeper validation */
1469 switch (oh->type) {
1470 case OSPF6_MESSAGE_TYPE_HELLO:
1471 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1472 followed
1473 by N>=0 router-IDs. */
1474 if (0
1475 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE)
1476 % 4)
1477 return MSG_OK;
1478 zlog_warn("%s: alignment error in %s packet", __func__,
1479 ospf6_message_type(oh->type));
1480 return MSG_NG;
1481 case OSPF6_MESSAGE_TYPE_DBDESC:
1482 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1483 followed
1484 by N>=0 header-only LSAs. */
1485 test = ospf6_lsaseq_examin(
1486 (struct ospf6_lsa_header *)((caddr_t)oh
1487 + OSPF6_HEADER_SIZE
1488 + OSPF6_DB_DESC_MIN_SIZE),
1489 bytesonwire - OSPF6_HEADER_SIZE
1490 - OSPF6_DB_DESC_MIN_SIZE,
1491 1, 0);
1492 break;
1493 case OSPF6_MESSAGE_TYPE_LSREQ:
1494 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1495 if (0
1496 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE)
1497 % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1498 return MSG_OK;
1499 zlog_warn("%s: alignment error in %s packet", __func__,
1500 ospf6_message_type(oh->type));
1501 return MSG_NG;
1502 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1503 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1504 followed
1505 by N>=0 full LSAs (with N declared beforehand). */
1506 lsupd = (struct ospf6_lsupdate *)((caddr_t)oh
1507 + OSPF6_HEADER_SIZE);
1508 test = ospf6_lsaseq_examin(
1509 (struct ospf6_lsa_header *)((caddr_t)lsupd
1510 + OSPF6_LS_UPD_MIN_SIZE),
1511 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1512 0, ntohl(lsupd->lsa_number) /* 32 bits */
1513 );
1514 break;
1515 case OSPF6_MESSAGE_TYPE_LSACK:
1516 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1517 test = ospf6_lsaseq_examin(
1518 (struct ospf6_lsa_header *)((caddr_t)oh
1519 + OSPF6_HEADER_SIZE
1520 + OSPF6_LS_ACK_MIN_SIZE),
1521 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1522 1, 0);
1523 break;
1524 default:
1525 zlog_warn("%s: invalid (%u) message type", __func__, oh->type);
1526 return MSG_NG;
1527 }
1528 if (test != MSG_OK)
1529 zlog_warn("%s: anomaly in %s packet", __func__,
1530 ospf6_message_type(oh->type));
1531 return test;
1532 }
1533
1534 /* Verify particular fields of otherwise correct received OSPF packet to
1535 meet the requirements of RFC. */
1536 static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
1537 struct ospf6_header *oh,
1538 const unsigned bytesonwire)
1539 {
1540
1541 if (MSG_OK != ospf6_packet_examin(oh, bytesonwire))
1542 return MSG_NG;
1543
1544 /* Area-ID check */
1545 if (oh->area_id != oi->area->area_id) {
1546 if (oh->area_id == OSPF_AREA_BACKBONE)
1547 zlog_warn(
1548 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1549 oi->interface->vrf->name, oi->interface->name);
1550 else
1551 zlog_warn(
1552 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1553 oi->interface->vrf->name, oi->interface->name,
1554 &oi->area->area_id, &oh->area_id);
1555 return MSG_NG;
1556 }
1557
1558 /* Instance-ID check */
1559 if (oh->instance_id != oi->instance_id) {
1560 zlog_warn(
1561 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1562 oi->interface->vrf->name, oi->interface->name,
1563 oi->instance_id, oh->instance_id);
1564 return MSG_NG;
1565 }
1566
1567 /* Router-ID check */
1568 if (oh->router_id == oi->area->ospf6->router_id) {
1569 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1570 oi->interface->vrf->name, oi->interface->name,
1571 &oh->router_id);
1572 return MSG_NG;
1573 }
1574 return MSG_OK;
1575 }
1576
1577 static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst,
1578 struct ospf6_interface *oi,
1579 struct ospf6_header *oh)
1580 {
1581 struct ospf6_neighbor *on;
1582 struct ospf6_lsupdate *lsupdate;
1583 char *p;
1584
1585 on = ospf6_neighbor_lookup(oh->router_id, oi);
1586 if (on == NULL) {
1587 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1588 zlog_debug("Neighbor not found, ignore");
1589 return;
1590 }
1591
1592 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1593 && on->state != OSPF6_NEIGHBOR_LOADING
1594 && on->state != OSPF6_NEIGHBOR_FULL) {
1595 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1596 zlog_debug("Neighbor state less than Exchange, ignore");
1597 return;
1598 }
1599
1600 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
1601 + sizeof(struct ospf6_header));
1602
1603 oi->ls_upd_in++;
1604
1605 /* Process LSAs */
1606 for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
1607 p < OSPF6_MESSAGE_END(oh)
1608 && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
1609 p += OSPF6_LSA_SIZE(p)) {
1610 ospf6_receive_lsa(on, (struct ospf6_lsa_header *)p);
1611 }
1612
1613 assert(p == OSPF6_MESSAGE_END(oh));
1614 }
1615
1616 static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst,
1617 struct ospf6_interface *oi,
1618 struct ospf6_header *oh)
1619 {
1620 struct ospf6_neighbor *on;
1621 char *p;
1622 struct ospf6_lsa *his, *mine;
1623 struct ospf6_lsdb *lsdb = NULL;
1624
1625 assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1626
1627 on = ospf6_neighbor_lookup(oh->router_id, oi);
1628 if (on == NULL) {
1629 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1630 zlog_debug("Neighbor not found, ignore");
1631 return;
1632 }
1633
1634 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1635 && on->state != OSPF6_NEIGHBOR_LOADING
1636 && on->state != OSPF6_NEIGHBOR_FULL) {
1637 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
1638 zlog_debug("Neighbor state less than Exchange, ignore");
1639 return;
1640 }
1641
1642 oi->ls_ack_in++;
1643
1644 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
1645 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
1646 p += sizeof(struct ospf6_lsa_header)) {
1647 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
1648
1649 switch (OSPF6_LSA_SCOPE(his->header->type)) {
1650 case OSPF6_SCOPE_LINKLOCAL:
1651 lsdb = on->ospf6_if->lsdb;
1652 break;
1653 case OSPF6_SCOPE_AREA:
1654 lsdb = on->ospf6_if->area->lsdb;
1655 break;
1656 case OSPF6_SCOPE_AS:
1657 lsdb = on->ospf6_if->area->ospf6->lsdb;
1658 break;
1659 case OSPF6_SCOPE_RESERVED:
1660 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1661 zlog_debug("Ignoring LSA of reserved scope");
1662 ospf6_lsa_delete(his);
1663 continue;
1664 }
1665
1666 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1667 zlog_debug("%s acknowledged by %s", his->name,
1668 on->name);
1669
1670 /* Find database copy */
1671 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
1672 his->header->adv_router, lsdb);
1673 if (mine == NULL) {
1674 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1675 zlog_debug("No database copy");
1676 ospf6_lsa_delete(his);
1677 continue;
1678 }
1679
1680 /* Check if the LSA is on his retrans-list */
1681 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
1682 his->header->adv_router,
1683 on->retrans_list);
1684 if (mine == NULL) {
1685 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1686 zlog_debug("Not on %s's retrans-list",
1687 on->name);
1688 ospf6_lsa_delete(his);
1689 continue;
1690 }
1691
1692 if (ospf6_lsa_compare(his, mine) != 0) {
1693 /* Log this questionable acknowledgement,
1694 and examine the next one. */
1695 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1696 zlog_debug("Questionable acknowledgement");
1697 ospf6_lsa_delete(his);
1698 continue;
1699 }
1700
1701 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1702 zlog_debug(
1703 "Acknowledged, remove from %s's retrans-list",
1704 on->name);
1705
1706 ospf6_decrement_retrans_count(mine);
1707 if (OSPF6_LSA_IS_MAXAGE(mine))
1708 ospf6_maxage_remove(on->ospf6_if->area->ospf6);
1709 ospf6_lsdb_remove(mine, on->retrans_list);
1710 ospf6_lsa_delete(his);
1711 }
1712
1713 assert(p == OSPF6_MESSAGE_END(oh));
1714 }
1715
1716 static uint8_t *recvbuf = NULL;
1717 static uint8_t *sendbuf = NULL;
1718 static unsigned int iobuflen = 0;
1719
1720 int ospf6_iobuf_size(unsigned int size)
1721 {
1722 /* NB: there was previously code here that tried to dynamically size
1723 * the buffer for whatever we see in MTU on interfaces. Which is
1724 * _unconditionally wrong_ - we can always receive fragmented IPv6
1725 * up to the regular 64k length limit. (No jumbograms, thankfully.)
1726 */
1727
1728 if (!iobuflen) {
1729 /* the + 128 is to have some runway at the end */
1730 size_t alloc_size = 65536 + 128;
1731
1732 assert(!recvbuf && !sendbuf);
1733
1734 recvbuf = XMALLOC(MTYPE_OSPF6_MESSAGE, alloc_size);
1735 sendbuf = XMALLOC(MTYPE_OSPF6_MESSAGE, alloc_size);
1736 iobuflen = alloc_size;
1737 }
1738
1739 return iobuflen;
1740 }
1741
1742 void ospf6_message_terminate(void)
1743 {
1744 XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
1745 XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
1746
1747 iobuflen = 0;
1748 }
1749
1750 enum ospf6_read_return_enum {
1751 OSPF6_READ_ERROR,
1752 OSPF6_READ_CONTINUE,
1753 };
1754
1755 static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
1756 {
1757 int len;
1758 struct in6_addr src, dst;
1759 ifindex_t ifindex;
1760 struct iovec iovector[2];
1761 struct ospf6_interface *oi;
1762 struct ospf6_header *oh;
1763 enum ospf6_auth_err ret = OSPF6_AUTH_PROCESS_NORMAL;
1764 uint32_t at_len = 0;
1765 uint32_t lls_len = 0;
1766
1767 /* initialize */
1768 memset(&src, 0, sizeof(src));
1769 memset(&dst, 0, sizeof(dst));
1770 ifindex = 0;
1771 iovector[0].iov_base = recvbuf;
1772 iovector[0].iov_len = iobuflen;
1773 iovector[1].iov_base = NULL;
1774 iovector[1].iov_len = 0;
1775
1776 /* receive message */
1777 len = ospf6_recvmsg(&src, &dst, &ifindex, iovector, sockfd);
1778 if (len < 0)
1779 return OSPF6_READ_ERROR;
1780
1781 if ((uint)len > iobuflen) {
1782 flog_err(EC_LIB_DEVELOPMENT, "Excess message read");
1783 return OSPF6_READ_ERROR;
1784 }
1785
1786 /* ensure some zeroes past the end, just as a security precaution */
1787 memset(recvbuf + len, 0, MIN(128, iobuflen - len));
1788
1789 oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id);
1790 if (oi == NULL || oi->area == NULL
1791 || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
1792 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1793 RECV_HDR))
1794 zlog_debug("Message received on disabled interface");
1795 return OSPF6_READ_CONTINUE;
1796 }
1797 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) {
1798 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1799 RECV_HDR))
1800 zlog_debug("%s: Ignore message on passive interface %s",
1801 __func__, oi->interface->name);
1802 return OSPF6_READ_CONTINUE;
1803 }
1804
1805 /*
1806 * Drop packet destined to another VRF.
1807 * This happens when raw_l3mdev_accept is set to 1.
1808 */
1809 if (ospf6->vrf_id != oi->interface->vrf->vrf_id)
1810 return OSPF6_READ_CONTINUE;
1811
1812 oh = (struct ospf6_header *)recvbuf;
1813 ret = ospf6_auth_validate_pkt(oi, (uint32_t *)&len, oh, &at_len,
1814 &lls_len);
1815 if (ret == OSPF6_AUTH_VALIDATE_SUCCESS) {
1816 ret = ospf6_auth_check_digest(oh, oi, &src, lls_len);
1817 if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
1818 if (IS_OSPF6_DEBUG_AUTH_RX)
1819 zlog_err(
1820 "RECV[%s]: OSPF packet auth digest miss-match on %s",
1821 oi->interface->name,
1822 ospf6_message_type(oh->type));
1823 oi->at_data.rx_drop++;
1824 return OSPF6_READ_CONTINUE;
1825 }
1826 } else if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
1827 oi->at_data.rx_drop++;
1828 return OSPF6_READ_CONTINUE;
1829 }
1830
1831 if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK)
1832 return OSPF6_READ_CONTINUE;
1833
1834 /* Being here means, that no sizing/alignment issues were detected in
1835 the input packet. This renders the additional checks performed below
1836 and also in the type-specific dispatching functions a dead code,
1837 which can be dismissed in a cleanup-focused review round later. */
1838
1839 /* Log */
1840 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) {
1841 zlog_debug("%s received on %s", ospf6_message_type(oh->type),
1842 oi->interface->name);
1843 zlog_debug(" src: %pI6", &src);
1844 zlog_debug(" dst: %pI6", &dst);
1845
1846 switch (oh->type) {
1847 case OSPF6_MESSAGE_TYPE_HELLO:
1848 ospf6_hello_print(oh, OSPF6_ACTION_RECV);
1849 break;
1850 case OSPF6_MESSAGE_TYPE_DBDESC:
1851 ospf6_dbdesc_print(oh, OSPF6_ACTION_RECV);
1852 break;
1853 case OSPF6_MESSAGE_TYPE_LSREQ:
1854 ospf6_lsreq_print(oh, OSPF6_ACTION_RECV);
1855 break;
1856 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1857 ospf6_lsupdate_print(oh, OSPF6_ACTION_RECV);
1858 break;
1859 case OSPF6_MESSAGE_TYPE_LSACK:
1860 ospf6_lsack_print(oh, OSPF6_ACTION_RECV);
1861 break;
1862 default:
1863 assert(0);
1864 }
1865
1866 if ((at_len != 0) && IS_OSPF6_DEBUG_AUTH_RX)
1867 ospf6_auth_hdr_dump_recv(oh, (len + at_len + lls_len),
1868 lls_len);
1869 }
1870
1871 switch (oh->type) {
1872 case OSPF6_MESSAGE_TYPE_HELLO:
1873 ospf6_hello_recv(&src, &dst, oi, oh);
1874 break;
1875
1876 case OSPF6_MESSAGE_TYPE_DBDESC:
1877 ospf6_dbdesc_recv(&src, &dst, oi, oh);
1878 break;
1879
1880 case OSPF6_MESSAGE_TYPE_LSREQ:
1881 ospf6_lsreq_recv(&src, &dst, oi, oh);
1882 break;
1883
1884 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1885 ospf6_lsupdate_recv(&src, &dst, oi, oh);
1886 break;
1887
1888 case OSPF6_MESSAGE_TYPE_LSACK:
1889 ospf6_lsack_recv(&src, &dst, oi, oh);
1890 break;
1891
1892 default:
1893 assert(0);
1894 }
1895
1896 return OSPF6_READ_CONTINUE;
1897 }
1898
1899 void ospf6_receive(struct thread *thread)
1900 {
1901 int sockfd;
1902 struct ospf6 *ospf6;
1903 int count = 0;
1904
1905 /* add next read thread */
1906 ospf6 = THREAD_ARG(thread);
1907 sockfd = THREAD_FD(thread);
1908
1909 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
1910 &ospf6->t_ospf6_receive);
1911
1912 while (count < ospf6->write_oi_count) {
1913 count++;
1914 switch (ospf6_read_helper(sockfd, ospf6)) {
1915 case OSPF6_READ_ERROR:
1916 return;
1917 case OSPF6_READ_CONTINUE:
1918 break;
1919 }
1920 }
1921 }
1922
1923 static void ospf6_fill_hdr_checksum(struct ospf6_interface *oi,
1924 struct ospf6_packet *op)
1925 {
1926 struct ipv6_ph ph = {};
1927 struct ospf6_header *oh;
1928 void *offset = NULL;
1929
1930 if (oi->at_data.flags != 0)
1931 return;
1932
1933 memcpy(&ph.src, oi->linklocal_addr, sizeof(struct in6_addr));
1934 memcpy(&ph.dst, &op->dst, sizeof(struct in6_addr));
1935 ph.ulpl = htonl(op->length);
1936 ph.next_hdr = IPPROTO_OSPFIGP;
1937
1938 /* Suppress static analysis warnings about accessing icmp6 oob */
1939 oh = (struct ospf6_header *)STREAM_DATA(op->s);
1940 offset = oh;
1941 oh->checksum = in_cksum_with_ph6(&ph, offset, op->length);
1942 }
1943
1944 static void ospf6_make_header(uint8_t type, struct ospf6_interface *oi,
1945 struct stream *s)
1946 {
1947 struct ospf6_header *oh;
1948
1949 oh = (struct ospf6_header *)STREAM_DATA(s);
1950
1951 oh->version = (uint8_t)OSPFV3_VERSION;
1952 oh->type = type;
1953 oh->length = 0;
1954
1955 oh->router_id = oi->area->ospf6->router_id;
1956 oh->area_id = oi->area->area_id;
1957 oh->checksum = 0;
1958 oh->instance_id = oi->instance_id;
1959 oh->reserved = 0;
1960
1961 stream_forward_endp(s, OSPF6_HEADER_SIZE);
1962 }
1963
1964 static void ospf6_fill_header(struct ospf6_interface *oi, struct stream *s,
1965 uint16_t length)
1966 {
1967 struct ospf6_header *oh;
1968
1969 oh = (struct ospf6_header *)STREAM_DATA(s);
1970
1971 oh->length = htons(length);
1972 }
1973
1974 static void ospf6_fill_lsupdate_header(struct stream *s, uint32_t lsa_num)
1975 {
1976 struct ospf6_header *oh;
1977 struct ospf6_lsupdate *lsu;
1978
1979 oh = (struct ospf6_header *)STREAM_DATA(s);
1980
1981 lsu = (struct ospf6_lsupdate *)((caddr_t)oh
1982 + sizeof(struct ospf6_header));
1983 lsu->lsa_number = htonl(lsa_num);
1984 }
1985
1986 static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface *oi)
1987 {
1988 char *keychain_name = NULL;
1989 struct keychain *keychain = NULL;
1990 struct key *key = NULL;
1991
1992 keychain_name = oi->at_data.keychain;
1993 keychain = keychain_lookup(keychain_name);
1994 if (keychain) {
1995 key = key_lookup_for_send(keychain);
1996 if (key && key->string &&
1997 key->hash_algo != KEYCHAIN_ALGO_NULL) {
1998 /* storing the values so that further
1999 * lookup can be avoided. after
2000 * processing the digest need to reset
2001 * these values
2002 */
2003 oi->at_data.hash_algo = key->hash_algo;
2004 if (oi->at_data.auth_key)
2005 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY,
2006 oi->at_data.auth_key);
2007 oi->at_data.auth_key = XSTRDUP(
2008 MTYPE_OSPF6_AUTH_MANUAL_KEY, key->string);
2009 oi->at_data.key_id = key->index;
2010 SET_FLAG(oi->at_data.flags,
2011 OSPF6_AUTH_TRAILER_KEYCHAIN_VALID);
2012 }
2013 }
2014 }
2015
2016 static uint16_t ospf6_packet_max(struct ospf6_interface *oi)
2017 {
2018 uint16_t at_len = 0;
2019
2020 assert(oi->ifmtu > sizeof(struct ip6_hdr));
2021
2022 if (oi->at_data.flags != 0) {
2023 if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
2024 ospf6_auth_trailer_copy_keychain_key(oi);
2025
2026 at_len += OSPF6_AUTH_HDR_MIN_SIZE;
2027 at_len += keychain_get_hash_len(oi->at_data.hash_algo);
2028 return oi->ifmtu - (sizeof(struct ip6_hdr)) - at_len;
2029 }
2030
2031 return oi->ifmtu - (sizeof(struct ip6_hdr));
2032 }
2033
2034 static uint16_t ospf6_make_hello(struct ospf6_interface *oi, struct stream *s)
2035 {
2036 struct listnode *node, *nnode;
2037 struct ospf6_neighbor *on;
2038 uint16_t length = OSPF6_HELLO_MIN_SIZE;
2039 uint8_t options1 = oi->area->options[1];
2040
2041 if (oi->at_data.flags != 0)
2042 options1 |= OSPF6_OPT_AT;
2043
2044 stream_putl(s, oi->interface->ifindex);
2045 stream_putc(s, oi->priority);
2046 stream_putc(s, oi->area->options[0]);
2047 stream_putc(s, options1);
2048 stream_putc(s, oi->area->options[2]);
2049 stream_putw(s, oi->hello_interval);
2050 stream_putw(s, oi->dead_interval);
2051 stream_put_ipv4(s, oi->drouter);
2052 stream_put_ipv4(s, oi->bdrouter);
2053
2054 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
2055 if (on->state < OSPF6_NEIGHBOR_INIT)
2056 continue;
2057
2058 if ((length + sizeof(uint32_t) + OSPF6_HEADER_SIZE)
2059 > ospf6_packet_max(oi)) {
2060 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO,
2061 SEND))
2062 zlog_debug(
2063 "sending Hello message: exceeds I/F MTU");
2064 break;
2065 }
2066
2067 stream_put_ipv4(s, on->router_id);
2068 length += sizeof(uint32_t);
2069 }
2070
2071 return length;
2072 }
2073
2074 static void ospf6_write(struct thread *thread)
2075 {
2076 struct ospf6 *ospf6 = THREAD_ARG(thread);
2077 struct ospf6_interface *oi;
2078 struct ospf6_header *oh;
2079 struct ospf6_packet *op;
2080 struct listnode *node;
2081 struct iovec iovector[2];
2082 int pkt_count = 0;
2083 int len;
2084 int64_t latency = 0;
2085 struct timeval timestamp;
2086 uint16_t at_len = 0;
2087
2088 if (ospf6->fd < 0) {
2089 zlog_warn("ospf6_write failed to send, fd %d", ospf6->fd);
2090 return;
2091 }
2092
2093 node = listhead(ospf6->oi_write_q);
2094 assert(node);
2095 oi = listgetdata(node);
2096
2097 while ((pkt_count < ospf6->write_oi_count) && oi) {
2098 op = ospf6_fifo_head(oi->obuf);
2099 assert(op);
2100 assert(op->length >= OSPF6_HEADER_SIZE);
2101
2102 iovector[0].iov_base = (caddr_t)stream_pnt(op->s);
2103 iovector[0].iov_len = op->length;
2104 iovector[1].iov_base = NULL;
2105 iovector[1].iov_len = 0;
2106
2107 oh = (struct ospf6_header *)STREAM_DATA(op->s);
2108
2109 if (oi->at_data.flags != 0) {
2110 at_len = ospf6_auth_len_get(oi);
2111 if (at_len) {
2112 iovector[0].iov_len =
2113 ntohs(oh->length) + at_len;
2114 ospf6_auth_digest_send(oi->linklocal_addr, oi,
2115 oh, at_len,
2116 iovector[0].iov_len);
2117 } else {
2118 iovector[0].iov_len = ntohs(oh->length);
2119 }
2120 } else {
2121 iovector[0].iov_len = ntohs(oh->length);
2122 }
2123
2124 len = ospf6_sendmsg(oi->linklocal_addr, &op->dst,
2125 oi->interface->ifindex, iovector,
2126 ospf6->fd);
2127
2128 if (len != (op->length + (int)at_len))
2129 flog_err(EC_LIB_DEVELOPMENT,
2130 "Could not send entire message");
2131
2132 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
2133 zlog_debug("%s send on %s",
2134 ospf6_message_type(oh->type),
2135 oi->interface->name);
2136 zlog_debug(" src: %pI6", oi->linklocal_addr);
2137 zlog_debug(" dst: %pI6", &op->dst);
2138 switch (oh->type) {
2139 case OSPF6_MESSAGE_TYPE_HELLO:
2140 ospf6_hello_print(oh, OSPF6_ACTION_SEND);
2141 break;
2142 case OSPF6_MESSAGE_TYPE_DBDESC:
2143 ospf6_dbdesc_print(oh, OSPF6_ACTION_SEND);
2144 break;
2145 case OSPF6_MESSAGE_TYPE_LSREQ:
2146 ospf6_lsreq_print(oh, OSPF6_ACTION_SEND);
2147 break;
2148 case OSPF6_MESSAGE_TYPE_LSUPDATE:
2149 ospf6_lsupdate_print(oh, OSPF6_ACTION_SEND);
2150 break;
2151 case OSPF6_MESSAGE_TYPE_LSACK:
2152 ospf6_lsack_print(oh, OSPF6_ACTION_SEND);
2153 break;
2154 default:
2155 zlog_debug("Unknown message");
2156 assert(0);
2157 break;
2158 }
2159 }
2160 switch (oh->type) {
2161 case OSPF6_MESSAGE_TYPE_HELLO:
2162 monotime(&timestamp);
2163 if (oi->hello_out)
2164 latency = monotime_since(&oi->last_hello, NULL)
2165 - ((int64_t)oi->hello_interval
2166 * 1000000);
2167
2168 /* log if latency exceeds the hello period */
2169 if (latency > ((int64_t)oi->hello_interval * 1000000))
2170 zlog_warn("%s hello TX high latency %" PRId64
2171 "us.",
2172 __func__, latency);
2173 oi->last_hello = timestamp;
2174 oi->hello_out++;
2175 break;
2176 case OSPF6_MESSAGE_TYPE_DBDESC:
2177 oi->db_desc_out++;
2178 break;
2179 case OSPF6_MESSAGE_TYPE_LSREQ:
2180 oi->ls_req_out++;
2181 break;
2182 case OSPF6_MESSAGE_TYPE_LSUPDATE:
2183 oi->ls_upd_out++;
2184 break;
2185 case OSPF6_MESSAGE_TYPE_LSACK:
2186 oi->ls_ack_out++;
2187 break;
2188 default:
2189 zlog_debug("Unknown message");
2190 assert(0);
2191 break;
2192 }
2193
2194 if ((oi->at_data.flags != 0) &&
2195 (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) &&
2196 (IS_OSPF6_DEBUG_AUTH_TX))
2197 ospf6_auth_hdr_dump_send(oh, iovector[0].iov_len);
2198
2199 /* initialize at_len to 0 for next packet */
2200 at_len = 0;
2201
2202 /* Now delete packet from queue. */
2203 ospf6_packet_delete(oi);
2204
2205 /* Move this interface to the tail of write_q to
2206 serve everyone in a round robin fashion */
2207 list_delete_node(ospf6->oi_write_q, node);
2208 if (ospf6_fifo_head(oi->obuf) == NULL) {
2209 oi->on_write_q = 0;
2210 oi = NULL;
2211 } else {
2212 listnode_add(ospf6->oi_write_q, oi);
2213 }
2214
2215 /* Setup to service from the head of the queue again */
2216 if (!list_isempty(ospf6->oi_write_q)) {
2217 node = listhead(ospf6->oi_write_q);
2218 oi = listgetdata(node);
2219 }
2220 }
2221
2222 /* If packets still remain in queue, call write thread. */
2223 if (!list_isempty(ospf6->oi_write_q))
2224 thread_add_write(master, ospf6_write, ospf6, ospf6->fd,
2225 &ospf6->t_write);
2226 }
2227
2228 void ospf6_hello_send(struct thread *thread)
2229 {
2230 struct ospf6_interface *oi;
2231 struct ospf6_packet *op;
2232 uint16_t length = OSPF6_HEADER_SIZE;
2233
2234 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2235
2236 if (oi->state <= OSPF6_INTERFACE_DOWN) {
2237 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND_HDR))
2238 zlog_debug("Unable to send Hello on down interface %s",
2239 oi->interface->name);
2240 return;
2241 }
2242
2243 op = ospf6_packet_new(oi->ifmtu);
2244
2245 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO, oi, op->s);
2246
2247 /* Prepare OSPF Hello body */
2248 length += ospf6_make_hello(oi, op->s);
2249 if (length == OSPF6_HEADER_SIZE) {
2250 /* Hello overshooting MTU */
2251 ospf6_packet_free(op);
2252 return;
2253 }
2254
2255 /* Fill OSPF header. */
2256 ospf6_fill_header(oi, op->s, length);
2257
2258 /* Set packet length. */
2259 op->length = length;
2260
2261 op->dst = allspfrouters6;
2262
2263 ospf6_fill_hdr_checksum(oi, op);
2264
2265 /* Add packet to the top of the interface output queue, so that they
2266 * can't get delayed by things like long queues of LS Update packets
2267 */
2268 ospf6_packet_add_top(oi, op);
2269
2270 /* set next thread */
2271 thread_add_timer(master, ospf6_hello_send, oi, oi->hello_interval,
2272 &oi->thread_send_hello);
2273
2274 OSPF6_MESSAGE_WRITE_ON(oi);
2275 }
2276
2277 static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
2278 {
2279 uint16_t length = OSPF6_DB_DESC_MIN_SIZE;
2280 struct ospf6_lsa *lsa, *lsanext;
2281 uint8_t options1 = on->ospf6_if->area->options[1];
2282
2283 if (on->ospf6_if->at_data.flags != 0)
2284 options1 |= OSPF6_OPT_AT;
2285
2286 /* if this is initial one, initialize sequence number for DbDesc */
2287 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
2288 && (on->dbdesc_seqnum == 0)) {
2289 on->dbdesc_seqnum = frr_sequence32_next();
2290 }
2291
2292 /* reserved */
2293 stream_putc(s, 0); /* reserved 1 */
2294 stream_putc(s, on->ospf6_if->area->options[0]);
2295 stream_putc(s, options1);
2296 stream_putc(s, on->ospf6_if->area->options[2]);
2297 stream_putw(s, on->ospf6_if->ifmtu);
2298 stream_putc(s, 0); /* reserved 2 */
2299 stream_putc(s, on->dbdesc_bits);
2300 stream_putl(s, on->dbdesc_seqnum);
2301
2302 /* if this is not initial one, set LSA headers in dbdesc */
2303 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)) {
2304 for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) {
2305 ospf6_lsa_age_update_to_send(lsa,
2306 on->ospf6_if->transdelay);
2307
2308 /* MTU check */
2309 if ((length + sizeof(struct ospf6_lsa_header)
2310 + OSPF6_HEADER_SIZE)
2311 > ospf6_packet_max(on->ospf6_if)) {
2312 ospf6_lsa_unlock(lsa);
2313 if (lsanext)
2314 ospf6_lsa_unlock(lsanext);
2315 break;
2316 }
2317 stream_put(s, lsa->header,
2318 sizeof(struct ospf6_lsa_header));
2319 length += sizeof(struct ospf6_lsa_header);
2320 }
2321 }
2322 return length;
2323 }
2324
2325 void ospf6_dbdesc_send(struct thread *thread)
2326 {
2327 struct ospf6_neighbor *on;
2328 uint16_t length = OSPF6_HEADER_SIZE;
2329 struct ospf6_packet *op;
2330
2331 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2332
2333 if (on->state < OSPF6_NEIGHBOR_EXSTART) {
2334 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND))
2335 zlog_debug(
2336 "Quit to send DbDesc to neighbor %s state %s",
2337 on->name, ospf6_neighbor_state_str[on->state]);
2338 return;
2339 }
2340
2341 /* set next thread if master */
2342 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
2343 thread_add_timer(master, ospf6_dbdesc_send, on,
2344 on->ospf6_if->rxmt_interval,
2345 &on->thread_send_dbdesc);
2346
2347 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2348 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC, on->ospf6_if, op->s);
2349
2350 length += ospf6_make_dbdesc(on, op->s);
2351 ospf6_fill_header(on->ospf6_if, op->s, length);
2352
2353 /* Set packet length. */
2354 op->length = length;
2355
2356 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2357 op->dst = allspfrouters6;
2358 else
2359 op->dst = on->linklocal_addr;
2360
2361 ospf6_fill_hdr_checksum(on->ospf6_if, op);
2362
2363 ospf6_packet_add(on->ospf6_if, op);
2364
2365 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2366 }
2367
2368 void ospf6_dbdesc_send_newone(struct thread *thread)
2369 {
2370 struct ospf6_neighbor *on;
2371 struct ospf6_lsa *lsa, *lsanext;
2372 unsigned int size = 0;
2373
2374 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2375 ospf6_lsdb_remove_all(on->dbdesc_list);
2376
2377 /* move LSAs from summary_list to dbdesc_list (within neighbor
2378 structure)
2379 so that ospf6_send_dbdesc () can send those LSAs */
2380 size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc);
2381 for (ALL_LSDB(on->summary_list, lsa, lsanext)) {
2382 /* if stub area then don't advertise AS-External LSAs */
2383 if ((IS_AREA_STUB(on->ospf6_if->area)
2384 || IS_AREA_NSSA(on->ospf6_if->area))
2385 && ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
2386 ospf6_lsdb_remove(lsa, on->summary_list);
2387 continue;
2388 }
2389
2390 if (size + sizeof(struct ospf6_lsa_header)
2391 > ospf6_packet_max(on->ospf6_if)) {
2392 ospf6_lsa_unlock(lsa);
2393 if (lsanext)
2394 ospf6_lsa_unlock(lsanext);
2395 break;
2396 }
2397
2398 ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->dbdesc_list);
2399 ospf6_lsdb_remove(lsa, on->summary_list);
2400 size += sizeof(struct ospf6_lsa_header);
2401 }
2402
2403 if (on->summary_list->count == 0)
2404 UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
2405
2406 /* If slave, More bit check must be done here */
2407 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
2408 !CHECK_FLAG(on->dbdesc_last.bits, OSPF6_DBDESC_MBIT)
2409 && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
2410 thread_add_event(master, exchange_done, on, 0,
2411 &on->thread_exchange_done);
2412
2413 thread_execute(master, ospf6_dbdesc_send, on, 0);
2414 }
2415
2416 static uint16_t ospf6_make_lsreq(struct ospf6_neighbor *on, struct stream *s)
2417 {
2418 uint16_t length = 0;
2419 struct ospf6_lsa *lsa, *lsanext, *last_req = NULL;
2420
2421 for (ALL_LSDB(on->request_list, lsa, lsanext)) {
2422 if ((length + OSPF6_HEADER_SIZE)
2423 > ospf6_packet_max(on->ospf6_if)) {
2424 ospf6_lsa_unlock(lsa);
2425 if (lsanext)
2426 ospf6_lsa_unlock(lsanext);
2427 break;
2428 }
2429 stream_putw(s, 0); /* reserved */
2430 stream_putw(s, ntohs(lsa->header->type));
2431 stream_putl(s, ntohl(lsa->header->id));
2432 stream_putl(s, ntohl(lsa->header->adv_router));
2433 length += sizeof(struct ospf6_lsreq_entry);
2434 last_req = lsa;
2435 }
2436
2437 if (last_req != NULL) {
2438 if (on->last_ls_req != NULL)
2439 on->last_ls_req = ospf6_lsa_unlock(on->last_ls_req);
2440
2441 ospf6_lsa_lock(last_req);
2442 on->last_ls_req = last_req;
2443 }
2444
2445 return length;
2446 }
2447
2448 static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor *on,
2449 struct ospf6_packet **op)
2450 {
2451 uint16_t length = 0;
2452 struct ospf6_lsa *lsa, *lsanext;
2453 int lsa_cnt = 0;
2454
2455 for (ALL_LSDB(on->lsack_list, lsa, lsanext)) {
2456 if ((length + sizeof(struct ospf6_lsa_header)
2457 + OSPF6_HEADER_SIZE)
2458 > ospf6_packet_max(on->ospf6_if)) {
2459 /* if we run out of packet size/space here,
2460 better to try again soon. */
2461 if (lsa_cnt) {
2462 ospf6_fill_header(on->ospf6_if, (*op)->s,
2463 length + OSPF6_HEADER_SIZE);
2464
2465 (*op)->length = length + OSPF6_HEADER_SIZE;
2466 (*op)->dst = on->linklocal_addr;
2467 ospf6_fill_hdr_checksum(on->ospf6_if, *op);
2468 ospf6_packet_add(on->ospf6_if, *op);
2469 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2470 /* new packet */
2471 *op = ospf6_packet_new(on->ospf6_if->ifmtu);
2472 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK,
2473 on->ospf6_if, (*op)->s);
2474 length = 0;
2475 lsa_cnt = 0;
2476 }
2477 }
2478 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2479 stream_put((*op)->s, lsa->header,
2480 sizeof(struct ospf6_lsa_header));
2481 length += sizeof(struct ospf6_lsa_header);
2482
2483 assert(lsa->lock == 2);
2484 ospf6_lsdb_remove(lsa, on->lsack_list);
2485 lsa_cnt++;
2486 }
2487 return length;
2488 }
2489
2490 void ospf6_lsreq_send(struct thread *thread)
2491 {
2492 struct ospf6_neighbor *on;
2493 struct ospf6_packet *op;
2494 uint16_t length = OSPF6_HEADER_SIZE;
2495
2496 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2497
2498 /* LSReq will be sent only in ExStart or Loading */
2499 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
2500 && on->state != OSPF6_NEIGHBOR_LOADING) {
2501 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND_HDR))
2502 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2503 on->name,
2504 ospf6_neighbor_state_str[on->state]);
2505 return;
2506 }
2507
2508 /* schedule loading_done if request list is empty */
2509 if (on->request_list->count == 0) {
2510 thread_add_event(master, loading_done, on, 0, NULL);
2511 return;
2512 }
2513
2514 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2515 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ, on->ospf6_if, op->s);
2516
2517 length += ospf6_make_lsreq(on, op->s);
2518
2519 if (length == OSPF6_HEADER_SIZE) {
2520 /* Hello overshooting MTU */
2521 ospf6_packet_free(op);
2522 return;
2523 }
2524
2525 /* Fill OSPF header. */
2526 ospf6_fill_header(on->ospf6_if, op->s, length);
2527
2528 /* Set packet length */
2529 op->length = length;
2530
2531 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2532 op->dst = allspfrouters6;
2533 else
2534 op->dst = on->linklocal_addr;
2535
2536 ospf6_fill_hdr_checksum(on->ospf6_if, op);
2537 ospf6_packet_add(on->ospf6_if, op);
2538
2539 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2540
2541 /* set next thread */
2542 if (on->request_list->count != 0) {
2543 thread_add_timer(master, ospf6_lsreq_send, on,
2544 on->ospf6_if->rxmt_interval,
2545 &on->thread_send_lsreq);
2546 }
2547 }
2548
2549 static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
2550 struct ospf6_interface *oi,
2551 struct ospf6_packet *op)
2552 {
2553
2554 if (on) {
2555
2556 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2557 || (on->ospf6_if->state == OSPF6_INTERFACE_DR)
2558 || (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
2559 op->dst = allspfrouters6;
2560 else
2561 op->dst = on->linklocal_addr;
2562 oi = on->ospf6_if;
2563 } else if (oi) {
2564 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2565 || (oi->state == OSPF6_INTERFACE_DR)
2566 || (oi->state == OSPF6_INTERFACE_BDR))
2567 op->dst = allspfrouters6;
2568 else
2569 op->dst = alldrouters6;
2570 }
2571 if (oi) {
2572 ospf6_fill_hdr_checksum(oi, op);
2573 ospf6_packet_add(oi, op);
2574 /* If ospf instance is being deleted, send the packet
2575 * immediately
2576 */
2577 if ((oi->area == NULL) || (oi->area->ospf6 == NULL))
2578 return;
2579 if (oi->area->ospf6->inst_shutdown) {
2580 if (oi->on_write_q == 0) {
2581 listnode_add(oi->area->ospf6->oi_write_q, oi);
2582 oi->on_write_q = 1;
2583 }
2584 thread_execute(master, ospf6_write, oi->area->ospf6, 0);
2585 } else
2586 OSPF6_MESSAGE_WRITE_ON(oi);
2587 }
2588 }
2589
2590 static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor *on,
2591 struct ospf6_packet **op, int *lsa_cnt)
2592 {
2593 uint16_t length = OSPF6_LS_UPD_MIN_SIZE;
2594 struct ospf6_lsa *lsa, *lsanext;
2595
2596 /* skip over fixed header */
2597 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2598
2599 for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) {
2600 if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
2601 ospf6_packet_max(on->ospf6_if)) {
2602 ospf6_fill_header(on->ospf6_if, (*op)->s,
2603 length + OSPF6_HEADER_SIZE);
2604 (*op)->length = length + OSPF6_HEADER_SIZE;
2605 ospf6_fill_lsupdate_header((*op)->s, *lsa_cnt);
2606 ospf6_send_lsupdate(on, NULL, *op);
2607
2608 /* refresh packet */
2609 *op = ospf6_packet_new(on->ospf6_if->ifmtu);
2610 length = OSPF6_LS_UPD_MIN_SIZE;
2611 *lsa_cnt = 0;
2612 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE,
2613 on->ospf6_if, (*op)->s);
2614 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2615 }
2616 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2617 stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2618 (*lsa_cnt)++;
2619 length += OSPF6_LSA_SIZE(lsa->header);
2620 assert(lsa->lock == 2);
2621 ospf6_lsdb_remove(lsa, on->lsupdate_list);
2622 }
2623 return length;
2624 }
2625
2626 static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
2627 struct ospf6_packet **op,
2628 int *lsa_cnt)
2629 {
2630 uint16_t length = OSPF6_LS_UPD_MIN_SIZE;
2631 struct ospf6_lsa *lsa, *lsanext;
2632
2633 /* skip over fixed header */
2634 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2635
2636 for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
2637 if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
2638 ospf6_packet_max(on->ospf6_if)) {
2639 ospf6_fill_header(on->ospf6_if, (*op)->s,
2640 length + OSPF6_HEADER_SIZE);
2641 (*op)->length = length + OSPF6_HEADER_SIZE;
2642 ospf6_fill_lsupdate_header((*op)->s, *lsa_cnt);
2643 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2644 (*op)->dst = allspfrouters6;
2645 else
2646 (*op)->dst = on->linklocal_addr;
2647
2648 ospf6_fill_hdr_checksum(on->ospf6_if, *op);
2649 ospf6_packet_add(on->ospf6_if, *op);
2650 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2651
2652 /* refresh packet */
2653 *op = ospf6_packet_new(on->ospf6_if->ifmtu);
2654 length = OSPF6_LS_UPD_MIN_SIZE;
2655 *lsa_cnt = 0;
2656 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE,
2657 on->ospf6_if, (*op)->s);
2658 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2659 }
2660 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2661 stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2662 (*lsa_cnt)++;
2663 length += OSPF6_LSA_SIZE(lsa->header);
2664 }
2665 return length;
2666 }
2667
2668 void ospf6_lsupdate_send_neighbor(struct thread *thread)
2669 {
2670 struct ospf6_neighbor *on;
2671 struct ospf6_packet *op;
2672 uint16_t length = OSPF6_HEADER_SIZE;
2673 int lsa_cnt = 0;
2674
2675 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2676
2677 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
2678 zlog_debug("LSUpdate to neighbor %s", on->name);
2679
2680 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
2681 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
2682 SEND_HDR))
2683 zlog_debug("Quit to send (neighbor state %s)",
2684 ospf6_neighbor_state_str[on->state]);
2685 return;
2686 }
2687
2688 /* first do lsupdate_list */
2689 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2690 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, on->ospf6_if, op->s);
2691 length += ospf6_make_lsupdate_list(on, &op, &lsa_cnt);
2692 if (lsa_cnt) {
2693 /* Fill OSPF header. */
2694 ospf6_fill_header(on->ospf6_if, op->s, length);
2695 ospf6_fill_lsupdate_header(op->s, lsa_cnt);
2696 op->length = length;
2697 ospf6_send_lsupdate(on, NULL, op);
2698
2699 /* prepare new packet */
2700 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2701 length = OSPF6_HEADER_SIZE;
2702 lsa_cnt = 0;
2703 } else {
2704 stream_reset(op->s);
2705 length = OSPF6_HEADER_SIZE;
2706 }
2707
2708 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, on->ospf6_if, op->s);
2709 /* now do retransmit list */
2710 length += ospf6_make_ls_retrans_list(on, &op, &lsa_cnt);
2711 if (lsa_cnt) {
2712 ospf6_fill_header(on->ospf6_if, op->s, length);
2713 ospf6_fill_lsupdate_header(op->s, lsa_cnt);
2714 op->length = length;
2715 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2716 op->dst = allspfrouters6;
2717 else
2718 op->dst = on->linklocal_addr;
2719 ospf6_fill_hdr_checksum(on->ospf6_if, op);
2720 ospf6_packet_add(on->ospf6_if, op);
2721 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2722 } else
2723 ospf6_packet_free(op);
2724
2725 if (on->lsupdate_list->count != 0) {
2726 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
2727 &on->thread_send_lsupdate);
2728 } else if (on->retrans_list->count != 0) {
2729 thread_add_timer(master, ospf6_lsupdate_send_neighbor, on,
2730 on->ospf6_if->rxmt_interval,
2731 &on->thread_send_lsupdate);
2732 }
2733 }
2734
2735 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
2736 struct ospf6_lsa *lsa)
2737 {
2738 struct ospf6_packet *op;
2739 uint16_t length = OSPF6_HEADER_SIZE;
2740
2741 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2742 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, on->ospf6_if, op->s);
2743
2744 /* skip over fixed header */
2745 stream_forward_endp(op->s, OSPF6_LS_UPD_MIN_SIZE);
2746 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2747 stream_put(op->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2748 length = OSPF6_HEADER_SIZE + OSPF6_LS_UPD_MIN_SIZE
2749 + OSPF6_LSA_SIZE(lsa->header);
2750 ospf6_fill_header(on->ospf6_if, op->s, length);
2751 ospf6_fill_lsupdate_header(op->s, 1);
2752 op->length = length;
2753
2754 if (IS_OSPF6_DEBUG_FLOODING
2755 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
2756 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__,
2757 lsa->name, ntohs(lsa->header->age));
2758
2759 ospf6_send_lsupdate(on, NULL, op);
2760
2761 return 0;
2762 }
2763
2764 static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface *oi,
2765 struct ospf6_packet **op,
2766 int *lsa_cnt)
2767 {
2768 uint16_t length = OSPF6_LS_UPD_MIN_SIZE;
2769 struct ospf6_lsa *lsa, *lsanext;
2770
2771 /* skip over fixed header */
2772 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2773
2774 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext)) {
2775 if (length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE >
2776 ospf6_packet_max(oi)) {
2777 ospf6_fill_header(oi, (*op)->s,
2778 length + OSPF6_HEADER_SIZE);
2779 (*op)->length = length + OSPF6_HEADER_SIZE;
2780 ospf6_fill_lsupdate_header((*op)->s, *lsa_cnt);
2781 ospf6_send_lsupdate(NULL, oi, *op);
2782
2783 /* refresh packet */
2784 *op = ospf6_packet_new(oi->ifmtu);
2785 length = OSPF6_LS_UPD_MIN_SIZE;
2786 *lsa_cnt = 0;
2787 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, oi,
2788 (*op)->s);
2789 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2790 }
2791
2792 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2793 stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2794 (*lsa_cnt)++;
2795 length += OSPF6_LSA_SIZE(lsa->header);
2796
2797 assert(lsa->lock == 2);
2798 ospf6_lsdb_remove(lsa, oi->lsupdate_list);
2799 }
2800 return length;
2801 }
2802
2803 void ospf6_lsupdate_send_interface(struct thread *thread)
2804 {
2805 struct ospf6_interface *oi;
2806 struct ospf6_packet *op;
2807 uint16_t length = OSPF6_HEADER_SIZE;
2808 int lsa_cnt = 0;
2809
2810 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2811
2812 if (oi->state <= OSPF6_INTERFACE_WAITING) {
2813 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
2814 SEND_HDR))
2815 zlog_debug(
2816 "Quit to send LSUpdate to interface %s state %s",
2817 oi->interface->name,
2818 ospf6_interface_state_str[oi->state]);
2819 return;
2820 }
2821
2822 /* if we have nothing to send, return */
2823 if (oi->lsupdate_list->count == 0)
2824 return;
2825
2826 op = ospf6_packet_new(oi->ifmtu);
2827 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, oi, op->s);
2828 length += ospf6_make_lsupdate_interface(oi, &op, &lsa_cnt);
2829 if (lsa_cnt) {
2830 /* Fill OSPF header. */
2831 ospf6_fill_header(oi, op->s, length);
2832 ospf6_fill_lsupdate_header(op->s, lsa_cnt);
2833 op->length = length;
2834 ospf6_send_lsupdate(NULL, oi, op);
2835 } else
2836 ospf6_packet_free(op);
2837
2838 if (oi->lsupdate_list->count > 0) {
2839 thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0,
2840 &oi->thread_send_lsupdate);
2841 }
2842 }
2843
2844 void ospf6_lsack_send_neighbor(struct thread *thread)
2845 {
2846 struct ospf6_neighbor *on;
2847 struct ospf6_packet *op;
2848 uint16_t length = OSPF6_HEADER_SIZE;
2849
2850 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2851
2852 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
2853 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
2854 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2855 on->name,
2856 ospf6_neighbor_state_str[on->state]);
2857 return;
2858 }
2859
2860 /* if we have nothing to send, return */
2861 if (on->lsack_list->count == 0)
2862 return;
2863
2864 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2865 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK, on->ospf6_if, op->s);
2866
2867 length += ospf6_make_lsack_neighbor(on, &op);
2868
2869 if (length == OSPF6_HEADER_SIZE) {
2870 ospf6_packet_free(op);
2871 return;
2872 }
2873
2874 /* Fill OSPF header. */
2875 ospf6_fill_header(on->ospf6_if, op->s, length);
2876
2877 /* Set packet length, dst and queue to FIFO. */
2878 op->length = length;
2879 op->dst = on->linklocal_addr;
2880 ospf6_fill_hdr_checksum(on->ospf6_if, op);
2881 ospf6_packet_add(on->ospf6_if, op);
2882 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2883
2884 if (on->lsack_list->count > 0)
2885 thread_add_event(master, ospf6_lsack_send_neighbor, on, 0,
2886 &on->thread_send_lsack);
2887 }
2888
2889 static uint16_t ospf6_make_lsack_interface(struct ospf6_interface *oi,
2890 struct ospf6_packet *op)
2891 {
2892 uint16_t length = 0;
2893 struct ospf6_lsa *lsa, *lsanext;
2894
2895 for (ALL_LSDB(oi->lsack_list, lsa, lsanext)) {
2896 if ((length + sizeof(struct ospf6_lsa_header)
2897 + OSPF6_HEADER_SIZE)
2898 > ospf6_packet_max(oi)) {
2899 /* if we run out of packet size/space here,
2900 better to try again soon. */
2901 THREAD_OFF(oi->thread_send_lsack);
2902 thread_add_event(master, ospf6_lsack_send_interface, oi,
2903 0, &oi->thread_send_lsack);
2904
2905 ospf6_lsa_unlock(lsa);
2906 if (lsanext)
2907 ospf6_lsa_unlock(lsanext);
2908 break;
2909 }
2910 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2911 stream_put(op->s, lsa->header, sizeof(struct ospf6_lsa_header));
2912 length += sizeof(struct ospf6_lsa_header);
2913
2914 assert(lsa->lock == 2);
2915 ospf6_lsdb_remove(lsa, oi->lsack_list);
2916 }
2917 return length;
2918 }
2919
2920 void ospf6_lsack_send_interface(struct thread *thread)
2921 {
2922 struct ospf6_interface *oi;
2923 struct ospf6_packet *op;
2924 uint16_t length = OSPF6_HEADER_SIZE;
2925
2926 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2927
2928 if (oi->state <= OSPF6_INTERFACE_WAITING) {
2929 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
2930 zlog_debug(
2931 "Quit to send LSAck to interface %s state %s",
2932 oi->interface->name,
2933 ospf6_interface_state_str[oi->state]);
2934 return;
2935 }
2936
2937 /* if we have nothing to send, return */
2938 if (oi->lsack_list->count == 0)
2939 return;
2940
2941 op = ospf6_packet_new(oi->ifmtu);
2942 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK, oi, op->s);
2943
2944 length += ospf6_make_lsack_interface(oi, op);
2945
2946 if (length == OSPF6_HEADER_SIZE) {
2947 ospf6_packet_free(op);
2948 return;
2949 }
2950 /* Fill OSPF header. */
2951 ospf6_fill_header(oi, op->s, length);
2952
2953 /* Set packet length, dst and queue to FIFO. */
2954 op->length = length;
2955 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2956 || (oi->state == OSPF6_INTERFACE_DR)
2957 || (oi->state == OSPF6_INTERFACE_BDR))
2958 op->dst = allspfrouters6;
2959 else
2960 op->dst = alldrouters6;
2961
2962 ospf6_fill_hdr_checksum(oi, op);
2963 ospf6_packet_add(oi, op);
2964 OSPF6_MESSAGE_WRITE_ON(oi);
2965
2966 if (oi->lsack_list->count > 0)
2967 thread_add_event(master, ospf6_lsack_send_interface, oi, 0,
2968 &oi->thread_send_lsack);
2969 }
2970
2971 /* Commands */
2972 DEFUN(debug_ospf6_message, debug_ospf6_message_cmd,
2973 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2974 DEBUG_STR OSPF6_STR
2975 "Debug OSPFv3 message\n"
2976 "Debug Unknown message\n"
2977 "Debug Hello message\n"
2978 "Debug Database Description message\n"
2979 "Debug Link State Request message\n"
2980 "Debug Link State Update message\n"
2981 "Debug Link State Acknowledgement message\n"
2982 "Debug All message\n"
2983 "Debug only sending message, entire packet\n"
2984 "Debug only receiving message, entire packet\n"
2985 "Debug only sending message, header only\n"
2986 "Debug only receiving message, header only\n")
2987 {
2988 int idx_packet = 3;
2989 int idx_send_recv = 4;
2990 unsigned char level = 0;
2991 int type = 0;
2992 int i;
2993
2994 /* check type */
2995 if (!strncmp(argv[idx_packet]->arg, "u", 1))
2996 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2997 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
2998 type = OSPF6_MESSAGE_TYPE_HELLO;
2999 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
3000 type = OSPF6_MESSAGE_TYPE_DBDESC;
3001 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
3002 type = OSPF6_MESSAGE_TYPE_LSREQ;
3003 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
3004 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
3005 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
3006 type = OSPF6_MESSAGE_TYPE_LSACK;
3007 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
3008 type = OSPF6_MESSAGE_TYPE_ALL;
3009
3010 if (argc == 4)
3011 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
3012 else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
3013 level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
3014 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
3015 level = OSPF6_DEBUG_MESSAGE_SEND;
3016 else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
3017 level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
3018 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
3019 level = OSPF6_DEBUG_MESSAGE_RECV;
3020
3021 if (type == OSPF6_MESSAGE_TYPE_ALL) {
3022 for (i = 0; i < 6; i++)
3023 OSPF6_DEBUG_MESSAGE_ON(i, level);
3024 } else
3025 OSPF6_DEBUG_MESSAGE_ON(type, level);
3026
3027 return CMD_SUCCESS;
3028 }
3029
3030 DEFUN(no_debug_ospf6_message, no_debug_ospf6_message_cmd,
3031 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
3032 NO_STR DEBUG_STR OSPF6_STR
3033 "Debug OSPFv3 message\n"
3034 "Debug Unknown message\n"
3035 "Debug Hello message\n"
3036 "Debug Database Description message\n"
3037 "Debug Link State Request message\n"
3038 "Debug Link State Update message\n"
3039 "Debug Link State Acknowledgement message\n"
3040 "Debug All message\n"
3041 "Debug only sending message, entire pkt\n"
3042 "Debug only receiving message, entire pkt\n"
3043 "Debug only sending message, header only\n"
3044 "Debug only receiving message, header only\n")
3045 {
3046 int idx_packet = 4;
3047 int idx_send_recv = 5;
3048 unsigned char level = 0;
3049 int type = 0;
3050 int i;
3051
3052 /* check type */
3053 if (!strncmp(argv[idx_packet]->arg, "u", 1))
3054 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
3055 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
3056 type = OSPF6_MESSAGE_TYPE_HELLO;
3057 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
3058 type = OSPF6_MESSAGE_TYPE_DBDESC;
3059 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
3060 type = OSPF6_MESSAGE_TYPE_LSREQ;
3061 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
3062 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
3063 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
3064 type = OSPF6_MESSAGE_TYPE_LSACK;
3065 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
3066 type = OSPF6_MESSAGE_TYPE_ALL;
3067
3068 if (argc == 5)
3069 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV
3070 | OSPF6_DEBUG_MESSAGE_SEND_HDR
3071 | OSPF6_DEBUG_MESSAGE_RECV_HDR;
3072 else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
3073 level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
3074 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
3075 level = OSPF6_DEBUG_MESSAGE_SEND;
3076 else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
3077 level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
3078 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
3079 level = OSPF6_DEBUG_MESSAGE_RECV;
3080
3081 if (type == OSPF6_MESSAGE_TYPE_ALL) {
3082 for (i = 0; i < 6; i++)
3083 OSPF6_DEBUG_MESSAGE_OFF(i, level);
3084 } else
3085 OSPF6_DEBUG_MESSAGE_OFF(type, level);
3086
3087 return CMD_SUCCESS;
3088 }
3089
3090
3091 int config_write_ospf6_debug_message(struct vty *vty)
3092 {
3093 const char *type_str[] = {"unknown", "hello", "dbdesc",
3094 "lsreq", "lsupdate", "lsack"};
3095 unsigned char s = 0, r = 0, sh = 0, rh = 0;
3096 int i;
3097
3098 for (i = 0; i < 6; i++) {
3099 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
3100 s |= 1 << i;
3101 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
3102 r |= 1 << i;
3103 }
3104
3105 for (i = 0; i < 6; i++) {
3106 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
3107 sh |= 1 << i;
3108 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
3109 rh |= 1 << i;
3110 }
3111
3112 if (s == 0x3f && r == 0x3f) {
3113 vty_out(vty, "debug ospf6 message all\n");
3114 return 0;
3115 }
3116
3117 if (s == 0x3f && r == 0) {
3118 vty_out(vty, "debug ospf6 message all send\n");
3119 return 0;
3120 } else if (s == 0 && r == 0x3f) {
3121 vty_out(vty, "debug ospf6 message all recv\n");
3122 return 0;
3123 }
3124
3125 if (sh == 0x3f && rh == 0) {
3126 vty_out(vty, "debug ospf6 message all send-hdr\n");
3127 return 0;
3128 } else if (sh == 0 && rh == 0x3f) {
3129 vty_out(vty, "debug ospf6 message all recv-hdr\n");
3130 return 0;
3131 }
3132
3133 /* Unknown message is logged by default */
3134 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND)
3135 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
3136 vty_out(vty, "no debug ospf6 message unknown\n");
3137 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
3138 vty_out(vty, "no debug ospf6 message unknown send\n");
3139 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
3140 vty_out(vty, "no debug ospf6 message unknown recv\n");
3141
3142 for (i = 1; i < 6; i++) {
3143 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND)
3144 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV)) {
3145 vty_out(vty, "debug ospf6 message %s\n", type_str[i]);
3146 continue;
3147 }
3148
3149 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
3150 vty_out(vty, "debug ospf6 message %s send\n",
3151 type_str[i]);
3152 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
3153 vty_out(vty, "debug ospf6 message %s send-hdr\n",
3154 type_str[i]);
3155
3156 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
3157 vty_out(vty, "debug ospf6 message %s recv\n",
3158 type_str[i]);
3159 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
3160 vty_out(vty, "debug ospf6 message %s recv-hdr\n",
3161 type_str[i]);
3162 }
3163
3164 return 0;
3165 }
3166
3167 void install_element_ospf6_debug_message(void)
3168 {
3169 install_element(ENABLE_NODE, &debug_ospf6_message_cmd);
3170 install_element(ENABLE_NODE, &no_debug_ospf6_message_cmd);
3171 install_element(CONFIG_NODE, &debug_ospf6_message_cmd);
3172 install_element(CONFIG_NODE, &no_debug_ospf6_message_cmd);
3173 }