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