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