blob: dcbb36bf559b78eb8737b2fd6fa1f9d1ce72eb32 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
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
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
hasso3b4cd3a2004-05-18 19:28:32 +000024#include "memory.h"
hasso508e53e2004-05-18 18:57:06 +000025#include "log.h"
26#include "vty.h"
27#include "command.h"
28#include "thread.h"
29#include "linklist.h"
30
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
34#include "ospf6_network.h"
35#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000036
hasso508e53e2004-05-18 18:57:06 +000037#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_neighbor.h"
40#include "ospf6_interface.h"
41
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040042/* for structures and macros ospf6_lsa_examin() needs */
43#include "ospf6_abr.h"
44#include "ospf6_asbr.h"
45#include "ospf6_intra.h"
46
hasso508e53e2004-05-18 18:57:06 +000047#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000048#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000049
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +040050#include <netinet/ip6.h>
51
hasso508e53e2004-05-18 18:57:06 +000052unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
Denis Ovsienko5031ed12011-10-14 21:59:58 +040053static const struct message ospf6_message_type_str [] =
54{
55 { OSPF6_MESSAGE_TYPE_HELLO, "Hello" },
56 { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" },
57 { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" },
58 { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" },
59 { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" },
60};
Balaji.G837d16c2012-09-26 14:09:10 +053061static const size_t ospf6_message_type_str_max = array_size(ospf6_message_type_str);
hasso508e53e2004-05-18 18:57:06 +000062
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040063/* Minimum (besides the standard OSPF packet header) lengths for OSPF
64 packets of particular types, offset is the "type" field. */
65const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
66{
67 0,
68 OSPF6_HELLO_MIN_SIZE,
69 OSPF6_DB_DESC_MIN_SIZE,
70 OSPF6_LS_REQ_MIN_SIZE,
71 OSPF6_LS_UPD_MIN_SIZE,
72 OSPF6_LS_ACK_MIN_SIZE
73};
74
75/* Minimum (besides the standard LSA header) lengths for LSAs of particular
76 types, offset is the "LSA function code" portion of "LSA type" field. */
77const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
78{
79 0,
80 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
81 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
82 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
83 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
84 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
85 /* 0x2006 */ 0,
86 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
87 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
88 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
89};
90
hasso508e53e2004-05-18 18:57:06 +000091/* print functions */
92
93static void
94ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000095{
hasso508e53e2004-05-18 18:57:06 +000096 char router_id[16], area_id[16];
97 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
98 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000099
hassoc6487d62004-12-24 06:00:11 +0000100 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +0000101 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +0000102 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +0000103 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +0000104}
paul718e3742002-12-13 20:15:29 +0000105
106void
hasso508e53e2004-05-18 18:57:06 +0000107ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000108{
paul718e3742002-12-13 20:15:29 +0000109 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000110 char options[16];
111 char drouter[16], bdrouter[16], neighbor[16];
112 char *p;
paul718e3742002-12-13 20:15:29 +0000113
hasso508e53e2004-05-18 18:57:06 +0000114 ospf6_header_print (oh);
115 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000116
hasso508e53e2004-05-18 18:57:06 +0000117 hello = (struct ospf6_hello *)
118 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000119
hasso508e53e2004-05-18 18:57:06 +0000120 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
121 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
122 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000123
hassoc6487d62004-12-24 06:00:11 +0000124 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000125 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000126 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000127 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000128 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000129
hasso508e53e2004-05-18 18:57:06 +0000130 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
131 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
132 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000133 {
hasso508e53e2004-05-18 18:57:06 +0000134 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000135 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000136 }
hasso508e53e2004-05-18 18:57:06 +0000137
Denis Ovsienkofa079662011-10-08 17:22:45 +0400138 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000139}
140
hasso508e53e2004-05-18 18:57:06 +0000141void
142ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000143{
paul718e3742002-12-13 20:15:29 +0000144 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000145 char options[16];
146 char *p;
paul718e3742002-12-13 20:15:29 +0000147
hasso508e53e2004-05-18 18:57:06 +0000148 ospf6_header_print (oh);
149 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000150
hasso508e53e2004-05-18 18:57:06 +0000151 dbdesc = (struct ospf6_dbdesc *)
152 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000153
hasso508e53e2004-05-18 18:57:06 +0000154 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000155
hassoc6487d62004-12-24 06:00:11 +0000156 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000157 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000158 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000159 dbdesc->reserved2,
160 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
161 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
162 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
163 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000164
hasso508e53e2004-05-18 18:57:06 +0000165 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
166 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
167 p += sizeof (struct ospf6_lsa_header))
168 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
169
Denis Ovsienkofa079662011-10-08 17:22:45 +0400170 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000171}
172
hasso508e53e2004-05-18 18:57:06 +0000173void
174ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000175{
hasso508e53e2004-05-18 18:57:06 +0000176 char id[16], adv_router[16];
177 char *p;
paul718e3742002-12-13 20:15:29 +0000178
hasso508e53e2004-05-18 18:57:06 +0000179 ospf6_header_print (oh);
180 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000181
hasso508e53e2004-05-18 18:57:06 +0000182 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
183 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
184 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000185 {
hasso508e53e2004-05-18 18:57:06 +0000186 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
187 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
188 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000189 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000190 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000191 }
hasso508e53e2004-05-18 18:57:06 +0000192
Denis Ovsienkofa079662011-10-08 17:22:45 +0400193 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000194}
195
hasso508e53e2004-05-18 18:57:06 +0000196void
197ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000198{
paul718e3742002-12-13 20:15:29 +0000199 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000200 u_long num;
201 char *p;
paul718e3742002-12-13 20:15:29 +0000202
hasso508e53e2004-05-18 18:57:06 +0000203 ospf6_header_print (oh);
204 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000205
hasso508e53e2004-05-18 18:57:06 +0000206 lsupdate = (struct ospf6_lsupdate *)
207 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000208
hasso508e53e2004-05-18 18:57:06 +0000209 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000210 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000211
hasso508e53e2004-05-18 18:57:06 +0000212 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
213 p < OSPF6_MESSAGE_END (oh) &&
214 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
215 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000216 {
hasso508e53e2004-05-18 18:57:06 +0000217 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000218 }
paul718e3742002-12-13 20:15:29 +0000219
Denis Ovsienkofa079662011-10-08 17:22:45 +0400220 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000221}
222
hasso508e53e2004-05-18 18:57:06 +0000223void
224ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000225{
hasso508e53e2004-05-18 18:57:06 +0000226 char *p;
paul718e3742002-12-13 20:15:29 +0000227
hasso508e53e2004-05-18 18:57:06 +0000228 ospf6_header_print (oh);
229 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000230
hasso508e53e2004-05-18 18:57:06 +0000231 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
232 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
233 p += sizeof (struct ospf6_lsa_header))
234 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
235
Denis Ovsienkofa079662011-10-08 17:22:45 +0400236 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000237}
238
Paul Jakma6ac29a52008-08-15 13:45:30 +0100239static void
hasso508e53e2004-05-18 18:57:06 +0000240ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
241 struct ospf6_interface *oi, struct ospf6_header *oh)
242{
243 struct ospf6_hello *hello;
244 struct ospf6_neighbor *on;
245 char *p;
246 int twoway = 0;
247 int neighborchange = 0;
248 int backupseen = 0;
249
hasso508e53e2004-05-18 18:57:06 +0000250 hello = (struct ospf6_hello *)
251 ((caddr_t) oh + sizeof (struct ospf6_header));
252
paul718e3742002-12-13 20:15:29 +0000253 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000254 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000255 {
hasso508e53e2004-05-18 18:57:06 +0000256 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000257 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000258 return;
259 }
260
261 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000262 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000263 {
hasso508e53e2004-05-18 18:57:06 +0000264 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000265 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000266 return;
267 }
268
hasso508e53e2004-05-18 18:57:06 +0000269 /* E-bit check */
270 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
271 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000272 {
hasso508e53e2004-05-18 18:57:06 +0000273 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000274 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000275 return;
276 }
277
hasso508e53e2004-05-18 18:57:06 +0000278 /* Find neighbor, create if not exist */
279 on = ospf6_neighbor_lookup (oh->router_id, oi);
280 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000281 {
hasso508e53e2004-05-18 18:57:06 +0000282 on = ospf6_neighbor_create (oh->router_id, oi);
283 on->prev_drouter = on->drouter = hello->drouter;
284 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
285 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000286 }
287
hasso7b6ae022005-06-24 08:17:51 +0000288 /* always override neighbor's source address and ifindex */
289 on->ifindex = ntohl (hello->interface_id);
290 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
291
paul718e3742002-12-13 20:15:29 +0000292 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000293 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
294 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
295 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000296 {
hasso508e53e2004-05-18 18:57:06 +0000297 u_int32_t *router_id = (u_int32_t *) p;
298
299 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000300 twoway++;
paul718e3742002-12-13 20:15:29 +0000301 }
302
Denis Ovsienkofa079662011-10-08 17:22:45 +0400303 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000304
305 /* RouterPriority check */
306 if (on->priority != hello->priority)
307 {
308 on->priority = hello->priority;
309 neighborchange++;
310 }
311
312 /* DR check */
313 if (on->drouter != hello->drouter)
314 {
315 on->prev_drouter = on->drouter;
316 on->drouter = hello->drouter;
317 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
318 neighborchange++;
319 }
320
321 /* BDR check */
322 if (on->bdrouter != hello->bdrouter)
323 {
324 on->prev_bdrouter = on->bdrouter;
325 on->bdrouter = hello->bdrouter;
326 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
327 neighborchange++;
328 }
paul718e3742002-12-13 20:15:29 +0000329
330 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000331 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000332 {
hasso508e53e2004-05-18 18:57:06 +0000333 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000334 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000335 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000336 backupseen++;
337 }
338
hasso508e53e2004-05-18 18:57:06 +0000339 /* Execute neighbor events */
340 thread_execute (master, hello_received, on, 0);
341 if (twoway)
342 thread_execute (master, twoway_received, on, 0);
343 else
344 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000345
hasso508e53e2004-05-18 18:57:06 +0000346 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000347 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000348 thread_add_event (master, backup_seen, oi, 0);
349 if (neighborchange)
350 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000351}
352
hasso508e53e2004-05-18 18:57:06 +0000353static void
354ospf6_dbdesc_recv_master (struct ospf6_header *oh,
355 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000356{
paul718e3742002-12-13 20:15:29 +0000357 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000358 char *p;
paul718e3742002-12-13 20:15:29 +0000359
hasso508e53e2004-05-18 18:57:06 +0000360 dbdesc = (struct ospf6_dbdesc *)
361 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000362
hasso508e53e2004-05-18 18:57:06 +0000363 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000364 {
hasso508e53e2004-05-18 18:57:06 +0000365 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000366 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000367 return;
368 }
369
hasso508e53e2004-05-18 18:57:06 +0000370 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000371 {
hasso508e53e2004-05-18 18:57:06 +0000372 case OSPF6_NEIGHBOR_TWOWAY:
373 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000374 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000375 return;
376
377 case OSPF6_NEIGHBOR_INIT:
378 thread_execute (master, twoway_received, on, 0);
379 if (on->state != OSPF6_NEIGHBOR_EXSTART)
380 {
381 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000382 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000383 return;
384 }
385 /* else fall through to ExStart */
386
387 case OSPF6_NEIGHBOR_EXSTART:
388 /* if neighbor obeys us as our slave, schedule negotiation_done
389 and process LSA Headers. Otherwise, ignore this message */
390 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
391 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
392 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
393 {
394 /* execute NegotiationDone */
395 thread_execute (master, negotiation_done, on, 0);
396
397 /* Record neighbor options */
398 memcpy (on->options, dbdesc->options, sizeof (on->options));
399 }
400 else
401 {
402 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000403 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000404 return;
405 }
406 /* fall through to exchange */
407
408 case OSPF6_NEIGHBOR_EXCHANGE:
409 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
410 {
411 /* Duplicated DatabaseDescription is dropped by master */
412 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000413 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000414 return;
415 }
416
417 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
418 {
419 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000420 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000421 thread_add_event (master, seqnumber_mismatch, on, 0);
422 return;
423 }
424
425 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
426 {
427 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000428 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000429 thread_add_event (master, seqnumber_mismatch, on, 0);
430 return;
431 }
432
433 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
434 {
435 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000436 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000437 thread_add_event (master, seqnumber_mismatch, on, 0);
438 return;
439 }
440
441 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
442 {
443 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000444 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000445 (u_long) on->dbdesc_seqnum);
446 thread_add_event (master, seqnumber_mismatch, on, 0);
447 return;
448 }
449 break;
450
451 case OSPF6_NEIGHBOR_LOADING:
452 case OSPF6_NEIGHBOR_FULL:
453 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
454 {
455 /* Duplicated DatabaseDescription is dropped by master */
456 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000457 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000458 return;
459 }
460
461 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000462 zlog_debug ("Not duplicate dbdesc in state %s",
463 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000464 thread_add_event (master, seqnumber_mismatch, on, 0);
465 return;
466
467 default:
468 assert (0);
469 break;
470 }
471
472 /* Process LSA headers */
473 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
474 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
475 p += sizeof (struct ospf6_lsa_header))
476 {
477 struct ospf6_lsa *his, *mine;
478 struct ospf6_lsdb *lsdb = NULL;
479
480 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000481
482 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000483 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000484
485 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000486 {
hasso6452df02004-08-15 05:52:07 +0000487 case OSPF6_SCOPE_LINKLOCAL:
488 lsdb = on->ospf6_if->lsdb;
489 break;
490 case OSPF6_SCOPE_AREA:
491 lsdb = on->ospf6_if->area->lsdb;
492 break;
493 case OSPF6_SCOPE_AS:
494 lsdb = on->ospf6_if->area->ospf6->lsdb;
495 break;
496 case OSPF6_SCOPE_RESERVED:
497 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000498 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000499 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000500 continue;
501 break;
hasso508e53e2004-05-18 18:57:06 +0000502 }
503
504 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000505 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000506 {
507 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000508 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000509 ospf6_lsa_delete (his);
510 thread_add_event (master, seqnumber_mismatch, on, 0);
511 return;
512 }
513
514 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
515 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000516 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000517 {
hasso6452df02004-08-15 05:52:07 +0000518 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000519 zlog_debug ("Add request (No database copy)");
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000520 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso6452df02004-08-15 05:52:07 +0000521 }
522 else if (ospf6_lsa_compare (his, mine) < 0)
523 {
524 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000525 zlog_debug ("Add request (Received MoreRecent)");
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000526 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso508e53e2004-05-18 18:57:06 +0000527 }
528 else
hasso6452df02004-08-15 05:52:07 +0000529 {
530 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000531 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000532 }
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000533 ospf6_lsa_delete (his);
hasso508e53e2004-05-18 18:57:06 +0000534 }
535
Denis Ovsienkofa079662011-10-08 17:22:45 +0400536 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000537
538 /* Increment sequence number */
539 on->dbdesc_seqnum ++;
540
541 /* schedule send lsreq */
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000542 if (on->request_list->count && (on->thread_send_lsreq == NULL))
hasso508e53e2004-05-18 18:57:06 +0000543 on->thread_send_lsreq =
544 thread_add_event (master, ospf6_lsreq_send, on, 0);
545
546 THREAD_OFF (on->thread_send_dbdesc);
547
548 /* More bit check */
549 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
550 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
551 thread_add_event (master, exchange_done, on, 0);
552 else
553 on->thread_send_dbdesc =
554 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
555
556 /* save last received dbdesc */
557 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
558}
559
560static void
561ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
562 struct ospf6_neighbor *on)
563{
564 struct ospf6_dbdesc *dbdesc;
565 char *p;
566
567 dbdesc = (struct ospf6_dbdesc *)
568 ((caddr_t) oh + sizeof (struct ospf6_header));
569
570 if (on->state < OSPF6_NEIGHBOR_INIT)
571 {
572 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000573 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000574 return;
575 }
576
hasso508e53e2004-05-18 18:57:06 +0000577 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000578 {
hasso508e53e2004-05-18 18:57:06 +0000579 case OSPF6_NEIGHBOR_TWOWAY:
580 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000581 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000582 return;
583
584 case OSPF6_NEIGHBOR_INIT:
585 thread_execute (master, twoway_received, on, 0);
586 if (on->state != OSPF6_NEIGHBOR_EXSTART)
587 {
588 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000589 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000590 return;
591 }
592 /* else fall through to ExStart */
593
594 case OSPF6_NEIGHBOR_EXSTART:
595 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
596 and process LSA Headers. Otherwise, ignore this message */
597 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
598 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
599 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
600 ntohs (oh->length) == sizeof (struct ospf6_header) +
601 sizeof (struct ospf6_dbdesc))
602 {
603 /* set the master/slave bit to slave */
604 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
605
606 /* set the DD sequence number to one specified by master */
607 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
608
609 /* schedule NegotiationDone */
610 thread_execute (master, negotiation_done, on, 0);
611
612 /* Record neighbor options */
613 memcpy (on->options, dbdesc->options, sizeof (on->options));
614 }
615 else
616 {
617 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000618 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000619 return;
620 }
621 break;
622
623 case OSPF6_NEIGHBOR_EXCHANGE:
624 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
625 {
626 /* Duplicated DatabaseDescription causes slave to retransmit */
627 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000628 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000629 THREAD_OFF (on->thread_send_dbdesc);
630 on->thread_send_dbdesc =
631 thread_add_event (master, ospf6_dbdesc_send, on, 0);
632 return;
633 }
634
635 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
636 {
637 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000638 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000639 thread_add_event (master, seqnumber_mismatch, on, 0);
640 return;
641 }
642
643 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
644 {
645 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000646 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000647 thread_add_event (master, seqnumber_mismatch, on, 0);
648 return;
649 }
650
651 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
652 {
653 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000654 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000655 thread_add_event (master, seqnumber_mismatch, on, 0);
656 return;
657 }
658
659 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
660 {
661 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000662 zlog_debug ("Sequence number mismatch (%#lx expected)",
663 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000664 thread_add_event (master, seqnumber_mismatch, on, 0);
665 return;
666 }
667 break;
668
669 case OSPF6_NEIGHBOR_LOADING:
670 case OSPF6_NEIGHBOR_FULL:
671 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
672 {
673 /* Duplicated DatabaseDescription causes slave to retransmit */
674 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000675 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000676 THREAD_OFF (on->thread_send_dbdesc);
677 on->thread_send_dbdesc =
678 thread_add_event (master, ospf6_dbdesc_send, on, 0);
679 return;
680 }
681
682 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000683 zlog_debug ("Not duplicate dbdesc in state %s",
684 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000685 thread_add_event (master, seqnumber_mismatch, on, 0);
686 return;
687
688 default:
689 assert (0);
690 break;
paul718e3742002-12-13 20:15:29 +0000691 }
692
hasso508e53e2004-05-18 18:57:06 +0000693 /* Process LSA headers */
694 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
695 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
696 p += sizeof (struct ospf6_lsa_header))
697 {
698 struct ospf6_lsa *his, *mine;
699 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000700
hasso508e53e2004-05-18 18:57:06 +0000701 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000702
703 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000704 {
hasso6452df02004-08-15 05:52:07 +0000705 case OSPF6_SCOPE_LINKLOCAL:
706 lsdb = on->ospf6_if->lsdb;
707 break;
708 case OSPF6_SCOPE_AREA:
709 lsdb = on->ospf6_if->area->lsdb;
710 break;
711 case OSPF6_SCOPE_AS:
712 lsdb = on->ospf6_if->area->ospf6->lsdb;
713 break;
714 case OSPF6_SCOPE_RESERVED:
715 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000716 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000717 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000718 continue;
719 break;
hasso508e53e2004-05-18 18:57:06 +0000720 }
721
hasso6452df02004-08-15 05:52:07 +0000722 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
723 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000724 {
725 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000726 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000727 ospf6_lsa_delete (his);
728 thread_add_event (master, seqnumber_mismatch, on, 0);
729 return;
730 }
731
732 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
733 his->header->adv_router, lsdb);
734 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
735 {
hasso6452df02004-08-15 05:52:07 +0000736 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000737 zlog_debug ("Add request-list: %s", his->name);
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000738 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso508e53e2004-05-18 18:57:06 +0000739 }
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000740 ospf6_lsa_delete (his);
hasso508e53e2004-05-18 18:57:06 +0000741 }
742
Denis Ovsienkofa079662011-10-08 17:22:45 +0400743 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000744
745 /* Set sequence number to Master's */
746 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
747
748 /* schedule send lsreq */
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000749 if ((on->thread_send_lsreq == NULL) &&
750 (on->request_list->count))
hasso508e53e2004-05-18 18:57:06 +0000751 on->thread_send_lsreq =
752 thread_add_event (master, ospf6_lsreq_send, on, 0);
753
754 THREAD_OFF (on->thread_send_dbdesc);
755 on->thread_send_dbdesc =
756 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
757
758 /* save last received dbdesc */
759 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000760}
761
Paul Jakma6ac29a52008-08-15 13:45:30 +0100762static void
hasso508e53e2004-05-18 18:57:06 +0000763ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
764 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000765{
hasso508e53e2004-05-18 18:57:06 +0000766 struct ospf6_neighbor *on;
767 struct ospf6_dbdesc *dbdesc;
768
hasso508e53e2004-05-18 18:57:06 +0000769 on = ospf6_neighbor_lookup (oh->router_id, oi);
770 if (on == NULL)
771 {
772 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000773 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000774 return;
775 }
776
hasso508e53e2004-05-18 18:57:06 +0000777 dbdesc = (struct ospf6_dbdesc *)
778 ((caddr_t) oh + sizeof (struct ospf6_header));
779
780 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400781 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000782 {
783 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000784 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000785 return;
786 }
787
788 if (dbdesc->reserved1 || dbdesc->reserved2)
789 {
790 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000791 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
792 on->name);
hasso508e53e2004-05-18 18:57:06 +0000793 dbdesc->reserved1 = 0;
794 dbdesc->reserved2 = 0;
795 }
796
797 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
798 ospf6_dbdesc_recv_master (oh, on);
799 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
800 ospf6_dbdesc_recv_slave (oh, on);
801 else
802 {
803 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000804 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000805 }
806}
807
Paul Jakma6ac29a52008-08-15 13:45:30 +0100808static void
hasso508e53e2004-05-18 18:57:06 +0000809ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
810 struct ospf6_interface *oi, struct ospf6_header *oh)
811{
812 struct ospf6_neighbor *on;
813 char *p;
814 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000815 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000816 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000817
hasso508e53e2004-05-18 18:57:06 +0000818 on = ospf6_neighbor_lookup (oh->router_id, oi);
819 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000820 {
hasso508e53e2004-05-18 18:57:06 +0000821 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000822 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000823 return;
824 }
825
hasso508e53e2004-05-18 18:57:06 +0000826 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
827 on->state != OSPF6_NEIGHBOR_LOADING &&
828 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000829 {
hasso508e53e2004-05-18 18:57:06 +0000830 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000831 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000832 return;
833 }
834
hasso508e53e2004-05-18 18:57:06 +0000835 /* Process each request */
836 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
837 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
838 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000839 {
hasso508e53e2004-05-18 18:57:06 +0000840 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000841
842 switch (OSPF6_LSA_SCOPE (e->type))
843 {
844 case OSPF6_SCOPE_LINKLOCAL:
845 lsdb = on->ospf6_if->lsdb;
846 break;
847 case OSPF6_SCOPE_AREA:
848 lsdb = on->ospf6_if->area->lsdb;
849 break;
850 case OSPF6_SCOPE_AS:
851 lsdb = on->ospf6_if->area->ospf6->lsdb;
852 break;
853 default:
854 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000855 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000856 continue;
857 break;
858 }
paul718e3742002-12-13 20:15:29 +0000859
hasso508e53e2004-05-18 18:57:06 +0000860 /* Find database copy */
861 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
862 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000863 {
hasso508e53e2004-05-18 18:57:06 +0000864 char id[16], adv_router[16];
865 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
866 {
867 inet_ntop (AF_INET, &e->id, id, sizeof (id));
868 inet_ntop (AF_INET, &e->adv_router, adv_router,
869 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000870 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
871 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000872 }
873 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000874 return;
875 }
876
hasso508e53e2004-05-18 18:57:06 +0000877 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000878 }
879
Denis Ovsienkofa079662011-10-08 17:22:45 +0400880 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000881
hasso508e53e2004-05-18 18:57:06 +0000882 /* schedule send lsupdate */
883 THREAD_OFF (on->thread_send_lsupdate);
884 on->thread_send_lsupdate =
885 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000886}
887
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400888/* Verify, that the specified memory area contains exactly N valid IPv6
889 prefixes as specified by RFC5340, A.4.1. */
890static unsigned
891ospf6_prefixes_examin
892(
893 struct ospf6_prefix *current, /* start of buffer */
894 unsigned length,
895 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
896)
897{
898 u_char requested_pfx_bytes;
899 u_int32_t real_num_pfxs = 0;
900
901 while (length)
902 {
903 if (length < OSPF6_PREFIX_MIN_SIZE)
904 {
905 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
906 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
907 return MSG_NG;
908 }
909 /* safe to look deeper */
910 if (current->prefix_length > IPV6_MAX_BITLEN)
911 {
912 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
913 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
914 return MSG_NG;
915 }
916 /* covers both fixed- and variable-sized fields */
917 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
918 if (requested_pfx_bytes > length)
919 {
920 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
921 zlog_debug ("%s: undersized IPv6 prefix", __func__);
922 return MSG_NG;
923 }
924 /* next prefix */
925 length -= requested_pfx_bytes;
926 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
927 real_num_pfxs++;
928 }
929 if (real_num_pfxs != req_num_pfxs)
930 {
931 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
932 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
933 __func__, req_num_pfxs, real_num_pfxs);
934 return MSG_NG;
935 }
936 return MSG_OK;
937}
938
939/* Verify an LSA to have a valid length and dispatch further (where
940 appropriate) to check if the contents, including nested IPv6 prefixes,
941 is properly sized/aligned within the LSA. Note that this function gets
942 LSA type in network byte order, uses in host byte order and passes to
943 ospf6_lstype_name() in network byte order again. */
944static unsigned
945ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
946{
947 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
948 struct ospf6_as_external_lsa *as_external_lsa;
949 struct ospf6_link_lsa *link_lsa;
950 unsigned exp_length;
951 u_int8_t ltindex;
952 u_int16_t lsatype;
953
954 /* In case an additional minimum length constraint is defined for current
955 LSA type, make sure that this constraint is met. */
956 lsatype = ntohs (lsah->type);
957 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
958 if
959 (
960 ltindex < OSPF6_LSTYPE_SIZE &&
961 ospf6_lsa_minlen[ltindex] &&
962 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
963 )
964 {
965 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
966 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
967 return MSG_NG;
968 }
969 switch (lsatype)
970 {
971 case OSPF6_LSTYPE_ROUTER:
972 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
973 by N>=0 interface descriptions. */
974 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
975 {
976 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
977 zlog_debug ("%s: interface description alignment error", __func__);
978 return MSG_NG;
979 }
980 break;
981 case OSPF6_LSTYPE_NETWORK:
982 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
983 followed by N>=0 attached router descriptions. */
984 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
985 {
986 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
987 zlog_debug ("%s: router description alignment error", __func__);
988 return MSG_NG;
989 }
990 break;
991 case OSPF6_LSTYPE_INTER_PREFIX:
992 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
993 followed by 3-4 fields of a single IPv6 prefix. */
994 if (headeronly)
995 break;
996 return ospf6_prefixes_examin
997 (
998 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
999 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1000 1
1001 );
1002 case OSPF6_LSTYPE_INTER_ROUTER:
1003 /* RFC5340 A.4.6, fixed-size LSA. */
1004 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1005 {
1006 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1007 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1008 return MSG_NG;
1009 }
1010 break;
1011 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1012 case OSPF6_LSTYPE_TYPE_7:
1013 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1014 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1015 16 bytes of forwarding address, 4 bytes of external route tag,
1016 4 bytes of referenced link state ID. */
1017 if (headeronly)
1018 break;
1019 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1020 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1021 /* To find out if the last optional field (Referenced Link State ID) is
1022 assumed in this LSA, we need to access fixed fields of the IPv6
1023 prefix before ospf6_prefix_examin() confirms its sizing. */
1024 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1025 {
1026 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1027 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1028 return MSG_NG;
1029 }
1030 /* forwarding address */
1031 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1032 exp_length += 16;
1033 /* external route tag */
1034 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1035 exp_length += 4;
1036 /* referenced link state ID */
1037 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1038 exp_length += 4;
1039 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1040 this check does not include any IPv6 prefix fields. */
1041 if (exp_length > lsalen)
1042 {
1043 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1044 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1045 return MSG_NG;
1046 }
1047 /* The last call completely covers the remainder (IPv6 prefix). */
1048 return ospf6_prefixes_examin
1049 (
1050 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1051 lsalen - exp_length,
1052 1
1053 );
1054 case OSPF6_LSTYPE_LINK:
1055 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1056 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1057 if (headeronly)
1058 break;
1059 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1060 return ospf6_prefixes_examin
1061 (
1062 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1063 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1064 ntohl (link_lsa->prefix_num) /* 32 bits */
1065 );
1066 case OSPF6_LSTYPE_INTRA_PREFIX:
1067 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1068 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1069 if (headeronly)
1070 break;
1071 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1072 return ospf6_prefixes_examin
1073 (
1074 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1075 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1076 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1077 );
1078 }
1079 /* No additional validation is possible for unknown LSA types, which are
1080 themselves valid in OPSFv3, hence the default decision is to accept. */
1081 return MSG_OK;
1082}
1083
1084/* Verify if the provided input buffer is a valid sequence of LSAs. This
1085 includes verification of LSA blocks length/alignment and dispatching
1086 of deeper-level checks. */
1087static unsigned
1088ospf6_lsaseq_examin
1089(
1090 struct ospf6_lsa_header *lsah, /* start of buffered data */
1091 size_t length,
1092 const u_char headeronly,
1093 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1094 and treat the difference as an error. */
1095 const u_int32_t declared_num_lsas
1096)
1097{
1098 u_int32_t counted_lsas = 0;
1099
1100 while (length)
1101 {
1102 u_int16_t lsalen;
1103 if (length < OSPF6_LSA_HEADER_SIZE)
1104 {
1105 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001106 zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001107 __func__, length, counted_lsas);
1108 return MSG_NG;
1109 }
1110 /* save on ntohs() calls here and in the LSA validator */
1111 lsalen = OSPF6_LSA_SIZE (lsah);
1112 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1113 {
1114 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1115 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1116 __func__, counted_lsas, lsalen);
1117 return MSG_NG;
1118 }
1119 if (headeronly)
1120 {
1121 /* less checks here and in ospf6_lsa_examin() */
1122 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1123 {
1124 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1125 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1126 ospf6_lstype_name (lsah->type), counted_lsas);
1127 return MSG_NG;
1128 }
1129 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1130 length -= OSPF6_LSA_HEADER_SIZE;
1131 }
1132 else
1133 {
1134 /* make sure the input buffer is deep enough before further checks */
1135 if (lsalen > length)
1136 {
1137 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001138 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001139 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1140 return MSG_NG;
1141 }
1142 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1143 {
1144 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1145 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1146 ospf6_lstype_name (lsah->type), counted_lsas);
1147 return MSG_NG;
1148 }
1149 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1150 length -= lsalen;
1151 }
1152 counted_lsas++;
1153 }
1154
1155 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1156 {
1157 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1158 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1159 __func__, declared_num_lsas, counted_lsas);
1160 return MSG_NG;
1161 }
1162 return MSG_OK;
1163}
1164
1165/* Verify a complete OSPF packet for proper sizing/alignment. */
1166static unsigned
1167ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1168{
1169 struct ospf6_lsupdate *lsupd;
1170 unsigned test;
1171
1172 /* length, 1st approximation */
1173 if (bytesonwire < OSPF6_HEADER_SIZE)
1174 {
1175 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1176 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1177 return MSG_NG;
1178 }
1179 /* Now it is safe to access header fields. */
1180 if (bytesonwire != ntohs (oh->length))
1181 {
1182 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1183 zlog_debug ("%s: packet length error (%u real, %u declared)",
1184 __func__, bytesonwire, ntohs (oh->length));
1185 return MSG_NG;
1186 }
1187 /* version check */
1188 if (oh->version != OSPFV3_VERSION)
1189 {
1190 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1191 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1192 return MSG_NG;
1193 }
1194 /* length, 2nd approximation */
1195 if
1196 (
1197 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1198 ospf6_packet_minlen[oh->type] &&
1199 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1200 )
1201 {
1202 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1203 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001204 bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001205 return MSG_NG;
1206 }
1207 /* type-specific deeper validation */
1208 switch (oh->type)
1209 {
1210 case OSPF6_MESSAGE_TYPE_HELLO:
1211 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1212 by N>=0 router-IDs. */
1213 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1214 return MSG_OK;
1215 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1216 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001217 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001218 return MSG_NG;
1219 case OSPF6_MESSAGE_TYPE_DBDESC:
1220 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1221 by N>=0 header-only LSAs. */
1222 test = ospf6_lsaseq_examin
1223 (
1224 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1225 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1226 1,
1227 0
1228 );
1229 break;
1230 case OSPF6_MESSAGE_TYPE_LSREQ:
1231 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1232 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1233 return MSG_OK;
1234 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1235 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001236 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001237 return MSG_NG;
1238 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1239 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1240 by N>=0 full LSAs (with N declared beforehand). */
1241 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1242 test = ospf6_lsaseq_examin
1243 (
1244 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1245 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1246 0,
1247 ntohl (lsupd->lsa_number) /* 32 bits */
1248 );
1249 break;
1250 case OSPF6_MESSAGE_TYPE_LSACK:
1251 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1252 test = ospf6_lsaseq_examin
1253 (
1254 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1255 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1256 1,
1257 0
1258 );
1259 break;
1260 default:
1261 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1262 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1263 return MSG_NG;
1264 }
1265 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001266 zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001267 return test;
1268}
1269
1270/* Verify particular fields of otherwise correct received OSPF packet to
1271 meet the requirements of RFC. */
1272static int
1273ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1274{
1275 char buf[2][INET_ADDRSTRLEN];
1276
1277 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1278 return MSG_NG;
1279
1280 /* Area-ID check */
1281 if (oh->area_id != oi->area->area_id)
1282 {
1283 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1284 {
Dinesh Dutt8551e6d2013-10-22 17:42:18 -07001285 if (oh->area_id == OSPF_AREA_BACKBONE)
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001286 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1287 else
1288 zlog_debug
1289 (
1290 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1291 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1292 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1293 );
1294 }
1295 return MSG_NG;
1296 }
1297
1298 /* Instance-ID check */
1299 if (oh->instance_id != oi->instance_id)
1300 {
1301 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1302 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1303 return MSG_NG;
1304 }
1305
1306 /* Router-ID check */
1307 if (oh->router_id == oi->area->ospf6->router_id)
1308 {
1309 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1310 return MSG_NG;
1311 }
1312 return MSG_OK;
1313}
1314
Paul Jakma6ac29a52008-08-15 13:45:30 +01001315static void
hasso508e53e2004-05-18 18:57:06 +00001316ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1317 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001318{
hasso508e53e2004-05-18 18:57:06 +00001319 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001320 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001321 char *p;
paul718e3742002-12-13 20:15:29 +00001322
hasso508e53e2004-05-18 18:57:06 +00001323 on = ospf6_neighbor_lookup (oh->router_id, oi);
1324 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001325 {
hasso508e53e2004-05-18 18:57:06 +00001326 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001327 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001328 return;
1329 }
1330
hasso508e53e2004-05-18 18:57:06 +00001331 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1332 on->state != OSPF6_NEIGHBOR_LOADING &&
1333 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001334 {
hasso508e53e2004-05-18 18:57:06 +00001335 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001336 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001337 return;
1338 }
1339
hasso508e53e2004-05-18 18:57:06 +00001340 lsupdate = (struct ospf6_lsupdate *)
1341 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001342
hasso508e53e2004-05-18 18:57:06 +00001343 /* Process LSAs */
1344 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1345 p < OSPF6_MESSAGE_END (oh) &&
1346 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1347 p += OSPF6_LSA_SIZE (p))
1348 {
hasso6452df02004-08-15 05:52:07 +00001349 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001350 }
1351
Denis Ovsienkofa079662011-10-08 17:22:45 +04001352 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001353
paul718e3742002-12-13 20:15:29 +00001354}
1355
Paul Jakma6ac29a52008-08-15 13:45:30 +01001356static void
hasso508e53e2004-05-18 18:57:06 +00001357ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1358 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001359{
hasso508e53e2004-05-18 18:57:06 +00001360 struct ospf6_neighbor *on;
1361 char *p;
1362 struct ospf6_lsa *his, *mine;
1363 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001364
hasso508e53e2004-05-18 18:57:06 +00001365 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001366
hasso508e53e2004-05-18 18:57:06 +00001367 on = ospf6_neighbor_lookup (oh->router_id, oi);
1368 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001369 {
hasso508e53e2004-05-18 18:57:06 +00001370 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001371 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001372 return;
1373 }
1374
hasso508e53e2004-05-18 18:57:06 +00001375 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1376 on->state != OSPF6_NEIGHBOR_LOADING &&
1377 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001378 {
hasso508e53e2004-05-18 18:57:06 +00001379 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001380 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001381 return;
1382 }
1383
hasso508e53e2004-05-18 18:57:06 +00001384 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1385 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1386 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001387 {
hasso508e53e2004-05-18 18:57:06 +00001388 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001389
hasso6452df02004-08-15 05:52:07 +00001390 switch (OSPF6_LSA_SCOPE (his->header->type))
1391 {
1392 case OSPF6_SCOPE_LINKLOCAL:
1393 lsdb = on->ospf6_if->lsdb;
1394 break;
1395 case OSPF6_SCOPE_AREA:
1396 lsdb = on->ospf6_if->area->lsdb;
1397 break;
1398 case OSPF6_SCOPE_AS:
1399 lsdb = on->ospf6_if->area->ospf6->lsdb;
1400 break;
1401 case OSPF6_SCOPE_RESERVED:
1402 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001403 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001404 ospf6_lsa_delete (his);
1405 continue;
1406 break;
1407 }
1408
1409 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001410 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001411
1412 /* Find database copy */
1413 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1414 his->header->adv_router, lsdb);
1415 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001416 {
hasso508e53e2004-05-18 18:57:06 +00001417 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001418 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001419 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001420 continue;
1421 }
1422
hasso508e53e2004-05-18 18:57:06 +00001423 /* Check if the LSA is on his retrans-list */
1424 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1425 his->header->adv_router, on->retrans_list);
1426 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001427 {
hasso508e53e2004-05-18 18:57:06 +00001428 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001429 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001430 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001431 continue;
1432 }
1433
hasso508e53e2004-05-18 18:57:06 +00001434 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001435 {
hasso508e53e2004-05-18 18:57:06 +00001436 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001437 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001438 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001439 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001440 ospf6_lsa_delete (his);
1441 continue;
paul718e3742002-12-13 20:15:29 +00001442 }
1443
hasso6452df02004-08-15 05:52:07 +00001444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001445 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1446 on->name);
hasso508e53e2004-05-18 18:57:06 +00001447
Paul Jakma932bf192006-05-15 10:42:24 +00001448 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001449 if (OSPF6_LSA_IS_MAXAGE (mine))
1450 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001451 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001452 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001453 }
1454
Denis Ovsienkofa079662011-10-08 17:22:45 +04001455 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001456}
1457
Paul Jakma6ac29a52008-08-15 13:45:30 +01001458static u_char *recvbuf = NULL;
1459static u_char *sendbuf = NULL;
1460static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001461
1462int
paul0c083ee2004-10-10 12:54:58 +00001463ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001464{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001465 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001466
1467 if (size <= iobuflen)
1468 return iobuflen;
1469
1470 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1471 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1472 if (recvnew == NULL || sendnew == NULL)
1473 {
hassob596c712004-07-09 18:33:43 +00001474 if (recvnew)
1475 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1476 if (sendnew)
1477 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001478 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001479 return iobuflen;
1480 }
1481
1482 if (recvbuf)
1483 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1484 if (sendbuf)
1485 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1486 recvbuf = recvnew;
1487 sendbuf = sendnew;
1488 iobuflen = size;
1489
1490 return iobuflen;
1491}
paul718e3742002-12-13 20:15:29 +00001492
Tom Goffae2254a2010-11-10 13:01:41 -08001493void
1494ospf6_message_terminate (void)
1495{
1496 if (recvbuf)
1497 {
1498 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1499 recvbuf = NULL;
1500 }
1501
1502 if (sendbuf)
1503 {
1504 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1505 sendbuf = NULL;
1506 }
1507
1508 iobuflen = 0;
1509}
1510
paul718e3742002-12-13 20:15:29 +00001511int
1512ospf6_receive (struct thread *thread)
1513{
paul0c083ee2004-10-10 12:54:58 +00001514 int sockfd;
1515 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001516 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001517 struct in6_addr src, dst;
1518 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001519 struct iovec iovector[2];
1520 struct ospf6_interface *oi;
1521 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001522
1523 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001524 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001525 thread_add_read (master, ospf6_receive, NULL, sockfd);
1526
1527 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001528 memset (&src, 0, sizeof (src));
1529 memset (&dst, 0, sizeof (dst));
1530 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001531 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001532 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001533 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001534 iovector[1].iov_base = NULL;
1535 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001536
1537 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001538 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001539 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001540 {
hasso508e53e2004-05-18 18:57:06 +00001541 zlog_err ("Excess message read");
1542 return 0;
1543 }
paul718e3742002-12-13 20:15:29 +00001544
hasso508e53e2004-05-18 18:57:06 +00001545 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1546 if (oi == NULL || oi->area == NULL)
1547 {
hassoc6487d62004-12-24 06:00:11 +00001548 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001549 return 0;
1550 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001551 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1552 {
1553 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1554 zlog_debug ("%s: Ignore message on passive interface %s",
1555 __func__, oi->interface->name);
1556 return 0;
1557 }
hasso508e53e2004-05-18 18:57:06 +00001558
1559 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001560 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1561 return 0;
1562
1563 /* Being here means, that no sizing/alignment issues were detected in
1564 the input packet. This renders the additional checks performed below
1565 and also in the type-specific dispatching functions a dead code,
1566 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001567
1568 /* Log */
1569 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1570 {
1571 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1572 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001573 zlog_debug ("%s received on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001574 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001575 zlog_debug (" src: %s", srcname);
1576 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001577
1578 switch (oh->type)
1579 {
1580 case OSPF6_MESSAGE_TYPE_HELLO:
1581 ospf6_hello_print (oh);
1582 break;
1583 case OSPF6_MESSAGE_TYPE_DBDESC:
1584 ospf6_dbdesc_print (oh);
1585 break;
1586 case OSPF6_MESSAGE_TYPE_LSREQ:
1587 ospf6_lsreq_print (oh);
1588 break;
1589 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1590 ospf6_lsupdate_print (oh);
1591 break;
1592 case OSPF6_MESSAGE_TYPE_LSACK:
1593 ospf6_lsack_print (oh);
1594 break;
1595 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001596 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001597 }
1598 }
1599
hasso508e53e2004-05-18 18:57:06 +00001600 switch (oh->type)
1601 {
1602 case OSPF6_MESSAGE_TYPE_HELLO:
1603 ospf6_hello_recv (&src, &dst, oi, oh);
1604 break;
1605
1606 case OSPF6_MESSAGE_TYPE_DBDESC:
1607 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1608 break;
1609
1610 case OSPF6_MESSAGE_TYPE_LSREQ:
1611 ospf6_lsreq_recv (&src, &dst, oi, oh);
1612 break;
1613
1614 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1615 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1616 break;
1617
1618 case OSPF6_MESSAGE_TYPE_LSACK:
1619 ospf6_lsack_recv (&src, &dst, oi, oh);
1620 break;
1621
1622 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001623 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001624 }
1625
1626 return 0;
1627}
1628
Paul Jakma6ac29a52008-08-15 13:45:30 +01001629static void
hasso508e53e2004-05-18 18:57:06 +00001630ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1631 struct ospf6_interface *oi, struct ospf6_header *oh)
1632{
1633 int len;
1634 char srcname[64], dstname[64];
1635 struct iovec iovector[2];
1636
1637 /* initialize */
1638 iovector[0].iov_base = (caddr_t) oh;
1639 iovector[0].iov_len = ntohs (oh->length);
1640 iovector[1].iov_base = NULL;
1641 iovector[1].iov_len = 0;
1642
1643 /* fill OSPF header */
1644 oh->version = OSPFV3_VERSION;
1645 /* message type must be set before */
1646 /* message length must be set before */
1647 oh->router_id = oi->area->ospf6->router_id;
1648 oh->area_id = oi->area->area_id;
1649 /* checksum is calculated by kernel */
1650 oh->instance_id = oi->instance_id;
1651 oh->reserved = 0;
1652
1653 /* Log */
1654 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1655 {
1656 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1657 if (src)
1658 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1659 else
1660 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001661 zlog_debug ("%s send on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001662 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001663 zlog_debug (" src: %s", srcname);
1664 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001665
1666 switch (oh->type)
1667 {
1668 case OSPF6_MESSAGE_TYPE_HELLO:
1669 ospf6_hello_print (oh);
1670 break;
1671 case OSPF6_MESSAGE_TYPE_DBDESC:
1672 ospf6_dbdesc_print (oh);
1673 break;
1674 case OSPF6_MESSAGE_TYPE_LSREQ:
1675 ospf6_lsreq_print (oh);
1676 break;
1677 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1678 ospf6_lsupdate_print (oh);
1679 break;
1680 case OSPF6_MESSAGE_TYPE_LSACK:
1681 ospf6_lsack_print (oh);
1682 break;
1683 default:
hassoc6487d62004-12-24 06:00:11 +00001684 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001685 assert (0);
1686 break;
1687 }
1688 }
1689
1690 /* send message */
1691 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1692 if (len != ntohs (oh->length))
1693 zlog_err ("Could not send entire message");
1694}
1695
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001696static uint32_t
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001697ospf6_packet_max(struct ospf6_interface *oi)
1698{
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001699 assert (oi->ifmtu > sizeof (struct ip6_hdr));
1700 return oi->ifmtu - (sizeof (struct ip6_hdr));
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001701}
1702
hasso508e53e2004-05-18 18:57:06 +00001703int
1704ospf6_hello_send (struct thread *thread)
1705{
1706 struct ospf6_interface *oi;
1707 struct ospf6_header *oh;
1708 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001709 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001710 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001711 struct ospf6_neighbor *on;
1712
1713 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1714 oi->thread_send_hello = (struct thread *) NULL;
1715
1716 if (oi->state <= OSPF6_INTERFACE_DOWN)
1717 {
1718 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001719 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001720 oi->interface->name);
1721 return 0;
1722 }
1723
1724 /* set next thread */
1725 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1726 oi, oi->hello_interval);
1727
hasso3b4cd3a2004-05-18 19:28:32 +00001728 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001729 oh = (struct ospf6_header *) sendbuf;
1730 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1731
1732 hello->interface_id = htonl (oi->interface->ifindex);
1733 hello->priority = oi->priority;
1734 hello->options[0] = oi->area->options[0];
1735 hello->options[1] = oi->area->options[1];
1736 hello->options[2] = oi->area->options[2];
1737 hello->hello_interval = htons (oi->hello_interval);
1738 hello->dead_interval = htons (oi->dead_interval);
1739 hello->drouter = oi->drouter;
1740 hello->bdrouter = oi->bdrouter;
1741
Paul Jakma6ac29a52008-08-15 13:45:30 +01001742 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001743
paul1eb8ef22005-04-07 07:30:20 +00001744 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001745 {
hasso508e53e2004-05-18 18:57:06 +00001746 if (on->state < OSPF6_NEIGHBOR_INIT)
1747 continue;
1748
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001749 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001750 {
1751 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001752 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001753 break;
1754 }
1755
1756 memcpy (p, &on->router_id, sizeof (u_int32_t));
1757 p += sizeof (u_int32_t);
1758 }
1759
1760 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1761 oh->length = htons (p - sendbuf);
1762
1763 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1764 return 0;
1765}
1766
1767int
1768ospf6_dbdesc_send (struct thread *thread)
1769{
1770 struct ospf6_neighbor *on;
1771 struct ospf6_header *oh;
1772 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001773 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001774 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00001775 struct in6_addr *dst;
hasso508e53e2004-05-18 18:57:06 +00001776
1777 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1778 on->thread_send_dbdesc = (struct thread *) NULL;
1779
1780 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1781 {
1782 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001783 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1784 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001785 return 0;
1786 }
1787
1788 /* set next thread if master */
1789 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1790 on->thread_send_dbdesc =
1791 thread_add_timer (master, ospf6_dbdesc_send, on,
1792 on->ospf6_if->rxmt_interval);
1793
hasso3b4cd3a2004-05-18 19:28:32 +00001794 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001795 oh = (struct ospf6_header *) sendbuf;
1796 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1797 sizeof (struct ospf6_header));
1798
1799 /* if this is initial one, initialize sequence number for DbDesc */
1800 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1801 {
1802 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001803 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001804 tv.tv_sec = 1;
1805 on->dbdesc_seqnum = tv.tv_sec;
1806 }
1807
1808 dbdesc->options[0] = on->ospf6_if->area->options[0];
1809 dbdesc->options[1] = on->ospf6_if->area->options[1];
1810 dbdesc->options[2] = on->ospf6_if->area->options[2];
1811 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1812 dbdesc->bits = on->dbdesc_bits;
1813 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1814
1815 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001816 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001817 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1818 {
1819 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1820 lsa = ospf6_lsdb_next (lsa))
1821 {
1822 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1823
1824 /* MTU check */
1825 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001826 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001827 {
1828 ospf6_lsa_unlock (lsa);
1829 break;
1830 }
1831 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1832 p += sizeof (struct ospf6_lsa_header);
1833 }
1834 }
1835
1836 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1837 oh->length = htons (p - sendbuf);
1838
Dinesh Duttc5926a92013-08-24 07:55:00 +00001839
1840 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1841 dst = &allspfrouters6;
1842 else
1843 dst = &on->linklocal_addr;
1844
1845 ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
1846
hasso508e53e2004-05-18 18:57:06 +00001847 return 0;
1848}
1849
1850int
1851ospf6_dbdesc_send_newone (struct thread *thread)
1852{
1853 struct ospf6_neighbor *on;
1854 struct ospf6_lsa *lsa;
1855 unsigned int size = 0;
1856
1857 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001858 ospf6_lsdb_remove_all (on->dbdesc_list);
1859
1860 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1861 so that ospf6_send_dbdesc () can send those LSAs */
1862 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1863 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1864 lsa = ospf6_lsdb_next (lsa))
1865 {
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001866 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001867 {
1868 ospf6_lsa_unlock (lsa);
1869 break;
1870 }
1871
hasso508e53e2004-05-18 18:57:06 +00001872 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1873 ospf6_lsdb_remove (lsa, on->summary_list);
1874 size += sizeof (struct ospf6_lsa_header);
1875 }
1876
1877 if (on->summary_list->count == 0)
1878 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1879
1880 /* If slave, More bit check must be done here */
1881 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1882 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1883 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1884 thread_add_event (master, exchange_done, on, 0);
1885
1886 thread_execute (master, ospf6_dbdesc_send, on, 0);
1887 return 0;
1888}
1889
1890int
1891ospf6_lsreq_send (struct thread *thread)
1892{
1893 struct ospf6_neighbor *on;
1894 struct ospf6_header *oh;
1895 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001896 u_char *p;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001897 struct ospf6_lsa *lsa, *last_req;
hasso508e53e2004-05-18 18:57:06 +00001898
1899 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1900 on->thread_send_lsreq = (struct thread *) NULL;
1901
1902 /* LSReq will be sent only in ExStart or Loading */
1903 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1904 on->state != OSPF6_NEIGHBOR_LOADING)
1905 {
1906 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001907 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1908 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001909 return 0;
1910 }
1911
1912 /* schedule loading_done if request list is empty */
1913 if (on->request_list->count == 0)
1914 {
1915 thread_add_event (master, loading_done, on, 0);
1916 return 0;
1917 }
1918
hasso3b4cd3a2004-05-18 19:28:32 +00001919 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001920 oh = (struct ospf6_header *) sendbuf;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001921 last_req = NULL;
hasso508e53e2004-05-18 18:57:06 +00001922
1923 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001924 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001925 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1926 lsa = ospf6_lsdb_next (lsa))
1927 {
1928 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001929 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001930 {
1931 ospf6_lsa_unlock (lsa);
1932 break;
1933 }
1934
1935 e = (struct ospf6_lsreq_entry *) p;
1936 e->type = lsa->header->type;
1937 e->id = lsa->header->id;
1938 e->adv_router = lsa->header->adv_router;
1939 p += sizeof (struct ospf6_lsreq_entry);
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001940 last_req = lsa;
1941 }
1942
1943 if (last_req != NULL)
1944 {
1945 if (on->last_ls_req != NULL)
1946 {
1947 ospf6_lsa_unlock (on->last_ls_req);
1948 }
1949 ospf6_lsa_lock (last_req);
1950 on->last_ls_req = last_req;
hasso508e53e2004-05-18 18:57:06 +00001951 }
1952
1953 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1954 oh->length = htons (p - sendbuf);
1955
Dinesh Duttc5926a92013-08-24 07:55:00 +00001956 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1957 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
hasso508e53e2004-05-18 18:57:06 +00001958 on->ospf6_if, oh);
Dinesh Duttc5926a92013-08-24 07:55:00 +00001959 else
1960 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1961 on->ospf6_if, oh);
1962
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001963 /* set next thread */
1964 if (on->request_list->count != 0)
1965 {
1966 on->thread_send_lsreq =
1967 thread_add_timer (master, ospf6_lsreq_send, on,
1968 on->ospf6_if->rxmt_interval);
1969 }
1970
hasso508e53e2004-05-18 18:57:06 +00001971 return 0;
1972}
1973
1974int
1975ospf6_lsupdate_send_neighbor (struct thread *thread)
1976{
1977 struct ospf6_neighbor *on;
1978 struct ospf6_header *oh;
1979 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001980 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00001981 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00001982 struct ospf6_lsa *lsa;
1983
1984 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1985 on->thread_send_lsupdate = (struct thread *) NULL;
1986
hasso6452df02004-08-15 05:52:07 +00001987 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001988 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001989
hasso508e53e2004-05-18 18:57:06 +00001990 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1991 {
1992 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001993 zlog_debug ("Quit to send (neighbor state %s)",
1994 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001995 return 0;
1996 }
1997
hasso3b4cd3a2004-05-18 19:28:32 +00001998 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001999 oh = (struct ospf6_header *) sendbuf;
2000 lsupdate = (struct ospf6_lsupdate *)
2001 ((caddr_t) oh + sizeof (struct ospf6_header));
2002
Paul Jakma6ac29a52008-08-15 13:45:30 +01002003 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002004 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002005
2006 /* lsupdate_list lists those LSA which doesn't need to be
2007 retransmitted. remove those from the list */
2008 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2009 lsa = ospf6_lsdb_next (lsa))
2010 {
2011 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002012 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002013 > ospf6_packet_max(on->ospf6_if))
2014 {
2015 ospf6_lsa_unlock (lsa);
2016 break;
2017 }
hasso508e53e2004-05-18 18:57:06 +00002018
hasso508e53e2004-05-18 18:57:06 +00002019 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2020 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2021 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002022 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002023
2024 assert (lsa->lock == 2);
2025 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2026 }
2027
Dinesh Duttc5926a92013-08-24 07:55:00 +00002028 if (lsa_cnt)
2029 {
2030 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2031 oh->length = htons (p - sendbuf);
2032 lsupdate->lsa_number = htonl (lsa_cnt);
2033
2034 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2035 (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
2036 (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
2037 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2038 on->ospf6_if, oh);
2039 else
2040 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2041 on->ospf6_if, oh);
2042 }
2043
2044 /* The addresses used for retransmissions are different from those sent the
2045 first time and so we need to separate them here.
2046 */
2047 memset (sendbuf, 0, iobuflen);
2048 oh = (struct ospf6_header *) sendbuf;
2049 lsupdate = (struct ospf6_lsupdate *)
2050 ((caddr_t) oh + sizeof (struct ospf6_header));
2051 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
2052 lsa_cnt = 0;
2053
hasso508e53e2004-05-18 18:57:06 +00002054 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2055 lsa = ospf6_lsdb_next (lsa))
2056 {
2057 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002058 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002059 > ospf6_packet_max(on->ospf6_if))
2060 {
2061 ospf6_lsa_unlock (lsa);
2062 break;
2063 }
hasso508e53e2004-05-18 18:57:06 +00002064
hasso508e53e2004-05-18 18:57:06 +00002065 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);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002068 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002069 }
2070
Dinesh Duttc5926a92013-08-24 07:55:00 +00002071 if (lsa_cnt)
hasso508e53e2004-05-18 18:57:06 +00002072 {
Dinesh Duttc5926a92013-08-24 07:55:00 +00002073 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2074 oh->length = htons (p - sendbuf);
2075 lsupdate->lsa_number = htonl (lsa_cnt);
2076
2077 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2078 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2079 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002080 else
Dinesh Duttc5926a92013-08-24 07:55:00 +00002081 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2082 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002083 }
2084
Dinesh Duttc5926a92013-08-24 07:55:00 +00002085 if (on->lsupdate_list->count != 0)
2086 on->thread_send_lsupdate =
2087 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2088 else if (on->retrans_list->count != 0)
2089 on->thread_send_lsupdate =
2090 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2091 on->ospf6_if->rxmt_interval);
hasso508e53e2004-05-18 18:57:06 +00002092 return 0;
2093}
2094
2095int
2096ospf6_lsupdate_send_interface (struct thread *thread)
2097{
2098 struct ospf6_interface *oi;
2099 struct ospf6_header *oh;
2100 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002101 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002102 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00002103 struct ospf6_lsa *lsa;
2104
2105 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2106 oi->thread_send_lsupdate = (struct thread *) NULL;
2107
2108 if (oi->state <= OSPF6_INTERFACE_WAITING)
2109 {
2110 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002111 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2112 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002113 return 0;
2114 }
2115
2116 /* if we have nothing to send, return */
2117 if (oi->lsupdate_list->count == 0)
2118 return 0;
2119
hasso3b4cd3a2004-05-18 19:28:32 +00002120 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002121 oh = (struct ospf6_header *) sendbuf;
2122 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
Dinesh Duttc5926a92013-08-24 07:55:00 +00002123 sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002124
Paul Jakma6ac29a52008-08-15 13:45:30 +01002125 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002126 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002127
2128 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2129 lsa = ospf6_lsdb_next (lsa))
2130 {
2131 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002132 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002133 > ospf6_packet_max(oi))
2134 {
2135 ospf6_lsa_unlock (lsa);
2136 break;
2137 }
hasso508e53e2004-05-18 18:57:06 +00002138
hasso508e53e2004-05-18 18:57:06 +00002139 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2140 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2141 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002142 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002143
2144 assert (lsa->lock == 2);
2145 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2146 }
2147
Dinesh Duttc5926a92013-08-24 07:55:00 +00002148 if (lsa_cnt)
2149 {
2150 lsupdate->lsa_number = htonl (lsa_cnt);
hasso508e53e2004-05-18 18:57:06 +00002151
Dinesh Duttc5926a92013-08-24 07:55:00 +00002152 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2153 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002154
Dinesh Duttc5926a92013-08-24 07:55:00 +00002155 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2156 (oi->state == OSPF6_INTERFACE_DR) ||
2157 (oi->state == OSPF6_INTERFACE_BDR))
2158 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2159 else
2160 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2161
2162 }
hasso508e53e2004-05-18 18:57:06 +00002163
2164 if (oi->lsupdate_list->count > 0)
2165 {
2166 oi->thread_send_lsupdate =
2167 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2168 }
2169
2170 return 0;
2171}
2172
2173int
2174ospf6_lsack_send_neighbor (struct thread *thread)
2175{
2176 struct ospf6_neighbor *on;
2177 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002178 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002179 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002180 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002181
2182 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2183 on->thread_send_lsack = (struct thread *) NULL;
2184
2185 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2186 {
2187 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002188 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2189 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002190 return 0;
2191 }
2192
2193 /* if we have nothing to send, return */
2194 if (on->lsack_list->count == 0)
2195 return 0;
2196
hasso3b4cd3a2004-05-18 19:28:32 +00002197 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002198 oh = (struct ospf6_header *) sendbuf;
2199
Paul Jakma6ac29a52008-08-15 13:45:30 +01002200 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002201
2202 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2203 lsa = ospf6_lsdb_next (lsa))
2204 {
2205 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002206 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002207 {
2208 /* if we run out of packet size/space here,
2209 better to try again soon. */
2210 THREAD_OFF (on->thread_send_lsack);
2211 on->thread_send_lsack =
2212 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
hasso508e53e2004-05-18 18:57:06 +00002213
Dinesh Duttc5926a92013-08-24 07:55:00 +00002214 ospf6_lsa_unlock (lsa);
2215 break;
2216 }
hasso508e53e2004-05-18 18:57:06 +00002217
2218 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2219 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2220 p += sizeof (struct ospf6_lsa_header);
2221
2222 assert (lsa->lock == 2);
2223 ospf6_lsdb_remove (lsa, on->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002224 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002225 }
2226
Dinesh Duttc5926a92013-08-24 07:55:00 +00002227 if (lsa_cnt)
2228 {
2229 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2230 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002231
Dinesh Duttc5926a92013-08-24 07:55:00 +00002232 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2233 on->ospf6_if, oh);
2234 }
2235
2236 if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
2237 {
2238 on->thread_send_lsack =
2239 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2240 }
2241
hasso508e53e2004-05-18 18:57:06 +00002242 return 0;
2243}
2244
2245int
2246ospf6_lsack_send_interface (struct thread *thread)
2247{
2248 struct ospf6_interface *oi;
2249 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002250 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002251 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002252 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002253
2254 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2255 oi->thread_send_lsack = (struct thread *) NULL;
2256
2257 if (oi->state <= OSPF6_INTERFACE_WAITING)
2258 {
2259 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002260 zlog_debug ("Quit to send LSAck to interface %s state %s",
2261 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002262 return 0;
2263 }
2264
2265 /* if we have nothing to send, return */
2266 if (oi->lsack_list->count == 0)
2267 return 0;
2268
hasso3b4cd3a2004-05-18 19:28:32 +00002269 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002270 oh = (struct ospf6_header *) sendbuf;
2271
Paul Jakma6ac29a52008-08-15 13:45:30 +01002272 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002273
2274 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2275 lsa = ospf6_lsdb_next (lsa))
2276 {
2277 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002278 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002279 {
2280 /* if we run out of packet size/space here,
2281 better to try again soon. */
2282 THREAD_OFF (oi->thread_send_lsack);
2283 oi->thread_send_lsack =
2284 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
hasso508e53e2004-05-18 18:57:06 +00002285
Dinesh Duttc5926a92013-08-24 07:55:00 +00002286 ospf6_lsa_unlock (lsa);
2287 break;
2288 }
hasso508e53e2004-05-18 18:57:06 +00002289
2290 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2291 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2292 p += sizeof (struct ospf6_lsa_header);
2293
2294 assert (lsa->lock == 2);
2295 ospf6_lsdb_remove (lsa, oi->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002296 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002297 }
2298
Dinesh Duttc5926a92013-08-24 07:55:00 +00002299 if (lsa_cnt)
2300 {
2301 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2302 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002303
Dinesh Duttc5926a92013-08-24 07:55:00 +00002304 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2305 (oi->state == OSPF6_INTERFACE_DR) ||
2306 (oi->state == OSPF6_INTERFACE_BDR))
2307 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2308 else
2309 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2310 }
hasso508e53e2004-05-18 18:57:06 +00002311
2312 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2313 {
2314 oi->thread_send_lsack =
2315 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2316 }
paul718e3742002-12-13 20:15:29 +00002317
2318 return 0;
2319}
2320
2321
hasso508e53e2004-05-18 18:57:06 +00002322/* Commands */
2323DEFUN (debug_ospf6_message,
2324 debug_ospf6_message_cmd,
2325 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2326 DEBUG_STR
2327 OSPF6_STR
2328 "Debug OSPFv3 message\n"
2329 "Debug Unknown message\n"
2330 "Debug Hello message\n"
2331 "Debug Database Description message\n"
2332 "Debug Link State Request message\n"
2333 "Debug Link State Update message\n"
2334 "Debug Link State Acknowledgement message\n"
2335 "Debug All message\n"
2336 )
paul718e3742002-12-13 20:15:29 +00002337{
hasso508e53e2004-05-18 18:57:06 +00002338 unsigned char level = 0;
2339 int type = 0;
paul718e3742002-12-13 20:15:29 +00002340 int i;
2341
hasso508e53e2004-05-18 18:57:06 +00002342 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002343
hasso508e53e2004-05-18 18:57:06 +00002344 /* check type */
2345 if (! strncmp (argv[0], "u", 1))
2346 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2347 else if (! strncmp (argv[0], "h", 1))
2348 type = OSPF6_MESSAGE_TYPE_HELLO;
2349 else if (! strncmp (argv[0], "d", 1))
2350 type = OSPF6_MESSAGE_TYPE_DBDESC;
2351 else if (! strncmp (argv[0], "lsr", 3))
2352 type = OSPF6_MESSAGE_TYPE_LSREQ;
2353 else if (! strncmp (argv[0], "lsu", 3))
2354 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2355 else if (! strncmp (argv[0], "lsa", 3))
2356 type = OSPF6_MESSAGE_TYPE_LSACK;
2357 else if (! strncmp (argv[0], "a", 1))
2358 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002359
hasso508e53e2004-05-18 18:57:06 +00002360 if (argc == 1)
2361 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2362 else if (! strncmp (argv[1], "s", 1))
2363 level = OSPF6_DEBUG_MESSAGE_SEND;
2364 else if (! strncmp (argv[1], "r", 1))
2365 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002366
hasso508e53e2004-05-18 18:57:06 +00002367 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002368 {
hasso508e53e2004-05-18 18:57:06 +00002369 for (i = 0; i < 6; i++)
2370 OSPF6_DEBUG_MESSAGE_ON (i, level);
2371 }
2372 else
2373 OSPF6_DEBUG_MESSAGE_ON (type, level);
2374
2375 return CMD_SUCCESS;
2376}
2377
2378ALIAS (debug_ospf6_message,
2379 debug_ospf6_message_sendrecv_cmd,
2380 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2381 DEBUG_STR
2382 OSPF6_STR
2383 "Debug OSPFv3 message\n"
2384 "Debug Unknown message\n"
2385 "Debug Hello message\n"
2386 "Debug Database Description message\n"
2387 "Debug Link State Request message\n"
2388 "Debug Link State Update message\n"
2389 "Debug Link State Acknowledgement message\n"
2390 "Debug All message\n"
2391 "Debug only sending message\n"
2392 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002393 )
hasso508e53e2004-05-18 18:57:06 +00002394
2395
2396DEFUN (no_debug_ospf6_message,
2397 no_debug_ospf6_message_cmd,
2398 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2399 NO_STR
2400 DEBUG_STR
2401 OSPF6_STR
2402 "Debug OSPFv3 message\n"
2403 "Debug Unknown message\n"
2404 "Debug Hello message\n"
2405 "Debug Database Description message\n"
2406 "Debug Link State Request message\n"
2407 "Debug Link State Update message\n"
2408 "Debug Link State Acknowledgement message\n"
2409 "Debug All message\n"
2410 )
2411{
2412 unsigned char level = 0;
2413 int type = 0;
2414 int i;
2415
2416 assert (argc > 0);
2417
2418 /* check type */
2419 if (! strncmp (argv[0], "u", 1))
2420 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2421 else if (! strncmp (argv[0], "h", 1))
2422 type = OSPF6_MESSAGE_TYPE_HELLO;
2423 else if (! strncmp (argv[0], "d", 1))
2424 type = OSPF6_MESSAGE_TYPE_DBDESC;
2425 else if (! strncmp (argv[0], "lsr", 3))
2426 type = OSPF6_MESSAGE_TYPE_LSREQ;
2427 else if (! strncmp (argv[0], "lsu", 3))
2428 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2429 else if (! strncmp (argv[0], "lsa", 3))
2430 type = OSPF6_MESSAGE_TYPE_LSACK;
2431 else if (! strncmp (argv[0], "a", 1))
2432 type = OSPF6_MESSAGE_TYPE_ALL;
2433
2434 if (argc == 1)
2435 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2436 else if (! strncmp (argv[1], "s", 1))
2437 level = OSPF6_DEBUG_MESSAGE_SEND;
2438 else if (! strncmp (argv[1], "r", 1))
2439 level = OSPF6_DEBUG_MESSAGE_RECV;
2440
2441 if (type == OSPF6_MESSAGE_TYPE_ALL)
2442 {
2443 for (i = 0; i < 6; i++)
2444 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2445 }
2446 else
2447 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2448
2449 return CMD_SUCCESS;
2450}
2451
2452ALIAS (no_debug_ospf6_message,
2453 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002454 "no debug ospf6 message "
2455 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002456 NO_STR
2457 DEBUG_STR
2458 OSPF6_STR
2459 "Debug OSPFv3 message\n"
2460 "Debug Unknown message\n"
2461 "Debug Hello message\n"
2462 "Debug Database Description message\n"
2463 "Debug Link State Request message\n"
2464 "Debug Link State Update message\n"
2465 "Debug Link State Acknowledgement message\n"
2466 "Debug All message\n"
2467 "Debug only sending message\n"
2468 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002469 )
hasso508e53e2004-05-18 18:57:06 +00002470
2471int
2472config_write_ospf6_debug_message (struct vty *vty)
2473{
paul0c083ee2004-10-10 12:54:58 +00002474 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002475 "lsreq", "lsupdate", "lsack"};
2476 unsigned char s = 0, r = 0;
2477 int i;
2478
2479 for (i = 0; i < 6; i++)
2480 {
2481 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2482 s |= 1 << i;
2483 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2484 r |= 1 << i;
2485 }
2486
2487 if (s == 0x3f && r == 0x3f)
2488 {
hasso049207c2004-08-04 20:02:13 +00002489 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002490 return 0;
2491 }
2492
hasso508e53e2004-05-18 18:57:06 +00002493 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002494 {
hasso049207c2004-08-04 20:02:13 +00002495 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002496 return 0;
2497 }
2498 else if (s == 0 && r == 0x3f)
2499 {
hasso049207c2004-08-04 20:02:13 +00002500 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002501 return 0;
paul718e3742002-12-13 20:15:29 +00002502 }
2503
hasso508e53e2004-05-18 18:57:06 +00002504 /* Unknown message is logged by default */
2505 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2506 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002507 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002508 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002509 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002510 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002511 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002512
hasso508e53e2004-05-18 18:57:06 +00002513 for (i = 1; i < 6; i++)
2514 {
2515 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2516 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002517 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002518 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2519 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002520 VNL);
hasso508e53e2004-05-18 18:57:06 +00002521 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2522 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002523 VNL);
hasso508e53e2004-05-18 18:57:06 +00002524 }
paul718e3742002-12-13 20:15:29 +00002525
2526 return 0;
2527}
2528
paul718e3742002-12-13 20:15:29 +00002529void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002530install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002531{
hasso508e53e2004-05-18 18:57:06 +00002532 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2533 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2534 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2535 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2536 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2537 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2538 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2539 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002540}
2541
paul718e3742002-12-13 20:15:29 +00002542