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