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