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