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