blob: 439f6a6e3f569587632ee52ac178822e1f9d8f4b [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;
Vipin Kumare509af82015-05-19 18:03:40 -0700248 int neighbor_ifindex_change = 0;
hasso508e53e2004-05-18 18:57:06 +0000249 int backupseen = 0;
250
hasso508e53e2004-05-18 18:57:06 +0000251 hello = (struct ospf6_hello *)
252 ((caddr_t) oh + sizeof (struct ospf6_header));
253
paul718e3742002-12-13 20:15:29 +0000254 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000255 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000256 {
hasso508e53e2004-05-18 18:57:06 +0000257 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000258 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000259 return;
260 }
261
262 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000263 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000264 {
hasso508e53e2004-05-18 18:57:06 +0000265 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000266 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000267 return;
268 }
269
hasso508e53e2004-05-18 18:57:06 +0000270 /* E-bit check */
271 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
272 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000273 {
hasso508e53e2004-05-18 18:57:06 +0000274 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000275 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000276 return;
277 }
278
hasso508e53e2004-05-18 18:57:06 +0000279 /* Find neighbor, create if not exist */
280 on = ospf6_neighbor_lookup (oh->router_id, oi);
281 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000282 {
hasso508e53e2004-05-18 18:57:06 +0000283 on = ospf6_neighbor_create (oh->router_id, oi);
284 on->prev_drouter = on->drouter = hello->drouter;
285 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
286 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000287 }
288
Vipin Kumare509af82015-05-19 18:03:40 -0700289 /* Always override neighbor's source address */
hasso7b6ae022005-06-24 08:17:51 +0000290 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
291
Vipin Kumare509af82015-05-19 18:03:40 -0700292 /* Neighbor ifindex check */
293 if (on->ifindex > 0
294 && (unsigned int) on->ifindex != ntohl (hello->interface_id))
295 {
296 on->ifindex = ntohl (hello->interface_id);
297 neighbor_ifindex_change++;
298 }
299
paul718e3742002-12-13 20:15:29 +0000300 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000301 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
302 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
303 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000304 {
hasso508e53e2004-05-18 18:57:06 +0000305 u_int32_t *router_id = (u_int32_t *) p;
306
307 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000308 twoway++;
paul718e3742002-12-13 20:15:29 +0000309 }
310
Denis Ovsienkofa079662011-10-08 17:22:45 +0400311 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000312
313 /* RouterPriority check */
314 if (on->priority != hello->priority)
315 {
316 on->priority = hello->priority;
317 neighborchange++;
318 }
319
320 /* DR check */
321 if (on->drouter != hello->drouter)
322 {
323 on->prev_drouter = on->drouter;
324 on->drouter = hello->drouter;
325 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
326 neighborchange++;
327 }
328
329 /* BDR check */
330 if (on->bdrouter != hello->bdrouter)
331 {
332 on->prev_bdrouter = on->bdrouter;
333 on->bdrouter = hello->bdrouter;
334 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
335 neighborchange++;
336 }
paul718e3742002-12-13 20:15:29 +0000337
338 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000339 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000340 {
hasso508e53e2004-05-18 18:57:06 +0000341 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000342 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000343 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000344 backupseen++;
345 }
346
hasso508e53e2004-05-18 18:57:06 +0000347 /* Execute neighbor events */
348 thread_execute (master, hello_received, on, 0);
349 if (twoway)
350 thread_execute (master, twoway_received, on, 0);
351 else
352 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000353
hasso508e53e2004-05-18 18:57:06 +0000354 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000355 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000356 thread_add_event (master, backup_seen, oi, 0);
357 if (neighborchange)
358 thread_add_event (master, neighbor_change, oi, 0);
Vipin Kumare509af82015-05-19 18:03:40 -0700359
360 if (neighbor_ifindex_change && on->state == OSPF6_NEIGHBOR_FULL)
361 OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
paul718e3742002-12-13 20:15:29 +0000362}
363
hasso508e53e2004-05-18 18:57:06 +0000364static void
365ospf6_dbdesc_recv_master (struct ospf6_header *oh,
366 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000367{
paul718e3742002-12-13 20:15:29 +0000368 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000369 char *p;
paul718e3742002-12-13 20:15:29 +0000370
hasso508e53e2004-05-18 18:57:06 +0000371 dbdesc = (struct ospf6_dbdesc *)
372 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000373
hasso508e53e2004-05-18 18:57:06 +0000374 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000375 {
hasso508e53e2004-05-18 18:57:06 +0000376 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000377 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000378 return;
379 }
380
hasso508e53e2004-05-18 18:57:06 +0000381 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000382 {
hasso508e53e2004-05-18 18:57:06 +0000383 case OSPF6_NEIGHBOR_TWOWAY:
384 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000385 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000386 return;
387
388 case OSPF6_NEIGHBOR_INIT:
389 thread_execute (master, twoway_received, on, 0);
390 if (on->state != OSPF6_NEIGHBOR_EXSTART)
391 {
392 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000393 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000394 return;
395 }
396 /* else fall through to ExStart */
397
398 case OSPF6_NEIGHBOR_EXSTART:
399 /* if neighbor obeys us as our slave, schedule negotiation_done
400 and process LSA Headers. Otherwise, ignore this message */
401 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
402 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
403 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
404 {
405 /* execute NegotiationDone */
406 thread_execute (master, negotiation_done, on, 0);
407
408 /* Record neighbor options */
409 memcpy (on->options, dbdesc->options, sizeof (on->options));
410 }
411 else
412 {
413 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000414 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000415 return;
416 }
417 /* fall through to exchange */
418
419 case OSPF6_NEIGHBOR_EXCHANGE:
420 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
421 {
422 /* Duplicated DatabaseDescription is dropped by master */
423 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000424 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000425 return;
426 }
427
428 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
429 {
430 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000431 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000432 thread_add_event (master, seqnumber_mismatch, on, 0);
433 return;
434 }
435
436 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
437 {
438 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000439 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000440 thread_add_event (master, seqnumber_mismatch, on, 0);
441 return;
442 }
443
444 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
445 {
446 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000447 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000448 thread_add_event (master, seqnumber_mismatch, on, 0);
449 return;
450 }
451
452 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
453 {
454 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000455 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000456 (u_long) on->dbdesc_seqnum);
457 thread_add_event (master, seqnumber_mismatch, on, 0);
458 return;
459 }
460 break;
461
462 case OSPF6_NEIGHBOR_LOADING:
463 case OSPF6_NEIGHBOR_FULL:
464 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
465 {
466 /* Duplicated DatabaseDescription is dropped by master */
467 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000468 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000469 return;
470 }
471
472 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000473 zlog_debug ("Not duplicate dbdesc in state %s",
474 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000475 thread_add_event (master, seqnumber_mismatch, on, 0);
476 return;
477
478 default:
479 assert (0);
480 break;
481 }
482
483 /* Process LSA headers */
484 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
485 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
486 p += sizeof (struct ospf6_lsa_header))
487 {
488 struct ospf6_lsa *his, *mine;
489 struct ospf6_lsdb *lsdb = NULL;
490
491 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000492
493 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000494 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000495
496 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000497 {
hasso6452df02004-08-15 05:52:07 +0000498 case OSPF6_SCOPE_LINKLOCAL:
499 lsdb = on->ospf6_if->lsdb;
500 break;
501 case OSPF6_SCOPE_AREA:
502 lsdb = on->ospf6_if->area->lsdb;
503 break;
504 case OSPF6_SCOPE_AS:
505 lsdb = on->ospf6_if->area->ospf6->lsdb;
506 break;
507 case OSPF6_SCOPE_RESERVED:
508 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000509 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000510 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000511 continue;
512 break;
hasso508e53e2004-05-18 18:57:06 +0000513 }
514
515 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000516 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000517 {
518 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000519 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000520 ospf6_lsa_delete (his);
521 thread_add_event (master, seqnumber_mismatch, on, 0);
522 return;
523 }
524
525 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
526 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000527 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000528 {
hasso6452df02004-08-15 05:52:07 +0000529 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000530 zlog_debug ("Add request (No database copy)");
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000531 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso6452df02004-08-15 05:52:07 +0000532 }
533 else if (ospf6_lsa_compare (his, mine) < 0)
534 {
535 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000536 zlog_debug ("Add request (Received MoreRecent)");
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000537 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso508e53e2004-05-18 18:57:06 +0000538 }
539 else
hasso6452df02004-08-15 05:52:07 +0000540 {
541 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000542 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000543 }
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000544 ospf6_lsa_delete (his);
hasso508e53e2004-05-18 18:57:06 +0000545 }
546
Denis Ovsienkofa079662011-10-08 17:22:45 +0400547 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000548
549 /* Increment sequence number */
550 on->dbdesc_seqnum ++;
551
552 /* schedule send lsreq */
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000553 if (on->request_list->count && (on->thread_send_lsreq == NULL))
hasso508e53e2004-05-18 18:57:06 +0000554 on->thread_send_lsreq =
555 thread_add_event (master, ospf6_lsreq_send, on, 0);
556
557 THREAD_OFF (on->thread_send_dbdesc);
558
559 /* More bit check */
560 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
561 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
562 thread_add_event (master, exchange_done, on, 0);
563 else
564 on->thread_send_dbdesc =
565 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
566
567 /* save last received dbdesc */
568 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
569}
570
571static void
572ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
573 struct ospf6_neighbor *on)
574{
575 struct ospf6_dbdesc *dbdesc;
576 char *p;
577
578 dbdesc = (struct ospf6_dbdesc *)
579 ((caddr_t) oh + sizeof (struct ospf6_header));
580
581 if (on->state < OSPF6_NEIGHBOR_INIT)
582 {
583 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000584 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000585 return;
586 }
587
hasso508e53e2004-05-18 18:57:06 +0000588 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000589 {
hasso508e53e2004-05-18 18:57:06 +0000590 case OSPF6_NEIGHBOR_TWOWAY:
591 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000592 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000593 return;
594
595 case OSPF6_NEIGHBOR_INIT:
596 thread_execute (master, twoway_received, on, 0);
597 if (on->state != OSPF6_NEIGHBOR_EXSTART)
598 {
599 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000600 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000601 return;
602 }
603 /* else fall through to ExStart */
604
605 case OSPF6_NEIGHBOR_EXSTART:
606 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
607 and process LSA Headers. Otherwise, ignore this message */
608 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
609 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
610 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
611 ntohs (oh->length) == sizeof (struct ospf6_header) +
612 sizeof (struct ospf6_dbdesc))
613 {
614 /* set the master/slave bit to slave */
615 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
616
617 /* set the DD sequence number to one specified by master */
618 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
619
620 /* schedule NegotiationDone */
621 thread_execute (master, negotiation_done, on, 0);
622
623 /* Record neighbor options */
624 memcpy (on->options, dbdesc->options, sizeof (on->options));
625 }
626 else
627 {
628 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000629 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000630 return;
631 }
632 break;
633
634 case OSPF6_NEIGHBOR_EXCHANGE:
635 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
636 {
637 /* Duplicated DatabaseDescription causes slave to retransmit */
638 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000639 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000640 THREAD_OFF (on->thread_send_dbdesc);
641 on->thread_send_dbdesc =
642 thread_add_event (master, ospf6_dbdesc_send, on, 0);
643 return;
644 }
645
646 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
647 {
648 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000649 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000650 thread_add_event (master, seqnumber_mismatch, on, 0);
651 return;
652 }
653
654 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
655 {
656 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000657 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000658 thread_add_event (master, seqnumber_mismatch, on, 0);
659 return;
660 }
661
662 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
663 {
664 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000665 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000666 thread_add_event (master, seqnumber_mismatch, on, 0);
667 return;
668 }
669
670 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
671 {
672 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000673 zlog_debug ("Sequence number mismatch (%#lx expected)",
674 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000675 thread_add_event (master, seqnumber_mismatch, on, 0);
676 return;
677 }
678 break;
679
680 case OSPF6_NEIGHBOR_LOADING:
681 case OSPF6_NEIGHBOR_FULL:
682 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
683 {
684 /* Duplicated DatabaseDescription causes slave to retransmit */
685 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000686 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000687 THREAD_OFF (on->thread_send_dbdesc);
688 on->thread_send_dbdesc =
689 thread_add_event (master, ospf6_dbdesc_send, on, 0);
690 return;
691 }
692
693 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000694 zlog_debug ("Not duplicate dbdesc in state %s",
695 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000696 thread_add_event (master, seqnumber_mismatch, on, 0);
697 return;
698
699 default:
700 assert (0);
701 break;
paul718e3742002-12-13 20:15:29 +0000702 }
703
hasso508e53e2004-05-18 18:57:06 +0000704 /* Process LSA headers */
705 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
706 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
707 p += sizeof (struct ospf6_lsa_header))
708 {
709 struct ospf6_lsa *his, *mine;
710 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000711
hasso508e53e2004-05-18 18:57:06 +0000712 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000713
714 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000715 {
hasso6452df02004-08-15 05:52:07 +0000716 case OSPF6_SCOPE_LINKLOCAL:
717 lsdb = on->ospf6_if->lsdb;
718 break;
719 case OSPF6_SCOPE_AREA:
720 lsdb = on->ospf6_if->area->lsdb;
721 break;
722 case OSPF6_SCOPE_AS:
723 lsdb = on->ospf6_if->area->ospf6->lsdb;
724 break;
725 case OSPF6_SCOPE_RESERVED:
726 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000727 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000728 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000729 continue;
730 break;
hasso508e53e2004-05-18 18:57:06 +0000731 }
732
hasso6452df02004-08-15 05:52:07 +0000733 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
734 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000735 {
736 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000737 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000738 ospf6_lsa_delete (his);
739 thread_add_event (master, seqnumber_mismatch, on, 0);
740 return;
741 }
742
743 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
744 his->header->adv_router, lsdb);
745 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
746 {
hasso6452df02004-08-15 05:52:07 +0000747 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000748 zlog_debug ("Add request-list: %s", his->name);
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000749 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso508e53e2004-05-18 18:57:06 +0000750 }
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000751 ospf6_lsa_delete (his);
hasso508e53e2004-05-18 18:57:06 +0000752 }
753
Denis Ovsienkofa079662011-10-08 17:22:45 +0400754 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000755
756 /* Set sequence number to Master's */
757 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
758
759 /* schedule send lsreq */
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000760 if ((on->thread_send_lsreq == NULL) &&
761 (on->request_list->count))
hasso508e53e2004-05-18 18:57:06 +0000762 on->thread_send_lsreq =
763 thread_add_event (master, ospf6_lsreq_send, on, 0);
764
765 THREAD_OFF (on->thread_send_dbdesc);
766 on->thread_send_dbdesc =
767 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
768
769 /* save last received dbdesc */
770 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000771}
772
Paul Jakma6ac29a52008-08-15 13:45:30 +0100773static void
hasso508e53e2004-05-18 18:57:06 +0000774ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
775 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000776{
hasso508e53e2004-05-18 18:57:06 +0000777 struct ospf6_neighbor *on;
778 struct ospf6_dbdesc *dbdesc;
779
hasso508e53e2004-05-18 18:57:06 +0000780 on = ospf6_neighbor_lookup (oh->router_id, oi);
781 if (on == NULL)
782 {
783 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000784 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000785 return;
786 }
787
hasso508e53e2004-05-18 18:57:06 +0000788 dbdesc = (struct ospf6_dbdesc *)
789 ((caddr_t) oh + sizeof (struct ospf6_header));
790
791 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400792 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000793 {
794 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000795 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000796 return;
797 }
798
799 if (dbdesc->reserved1 || dbdesc->reserved2)
800 {
801 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000802 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
803 on->name);
hasso508e53e2004-05-18 18:57:06 +0000804 dbdesc->reserved1 = 0;
805 dbdesc->reserved2 = 0;
806 }
807
808 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
809 ospf6_dbdesc_recv_master (oh, on);
810 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
811 ospf6_dbdesc_recv_slave (oh, on);
812 else
813 {
814 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000815 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000816 }
817}
818
Paul Jakma6ac29a52008-08-15 13:45:30 +0100819static void
hasso508e53e2004-05-18 18:57:06 +0000820ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
821 struct ospf6_interface *oi, struct ospf6_header *oh)
822{
823 struct ospf6_neighbor *on;
824 char *p;
825 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000826 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000827 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000828
hasso508e53e2004-05-18 18:57:06 +0000829 on = ospf6_neighbor_lookup (oh->router_id, oi);
830 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000831 {
hasso508e53e2004-05-18 18:57:06 +0000832 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000833 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000834 return;
835 }
836
hasso508e53e2004-05-18 18:57:06 +0000837 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
838 on->state != OSPF6_NEIGHBOR_LOADING &&
839 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000840 {
hasso508e53e2004-05-18 18:57:06 +0000841 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000842 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000843 return;
844 }
845
hasso508e53e2004-05-18 18:57:06 +0000846 /* Process each request */
847 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
848 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
849 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000850 {
hasso508e53e2004-05-18 18:57:06 +0000851 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000852
853 switch (OSPF6_LSA_SCOPE (e->type))
854 {
855 case OSPF6_SCOPE_LINKLOCAL:
856 lsdb = on->ospf6_if->lsdb;
857 break;
858 case OSPF6_SCOPE_AREA:
859 lsdb = on->ospf6_if->area->lsdb;
860 break;
861 case OSPF6_SCOPE_AS:
862 lsdb = on->ospf6_if->area->ospf6->lsdb;
863 break;
864 default:
865 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000866 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000867 continue;
868 break;
869 }
paul718e3742002-12-13 20:15:29 +0000870
hasso508e53e2004-05-18 18:57:06 +0000871 /* Find database copy */
872 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
873 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000874 {
hasso508e53e2004-05-18 18:57:06 +0000875 char id[16], adv_router[16];
876 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
877 {
878 inet_ntop (AF_INET, &e->id, id, sizeof (id));
879 inet_ntop (AF_INET, &e->adv_router, adv_router,
880 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000881 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
882 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000883 }
884 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000885 return;
886 }
887
hasso508e53e2004-05-18 18:57:06 +0000888 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000889 }
890
Denis Ovsienkofa079662011-10-08 17:22:45 +0400891 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000892
hasso508e53e2004-05-18 18:57:06 +0000893 /* schedule send lsupdate */
894 THREAD_OFF (on->thread_send_lsupdate);
895 on->thread_send_lsupdate =
896 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000897}
898
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400899/* Verify, that the specified memory area contains exactly N valid IPv6
900 prefixes as specified by RFC5340, A.4.1. */
901static unsigned
902ospf6_prefixes_examin
903(
904 struct ospf6_prefix *current, /* start of buffer */
905 unsigned length,
906 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
907)
908{
909 u_char requested_pfx_bytes;
910 u_int32_t real_num_pfxs = 0;
911
912 while (length)
913 {
914 if (length < OSPF6_PREFIX_MIN_SIZE)
915 {
916 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
917 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
918 return MSG_NG;
919 }
920 /* safe to look deeper */
921 if (current->prefix_length > IPV6_MAX_BITLEN)
922 {
923 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
924 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
925 return MSG_NG;
926 }
927 /* covers both fixed- and variable-sized fields */
928 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
929 if (requested_pfx_bytes > length)
930 {
931 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
932 zlog_debug ("%s: undersized IPv6 prefix", __func__);
933 return MSG_NG;
934 }
935 /* next prefix */
936 length -= requested_pfx_bytes;
937 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
938 real_num_pfxs++;
939 }
940 if (real_num_pfxs != req_num_pfxs)
941 {
942 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
943 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
944 __func__, req_num_pfxs, real_num_pfxs);
945 return MSG_NG;
946 }
947 return MSG_OK;
948}
949
950/* Verify an LSA to have a valid length and dispatch further (where
951 appropriate) to check if the contents, including nested IPv6 prefixes,
952 is properly sized/aligned within the LSA. Note that this function gets
953 LSA type in network byte order, uses in host byte order and passes to
954 ospf6_lstype_name() in network byte order again. */
955static unsigned
956ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
957{
958 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
959 struct ospf6_as_external_lsa *as_external_lsa;
960 struct ospf6_link_lsa *link_lsa;
961 unsigned exp_length;
962 u_int8_t ltindex;
963 u_int16_t lsatype;
964
965 /* In case an additional minimum length constraint is defined for current
966 LSA type, make sure that this constraint is met. */
967 lsatype = ntohs (lsah->type);
968 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
969 if
970 (
971 ltindex < OSPF6_LSTYPE_SIZE &&
972 ospf6_lsa_minlen[ltindex] &&
973 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
974 )
975 {
976 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
977 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
978 return MSG_NG;
979 }
980 switch (lsatype)
981 {
982 case OSPF6_LSTYPE_ROUTER:
983 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
984 by N>=0 interface descriptions. */
985 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
986 {
987 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
988 zlog_debug ("%s: interface description alignment error", __func__);
989 return MSG_NG;
990 }
991 break;
992 case OSPF6_LSTYPE_NETWORK:
993 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
994 followed by N>=0 attached router descriptions. */
995 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
996 {
997 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
998 zlog_debug ("%s: router description alignment error", __func__);
999 return MSG_NG;
1000 }
1001 break;
1002 case OSPF6_LSTYPE_INTER_PREFIX:
1003 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
1004 followed by 3-4 fields of a single IPv6 prefix. */
1005 if (headeronly)
1006 break;
1007 return ospf6_prefixes_examin
1008 (
1009 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1010 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1011 1
1012 );
1013 case OSPF6_LSTYPE_INTER_ROUTER:
1014 /* RFC5340 A.4.6, fixed-size LSA. */
1015 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1016 {
1017 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1018 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1019 return MSG_NG;
1020 }
1021 break;
1022 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1023 case OSPF6_LSTYPE_TYPE_7:
1024 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1025 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1026 16 bytes of forwarding address, 4 bytes of external route tag,
1027 4 bytes of referenced link state ID. */
1028 if (headeronly)
1029 break;
1030 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1031 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1032 /* To find out if the last optional field (Referenced Link State ID) is
1033 assumed in this LSA, we need to access fixed fields of the IPv6
1034 prefix before ospf6_prefix_examin() confirms its sizing. */
1035 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1036 {
1037 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1038 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1039 return MSG_NG;
1040 }
1041 /* forwarding address */
1042 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1043 exp_length += 16;
1044 /* external route tag */
1045 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1046 exp_length += 4;
1047 /* referenced link state ID */
1048 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1049 exp_length += 4;
1050 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1051 this check does not include any IPv6 prefix fields. */
1052 if (exp_length > lsalen)
1053 {
1054 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1055 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1056 return MSG_NG;
1057 }
1058 /* The last call completely covers the remainder (IPv6 prefix). */
1059 return ospf6_prefixes_examin
1060 (
1061 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1062 lsalen - exp_length,
1063 1
1064 );
1065 case OSPF6_LSTYPE_LINK:
1066 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1067 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1068 if (headeronly)
1069 break;
1070 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1071 return ospf6_prefixes_examin
1072 (
1073 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1074 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1075 ntohl (link_lsa->prefix_num) /* 32 bits */
1076 );
1077 case OSPF6_LSTYPE_INTRA_PREFIX:
1078 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1079 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1080 if (headeronly)
1081 break;
1082 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1083 return ospf6_prefixes_examin
1084 (
1085 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1086 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1087 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1088 );
1089 }
1090 /* No additional validation is possible for unknown LSA types, which are
1091 themselves valid in OPSFv3, hence the default decision is to accept. */
1092 return MSG_OK;
1093}
1094
1095/* Verify if the provided input buffer is a valid sequence of LSAs. This
1096 includes verification of LSA blocks length/alignment and dispatching
1097 of deeper-level checks. */
1098static unsigned
1099ospf6_lsaseq_examin
1100(
1101 struct ospf6_lsa_header *lsah, /* start of buffered data */
1102 size_t length,
1103 const u_char headeronly,
1104 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1105 and treat the difference as an error. */
1106 const u_int32_t declared_num_lsas
1107)
1108{
1109 u_int32_t counted_lsas = 0;
1110
1111 while (length)
1112 {
1113 u_int16_t lsalen;
1114 if (length < OSPF6_LSA_HEADER_SIZE)
1115 {
1116 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001117 zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001118 __func__, length, counted_lsas);
1119 return MSG_NG;
1120 }
1121 /* save on ntohs() calls here and in the LSA validator */
1122 lsalen = OSPF6_LSA_SIZE (lsah);
1123 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1124 {
1125 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1126 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1127 __func__, counted_lsas, lsalen);
1128 return MSG_NG;
1129 }
1130 if (headeronly)
1131 {
1132 /* less checks here and in ospf6_lsa_examin() */
1133 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1134 {
1135 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1136 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1137 ospf6_lstype_name (lsah->type), counted_lsas);
1138 return MSG_NG;
1139 }
1140 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1141 length -= OSPF6_LSA_HEADER_SIZE;
1142 }
1143 else
1144 {
1145 /* make sure the input buffer is deep enough before further checks */
1146 if (lsalen > length)
1147 {
1148 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001149 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 +04001150 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1151 return MSG_NG;
1152 }
1153 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1154 {
1155 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1156 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1157 ospf6_lstype_name (lsah->type), counted_lsas);
1158 return MSG_NG;
1159 }
1160 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1161 length -= lsalen;
1162 }
1163 counted_lsas++;
1164 }
1165
1166 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1167 {
1168 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1169 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1170 __func__, declared_num_lsas, counted_lsas);
1171 return MSG_NG;
1172 }
1173 return MSG_OK;
1174}
1175
1176/* Verify a complete OSPF packet for proper sizing/alignment. */
1177static unsigned
1178ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1179{
1180 struct ospf6_lsupdate *lsupd;
1181 unsigned test;
1182
1183 /* length, 1st approximation */
1184 if (bytesonwire < OSPF6_HEADER_SIZE)
1185 {
1186 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1187 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1188 return MSG_NG;
1189 }
1190 /* Now it is safe to access header fields. */
1191 if (bytesonwire != ntohs (oh->length))
1192 {
1193 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1194 zlog_debug ("%s: packet length error (%u real, %u declared)",
1195 __func__, bytesonwire, ntohs (oh->length));
1196 return MSG_NG;
1197 }
1198 /* version check */
1199 if (oh->version != OSPFV3_VERSION)
1200 {
1201 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1202 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1203 return MSG_NG;
1204 }
1205 /* length, 2nd approximation */
1206 if
1207 (
1208 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1209 ospf6_packet_minlen[oh->type] &&
1210 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1211 )
1212 {
1213 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1214 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001215 bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001216 return MSG_NG;
1217 }
1218 /* type-specific deeper validation */
1219 switch (oh->type)
1220 {
1221 case OSPF6_MESSAGE_TYPE_HELLO:
1222 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1223 by N>=0 router-IDs. */
1224 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1225 return MSG_OK;
1226 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1227 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001228 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001229 return MSG_NG;
1230 case OSPF6_MESSAGE_TYPE_DBDESC:
1231 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1232 by N>=0 header-only LSAs. */
1233 test = ospf6_lsaseq_examin
1234 (
1235 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1236 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1237 1,
1238 0
1239 );
1240 break;
1241 case OSPF6_MESSAGE_TYPE_LSREQ:
1242 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1243 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1244 return MSG_OK;
1245 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1246 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001247 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001248 return MSG_NG;
1249 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1250 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1251 by N>=0 full LSAs (with N declared beforehand). */
1252 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1253 test = ospf6_lsaseq_examin
1254 (
1255 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1256 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1257 0,
1258 ntohl (lsupd->lsa_number) /* 32 bits */
1259 );
1260 break;
1261 case OSPF6_MESSAGE_TYPE_LSACK:
1262 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1263 test = ospf6_lsaseq_examin
1264 (
1265 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1266 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1267 1,
1268 0
1269 );
1270 break;
1271 default:
1272 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1273 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1274 return MSG_NG;
1275 }
1276 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001277 zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001278 return test;
1279}
1280
1281/* Verify particular fields of otherwise correct received OSPF packet to
1282 meet the requirements of RFC. */
1283static int
1284ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1285{
1286 char buf[2][INET_ADDRSTRLEN];
1287
1288 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1289 return MSG_NG;
1290
1291 /* Area-ID check */
1292 if (oh->area_id != oi->area->area_id)
1293 {
1294 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1295 {
Dinesh Dutt8551e6d2013-10-22 17:42:18 -07001296 if (oh->area_id == OSPF_AREA_BACKBONE)
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001297 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1298 else
1299 zlog_debug
1300 (
1301 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1302 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1303 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1304 );
1305 }
1306 return MSG_NG;
1307 }
1308
1309 /* Instance-ID check */
1310 if (oh->instance_id != oi->instance_id)
1311 {
1312 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1313 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1314 return MSG_NG;
1315 }
1316
1317 /* Router-ID check */
1318 if (oh->router_id == oi->area->ospf6->router_id)
1319 {
1320 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1321 return MSG_NG;
1322 }
1323 return MSG_OK;
1324}
1325
Paul Jakma6ac29a52008-08-15 13:45:30 +01001326static void
hasso508e53e2004-05-18 18:57:06 +00001327ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1328 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001329{
hasso508e53e2004-05-18 18:57:06 +00001330 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001331 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001332 char *p;
paul718e3742002-12-13 20:15:29 +00001333
hasso508e53e2004-05-18 18:57:06 +00001334 on = ospf6_neighbor_lookup (oh->router_id, oi);
1335 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001336 {
hasso508e53e2004-05-18 18:57:06 +00001337 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001338 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001339 return;
1340 }
1341
hasso508e53e2004-05-18 18:57:06 +00001342 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1343 on->state != OSPF6_NEIGHBOR_LOADING &&
1344 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001345 {
hasso508e53e2004-05-18 18:57:06 +00001346 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001347 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001348 return;
1349 }
1350
hasso508e53e2004-05-18 18:57:06 +00001351 lsupdate = (struct ospf6_lsupdate *)
1352 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001353
hasso508e53e2004-05-18 18:57:06 +00001354 /* Process LSAs */
1355 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1356 p < OSPF6_MESSAGE_END (oh) &&
1357 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1358 p += OSPF6_LSA_SIZE (p))
1359 {
hasso6452df02004-08-15 05:52:07 +00001360 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001361 }
1362
Denis Ovsienkofa079662011-10-08 17:22:45 +04001363 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001364
paul718e3742002-12-13 20:15:29 +00001365}
1366
Paul Jakma6ac29a52008-08-15 13:45:30 +01001367static void
hasso508e53e2004-05-18 18:57:06 +00001368ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1369 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001370{
hasso508e53e2004-05-18 18:57:06 +00001371 struct ospf6_neighbor *on;
1372 char *p;
1373 struct ospf6_lsa *his, *mine;
1374 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001375
hasso508e53e2004-05-18 18:57:06 +00001376 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001377
hasso508e53e2004-05-18 18:57:06 +00001378 on = ospf6_neighbor_lookup (oh->router_id, oi);
1379 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001380 {
hasso508e53e2004-05-18 18:57:06 +00001381 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001382 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001383 return;
1384 }
1385
hasso508e53e2004-05-18 18:57:06 +00001386 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1387 on->state != OSPF6_NEIGHBOR_LOADING &&
1388 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001389 {
hasso508e53e2004-05-18 18:57:06 +00001390 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001391 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001392 return;
1393 }
1394
hasso508e53e2004-05-18 18:57:06 +00001395 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1396 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1397 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001398 {
hasso508e53e2004-05-18 18:57:06 +00001399 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001400
hasso6452df02004-08-15 05:52:07 +00001401 switch (OSPF6_LSA_SCOPE (his->header->type))
1402 {
1403 case OSPF6_SCOPE_LINKLOCAL:
1404 lsdb = on->ospf6_if->lsdb;
1405 break;
1406 case OSPF6_SCOPE_AREA:
1407 lsdb = on->ospf6_if->area->lsdb;
1408 break;
1409 case OSPF6_SCOPE_AS:
1410 lsdb = on->ospf6_if->area->ospf6->lsdb;
1411 break;
1412 case OSPF6_SCOPE_RESERVED:
1413 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001414 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001415 ospf6_lsa_delete (his);
1416 continue;
1417 break;
1418 }
1419
1420 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001421 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001422
1423 /* Find database copy */
1424 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1425 his->header->adv_router, lsdb);
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 ("No database copy");
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 /* Check if the LSA is on his retrans-list */
1435 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1436 his->header->adv_router, on->retrans_list);
1437 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001438 {
hasso508e53e2004-05-18 18:57:06 +00001439 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001440 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001441 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001442 continue;
1443 }
1444
hasso508e53e2004-05-18 18:57:06 +00001445 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001446 {
hasso508e53e2004-05-18 18:57:06 +00001447 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001448 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001449 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001450 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001451 ospf6_lsa_delete (his);
1452 continue;
paul718e3742002-12-13 20:15:29 +00001453 }
1454
hasso6452df02004-08-15 05:52:07 +00001455 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001456 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1457 on->name);
hasso508e53e2004-05-18 18:57:06 +00001458
Paul Jakma932bf192006-05-15 10:42:24 +00001459 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001460 if (OSPF6_LSA_IS_MAXAGE (mine))
1461 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001462 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001463 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001464 }
1465
Denis Ovsienkofa079662011-10-08 17:22:45 +04001466 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001467}
1468
Paul Jakma6ac29a52008-08-15 13:45:30 +01001469static u_char *recvbuf = NULL;
1470static u_char *sendbuf = NULL;
1471static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001472
1473int
paul0c083ee2004-10-10 12:54:58 +00001474ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001475{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001476 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001477
1478 if (size <= iobuflen)
1479 return iobuflen;
1480
1481 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1482 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1483 if (recvnew == NULL || sendnew == NULL)
1484 {
hassob596c712004-07-09 18:33:43 +00001485 if (recvnew)
1486 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1487 if (sendnew)
1488 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001489 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001490 return iobuflen;
1491 }
1492
1493 if (recvbuf)
1494 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1495 if (sendbuf)
1496 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1497 recvbuf = recvnew;
1498 sendbuf = sendnew;
1499 iobuflen = size;
1500
1501 return iobuflen;
1502}
paul718e3742002-12-13 20:15:29 +00001503
Tom Goffae2254a2010-11-10 13:01:41 -08001504void
1505ospf6_message_terminate (void)
1506{
1507 if (recvbuf)
1508 {
1509 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1510 recvbuf = NULL;
1511 }
1512
1513 if (sendbuf)
1514 {
1515 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1516 sendbuf = NULL;
1517 }
1518
1519 iobuflen = 0;
1520}
1521
paul718e3742002-12-13 20:15:29 +00001522int
1523ospf6_receive (struct thread *thread)
1524{
paul0c083ee2004-10-10 12:54:58 +00001525 int sockfd;
1526 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001527 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001528 struct in6_addr src, dst;
Paul Jakma9099f9b2016-01-18 10:12:10 +00001529 ifindex_t ifindex;
hasso508e53e2004-05-18 18:57:06 +00001530 struct iovec iovector[2];
1531 struct ospf6_interface *oi;
1532 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001533
1534 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001535 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001536 thread_add_read (master, ospf6_receive, NULL, sockfd);
1537
1538 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001539 memset (&src, 0, sizeof (src));
1540 memset (&dst, 0, sizeof (dst));
1541 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001542 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001543 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001544 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001545 iovector[1].iov_base = NULL;
1546 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001547
1548 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001549 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001550 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001551 {
hasso508e53e2004-05-18 18:57:06 +00001552 zlog_err ("Excess message read");
1553 return 0;
1554 }
paul718e3742002-12-13 20:15:29 +00001555
hasso508e53e2004-05-18 18:57:06 +00001556 oi = ospf6_interface_lookup_by_ifindex (ifindex);
Christian Franked9628722013-03-08 21:47:35 +01001557 if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
hasso508e53e2004-05-18 18:57:06 +00001558 {
hassoc6487d62004-12-24 06:00:11 +00001559 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001560 return 0;
1561 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001562 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1563 {
1564 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1565 zlog_debug ("%s: Ignore message on passive interface %s",
1566 __func__, oi->interface->name);
1567 return 0;
1568 }
hasso508e53e2004-05-18 18:57:06 +00001569
1570 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001571 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1572 return 0;
1573
1574 /* Being here means, that no sizing/alignment issues were detected in
1575 the input packet. This renders the additional checks performed below
1576 and also in the type-specific dispatching functions a dead code,
1577 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001578
1579 /* Log */
1580 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1581 {
1582 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1583 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001584 zlog_debug ("%s received on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001585 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001586 zlog_debug (" src: %s", srcname);
1587 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001588
1589 switch (oh->type)
1590 {
1591 case OSPF6_MESSAGE_TYPE_HELLO:
1592 ospf6_hello_print (oh);
1593 break;
1594 case OSPF6_MESSAGE_TYPE_DBDESC:
1595 ospf6_dbdesc_print (oh);
1596 break;
1597 case OSPF6_MESSAGE_TYPE_LSREQ:
1598 ospf6_lsreq_print (oh);
1599 break;
1600 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1601 ospf6_lsupdate_print (oh);
1602 break;
1603 case OSPF6_MESSAGE_TYPE_LSACK:
1604 ospf6_lsack_print (oh);
1605 break;
1606 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001607 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001608 }
1609 }
1610
hasso508e53e2004-05-18 18:57:06 +00001611 switch (oh->type)
1612 {
1613 case OSPF6_MESSAGE_TYPE_HELLO:
1614 ospf6_hello_recv (&src, &dst, oi, oh);
1615 break;
1616
1617 case OSPF6_MESSAGE_TYPE_DBDESC:
1618 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1619 break;
1620
1621 case OSPF6_MESSAGE_TYPE_LSREQ:
1622 ospf6_lsreq_recv (&src, &dst, oi, oh);
1623 break;
1624
1625 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1626 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1627 break;
1628
1629 case OSPF6_MESSAGE_TYPE_LSACK:
1630 ospf6_lsack_recv (&src, &dst, oi, oh);
1631 break;
1632
1633 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001634 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001635 }
1636
1637 return 0;
1638}
1639
Paul Jakma6ac29a52008-08-15 13:45:30 +01001640static void
hasso508e53e2004-05-18 18:57:06 +00001641ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1642 struct ospf6_interface *oi, struct ospf6_header *oh)
1643{
Donald Sharp0bc874b2015-07-29 19:16:13 -04001644 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001645 char srcname[64], dstname[64];
1646 struct iovec iovector[2];
1647
1648 /* initialize */
1649 iovector[0].iov_base = (caddr_t) oh;
1650 iovector[0].iov_len = ntohs (oh->length);
1651 iovector[1].iov_base = NULL;
1652 iovector[1].iov_len = 0;
1653
1654 /* fill OSPF header */
1655 oh->version = OSPFV3_VERSION;
1656 /* message type must be set before */
1657 /* message length must be set before */
1658 oh->router_id = oi->area->ospf6->router_id;
1659 oh->area_id = oi->area->area_id;
1660 /* checksum is calculated by kernel */
1661 oh->instance_id = oi->instance_id;
1662 oh->reserved = 0;
1663
1664 /* Log */
1665 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1666 {
1667 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1668 if (src)
1669 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1670 else
1671 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001672 zlog_debug ("%s send on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001673 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001674 zlog_debug (" src: %s", srcname);
1675 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001676
1677 switch (oh->type)
1678 {
1679 case OSPF6_MESSAGE_TYPE_HELLO:
1680 ospf6_hello_print (oh);
1681 break;
1682 case OSPF6_MESSAGE_TYPE_DBDESC:
1683 ospf6_dbdesc_print (oh);
1684 break;
1685 case OSPF6_MESSAGE_TYPE_LSREQ:
1686 ospf6_lsreq_print (oh);
1687 break;
1688 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1689 ospf6_lsupdate_print (oh);
1690 break;
1691 case OSPF6_MESSAGE_TYPE_LSACK:
1692 ospf6_lsack_print (oh);
1693 break;
1694 default:
hassoc6487d62004-12-24 06:00:11 +00001695 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001696 assert (0);
1697 break;
1698 }
1699 }
1700
1701 /* send message */
1702 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1703 if (len != ntohs (oh->length))
1704 zlog_err ("Could not send entire message");
1705}
1706
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001707static uint32_t
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001708ospf6_packet_max(struct ospf6_interface *oi)
1709{
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001710 assert (oi->ifmtu > sizeof (struct ip6_hdr));
1711 return oi->ifmtu - (sizeof (struct ip6_hdr));
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001712}
1713
hasso508e53e2004-05-18 18:57:06 +00001714int
1715ospf6_hello_send (struct thread *thread)
1716{
1717 struct ospf6_interface *oi;
1718 struct ospf6_header *oh;
1719 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001720 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001721 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001722 struct ospf6_neighbor *on;
1723
1724 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1725 oi->thread_send_hello = (struct thread *) NULL;
1726
1727 if (oi->state <= OSPF6_INTERFACE_DOWN)
1728 {
1729 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001730 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001731 oi->interface->name);
1732 return 0;
1733 }
1734
Ingo Flaschberger1db65fa2011-04-17 18:28:20 +00001735 if (iobuflen == 0)
1736 {
1737 zlog_debug ("Unable to send Hello on interface %s iobuflen is 0",
1738 oi->interface->name);
1739 return 0;
1740 }
1741
hasso508e53e2004-05-18 18:57:06 +00001742 /* set next thread */
1743 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1744 oi, oi->hello_interval);
1745
hasso3b4cd3a2004-05-18 19:28:32 +00001746 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001747 oh = (struct ospf6_header *) sendbuf;
1748 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1749
1750 hello->interface_id = htonl (oi->interface->ifindex);
1751 hello->priority = oi->priority;
1752 hello->options[0] = oi->area->options[0];
1753 hello->options[1] = oi->area->options[1];
1754 hello->options[2] = oi->area->options[2];
1755 hello->hello_interval = htons (oi->hello_interval);
1756 hello->dead_interval = htons (oi->dead_interval);
1757 hello->drouter = oi->drouter;
1758 hello->bdrouter = oi->bdrouter;
1759
Paul Jakma6ac29a52008-08-15 13:45:30 +01001760 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001761
paul1eb8ef22005-04-07 07:30:20 +00001762 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001763 {
hasso508e53e2004-05-18 18:57:06 +00001764 if (on->state < OSPF6_NEIGHBOR_INIT)
1765 continue;
1766
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001767 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001768 {
1769 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001770 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001771 break;
1772 }
1773
1774 memcpy (p, &on->router_id, sizeof (u_int32_t));
1775 p += sizeof (u_int32_t);
1776 }
1777
1778 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1779 oh->length = htons (p - sendbuf);
1780
1781 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1782 return 0;
1783}
1784
1785int
1786ospf6_dbdesc_send (struct thread *thread)
1787{
1788 struct ospf6_neighbor *on;
1789 struct ospf6_header *oh;
1790 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001791 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001792 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00001793 struct in6_addr *dst;
hasso508e53e2004-05-18 18:57:06 +00001794
1795 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1796 on->thread_send_dbdesc = (struct thread *) NULL;
1797
1798 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1799 {
1800 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001801 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1802 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001803 return 0;
1804 }
1805
1806 /* set next thread if master */
1807 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1808 on->thread_send_dbdesc =
1809 thread_add_timer (master, ospf6_dbdesc_send, on,
1810 on->ospf6_if->rxmt_interval);
1811
hasso3b4cd3a2004-05-18 19:28:32 +00001812 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001813 oh = (struct ospf6_header *) sendbuf;
1814 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1815 sizeof (struct ospf6_header));
1816
1817 /* if this is initial one, initialize sequence number for DbDesc */
Dinesh Dutt7a10a352013-08-25 03:03:07 +00001818 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
1819 (on->dbdesc_seqnum == 0))
hasso508e53e2004-05-18 18:57:06 +00001820 {
1821 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001822 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001823 tv.tv_sec = 1;
1824 on->dbdesc_seqnum = tv.tv_sec;
1825 }
1826
1827 dbdesc->options[0] = on->ospf6_if->area->options[0];
1828 dbdesc->options[1] = on->ospf6_if->area->options[1];
1829 dbdesc->options[2] = on->ospf6_if->area->options[2];
1830 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1831 dbdesc->bits = on->dbdesc_bits;
1832 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1833
1834 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001835 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001836 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1837 {
1838 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1839 lsa = ospf6_lsdb_next (lsa))
1840 {
1841 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1842
1843 /* MTU check */
1844 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001845 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001846 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001847 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001848 break;
1849 }
1850 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1851 p += sizeof (struct ospf6_lsa_header);
1852 }
1853 }
1854
1855 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1856 oh->length = htons (p - sendbuf);
1857
Dinesh Duttc5926a92013-08-24 07:55:00 +00001858
1859 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1860 dst = &allspfrouters6;
1861 else
1862 dst = &on->linklocal_addr;
1863
1864 ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
1865
hasso508e53e2004-05-18 18:57:06 +00001866 return 0;
1867}
1868
1869int
1870ospf6_dbdesc_send_newone (struct thread *thread)
1871{
1872 struct ospf6_neighbor *on;
1873 struct ospf6_lsa *lsa;
1874 unsigned int size = 0;
1875
1876 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001877 ospf6_lsdb_remove_all (on->dbdesc_list);
1878
1879 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1880 so that ospf6_send_dbdesc () can send those LSAs */
1881 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1882 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1883 lsa = ospf6_lsdb_next (lsa))
1884 {
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001885 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001886 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001887 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001888 break;
1889 }
1890
hasso508e53e2004-05-18 18:57:06 +00001891 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1892 ospf6_lsdb_remove (lsa, on->summary_list);
1893 size += sizeof (struct ospf6_lsa_header);
1894 }
1895
1896 if (on->summary_list->count == 0)
1897 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1898
1899 /* If slave, More bit check must be done here */
1900 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1901 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1902 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1903 thread_add_event (master, exchange_done, on, 0);
1904
1905 thread_execute (master, ospf6_dbdesc_send, on, 0);
1906 return 0;
1907}
1908
1909int
1910ospf6_lsreq_send (struct thread *thread)
1911{
1912 struct ospf6_neighbor *on;
1913 struct ospf6_header *oh;
1914 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001915 u_char *p;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001916 struct ospf6_lsa *lsa, *last_req;
hasso508e53e2004-05-18 18:57:06 +00001917
1918 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1919 on->thread_send_lsreq = (struct thread *) NULL;
1920
1921 /* LSReq will be sent only in ExStart or Loading */
1922 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1923 on->state != OSPF6_NEIGHBOR_LOADING)
1924 {
1925 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001926 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1927 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001928 return 0;
1929 }
1930
1931 /* schedule loading_done if request list is empty */
1932 if (on->request_list->count == 0)
1933 {
1934 thread_add_event (master, loading_done, on, 0);
1935 return 0;
1936 }
1937
hasso3b4cd3a2004-05-18 19:28:32 +00001938 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001939 oh = (struct ospf6_header *) sendbuf;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001940 last_req = NULL;
hasso508e53e2004-05-18 18:57:06 +00001941
1942 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001943 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001944 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1945 lsa = ospf6_lsdb_next (lsa))
1946 {
1947 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001948 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001949 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001950 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001951 break;
1952 }
1953
1954 e = (struct ospf6_lsreq_entry *) p;
1955 e->type = lsa->header->type;
1956 e->id = lsa->header->id;
1957 e->adv_router = lsa->header->adv_router;
1958 p += sizeof (struct ospf6_lsreq_entry);
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001959 last_req = lsa;
1960 }
1961
1962 if (last_req != NULL)
1963 {
1964 if (on->last_ls_req != NULL)
1965 {
1966 ospf6_lsa_unlock (on->last_ls_req);
1967 }
1968 ospf6_lsa_lock (last_req);
1969 on->last_ls_req = last_req;
hasso508e53e2004-05-18 18:57:06 +00001970 }
1971
1972 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1973 oh->length = htons (p - sendbuf);
1974
Dinesh Duttc5926a92013-08-24 07:55:00 +00001975 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1976 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
hasso508e53e2004-05-18 18:57:06 +00001977 on->ospf6_if, oh);
Dinesh Duttc5926a92013-08-24 07:55:00 +00001978 else
1979 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1980 on->ospf6_if, oh);
1981
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001982 /* set next thread */
1983 if (on->request_list->count != 0)
1984 {
1985 on->thread_send_lsreq =
1986 thread_add_timer (master, ospf6_lsreq_send, on,
1987 on->ospf6_if->rxmt_interval);
1988 }
1989
hasso508e53e2004-05-18 18:57:06 +00001990 return 0;
1991}
1992
1993int
1994ospf6_lsupdate_send_neighbor (struct thread *thread)
1995{
1996 struct ospf6_neighbor *on;
1997 struct ospf6_header *oh;
1998 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001999 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002000 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00002001 struct ospf6_lsa *lsa;
2002
2003 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2004 on->thread_send_lsupdate = (struct thread *) NULL;
2005
hasso6452df02004-08-15 05:52:07 +00002006 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002007 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00002008
hasso508e53e2004-05-18 18:57:06 +00002009 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2010 {
2011 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002012 zlog_debug ("Quit to send (neighbor state %s)",
2013 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002014 return 0;
2015 }
2016
hasso3b4cd3a2004-05-18 19:28:32 +00002017 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002018 oh = (struct ospf6_header *) sendbuf;
2019 lsupdate = (struct ospf6_lsupdate *)
2020 ((caddr_t) oh + sizeof (struct ospf6_header));
2021
Paul Jakma6ac29a52008-08-15 13:45:30 +01002022 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002023 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002024
2025 /* lsupdate_list lists those LSA which doesn't need to be
2026 retransmitted. remove those from the list */
2027 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2028 lsa = ospf6_lsdb_next (lsa))
2029 {
2030 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002031 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002032 > ospf6_packet_max(on->ospf6_if))
2033 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002034 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002035 break;
2036 }
hasso508e53e2004-05-18 18:57:06 +00002037
hasso508e53e2004-05-18 18:57:06 +00002038 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2039 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2040 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002041 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002042
2043 assert (lsa->lock == 2);
2044 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2045 }
2046
Dinesh Duttc5926a92013-08-24 07:55:00 +00002047 if (lsa_cnt)
2048 {
2049 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2050 oh->length = htons (p - sendbuf);
2051 lsupdate->lsa_number = htonl (lsa_cnt);
2052
2053 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2054 (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
2055 (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
2056 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2057 on->ospf6_if, oh);
2058 else
2059 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2060 on->ospf6_if, oh);
2061 }
2062
2063 /* The addresses used for retransmissions are different from those sent the
2064 first time and so we need to separate them here.
2065 */
2066 memset (sendbuf, 0, iobuflen);
2067 oh = (struct ospf6_header *) sendbuf;
2068 lsupdate = (struct ospf6_lsupdate *)
2069 ((caddr_t) oh + sizeof (struct ospf6_header));
2070 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
2071 lsa_cnt = 0;
2072
hasso508e53e2004-05-18 18:57:06 +00002073 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2074 lsa = ospf6_lsdb_next (lsa))
2075 {
2076 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002077 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002078 > ospf6_packet_max(on->ospf6_if))
2079 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002080 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002081 break;
2082 }
hasso508e53e2004-05-18 18:57:06 +00002083
hasso508e53e2004-05-18 18:57:06 +00002084 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2085 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2086 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002087 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002088 }
2089
Dinesh Duttc5926a92013-08-24 07:55:00 +00002090 if (lsa_cnt)
hasso508e53e2004-05-18 18:57:06 +00002091 {
Dinesh Duttc5926a92013-08-24 07:55:00 +00002092 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2093 oh->length = htons (p - sendbuf);
2094 lsupdate->lsa_number = htonl (lsa_cnt);
2095
2096 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2097 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2098 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002099 else
Dinesh Duttc5926a92013-08-24 07:55:00 +00002100 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2101 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002102 }
2103
Dinesh Duttc5926a92013-08-24 07:55:00 +00002104 if (on->lsupdate_list->count != 0)
2105 on->thread_send_lsupdate =
2106 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2107 else if (on->retrans_list->count != 0)
2108 on->thread_send_lsupdate =
2109 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2110 on->ospf6_if->rxmt_interval);
hasso508e53e2004-05-18 18:57:06 +00002111 return 0;
2112}
2113
2114int
2115ospf6_lsupdate_send_interface (struct thread *thread)
2116{
2117 struct ospf6_interface *oi;
2118 struct ospf6_header *oh;
2119 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002120 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002121 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00002122 struct ospf6_lsa *lsa;
2123
2124 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2125 oi->thread_send_lsupdate = (struct thread *) NULL;
2126
2127 if (oi->state <= OSPF6_INTERFACE_WAITING)
2128 {
2129 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002130 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2131 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002132 return 0;
2133 }
2134
2135 /* if we have nothing to send, return */
2136 if (oi->lsupdate_list->count == 0)
2137 return 0;
2138
hasso3b4cd3a2004-05-18 19:28:32 +00002139 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002140 oh = (struct ospf6_header *) sendbuf;
2141 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
Dinesh Duttc5926a92013-08-24 07:55:00 +00002142 sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002143
Paul Jakma6ac29a52008-08-15 13:45:30 +01002144 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002145 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002146
2147 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2148 lsa = ospf6_lsdb_next (lsa))
2149 {
2150 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002151 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002152 > ospf6_packet_max(oi))
2153 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002154 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002155 break;
2156 }
hasso508e53e2004-05-18 18:57:06 +00002157
hasso508e53e2004-05-18 18:57:06 +00002158 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2159 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2160 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002161 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002162
2163 assert (lsa->lock == 2);
2164 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2165 }
2166
Dinesh Duttc5926a92013-08-24 07:55:00 +00002167 if (lsa_cnt)
2168 {
2169 lsupdate->lsa_number = htonl (lsa_cnt);
hasso508e53e2004-05-18 18:57:06 +00002170
Dinesh Duttc5926a92013-08-24 07:55:00 +00002171 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2172 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002173
Dinesh Duttc5926a92013-08-24 07:55:00 +00002174 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2175 (oi->state == OSPF6_INTERFACE_DR) ||
2176 (oi->state == OSPF6_INTERFACE_BDR))
2177 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2178 else
2179 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2180
2181 }
hasso508e53e2004-05-18 18:57:06 +00002182
2183 if (oi->lsupdate_list->count > 0)
2184 {
2185 oi->thread_send_lsupdate =
2186 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2187 }
2188
2189 return 0;
2190}
2191
2192int
2193ospf6_lsack_send_neighbor (struct thread *thread)
2194{
2195 struct ospf6_neighbor *on;
2196 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002197 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002198 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002199 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002200
2201 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2202 on->thread_send_lsack = (struct thread *) NULL;
2203
2204 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2205 {
2206 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002207 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2208 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002209 return 0;
2210 }
2211
2212 /* if we have nothing to send, return */
2213 if (on->lsack_list->count == 0)
2214 return 0;
2215
hasso3b4cd3a2004-05-18 19:28:32 +00002216 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002217 oh = (struct ospf6_header *) sendbuf;
2218
Paul Jakma6ac29a52008-08-15 13:45:30 +01002219 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002220
2221 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2222 lsa = ospf6_lsdb_next (lsa))
2223 {
2224 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002225 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002226 {
2227 /* if we run out of packet size/space here,
2228 better to try again soon. */
2229 THREAD_OFF (on->thread_send_lsack);
2230 on->thread_send_lsack =
2231 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
hasso508e53e2004-05-18 18:57:06 +00002232
Dinesh Dutta765eb92013-08-24 07:55:14 +00002233 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002234 break;
2235 }
hasso508e53e2004-05-18 18:57:06 +00002236
2237 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2238 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2239 p += sizeof (struct ospf6_lsa_header);
2240
2241 assert (lsa->lock == 2);
2242 ospf6_lsdb_remove (lsa, on->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002243 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002244 }
2245
Dinesh Duttc5926a92013-08-24 07:55:00 +00002246 if (lsa_cnt)
2247 {
2248 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2249 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002250
Dinesh Duttc5926a92013-08-24 07:55:00 +00002251 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2252 on->ospf6_if, oh);
2253 }
2254
2255 if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
2256 {
2257 on->thread_send_lsack =
2258 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2259 }
2260
hasso508e53e2004-05-18 18:57:06 +00002261 return 0;
2262}
2263
2264int
2265ospf6_lsack_send_interface (struct thread *thread)
2266{
2267 struct ospf6_interface *oi;
2268 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002269 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002270 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002271 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002272
2273 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2274 oi->thread_send_lsack = (struct thread *) NULL;
2275
2276 if (oi->state <= OSPF6_INTERFACE_WAITING)
2277 {
2278 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002279 zlog_debug ("Quit to send LSAck to interface %s state %s",
2280 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002281 return 0;
2282 }
2283
2284 /* if we have nothing to send, return */
2285 if (oi->lsack_list->count == 0)
2286 return 0;
2287
hasso3b4cd3a2004-05-18 19:28:32 +00002288 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002289 oh = (struct ospf6_header *) sendbuf;
2290
Paul Jakma6ac29a52008-08-15 13:45:30 +01002291 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002292
2293 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2294 lsa = ospf6_lsdb_next (lsa))
2295 {
2296 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002297 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002298 {
2299 /* if we run out of packet size/space here,
2300 better to try again soon. */
2301 THREAD_OFF (oi->thread_send_lsack);
2302 oi->thread_send_lsack =
2303 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
hasso508e53e2004-05-18 18:57:06 +00002304
Dinesh Dutta765eb92013-08-24 07:55:14 +00002305 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002306 break;
2307 }
hasso508e53e2004-05-18 18:57:06 +00002308
2309 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2310 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2311 p += sizeof (struct ospf6_lsa_header);
2312
2313 assert (lsa->lock == 2);
2314 ospf6_lsdb_remove (lsa, oi->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002315 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002316 }
2317
Dinesh Duttc5926a92013-08-24 07:55:00 +00002318 if (lsa_cnt)
2319 {
2320 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2321 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002322
Dinesh Duttc5926a92013-08-24 07:55:00 +00002323 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2324 (oi->state == OSPF6_INTERFACE_DR) ||
2325 (oi->state == OSPF6_INTERFACE_BDR))
2326 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2327 else
2328 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2329 }
hasso508e53e2004-05-18 18:57:06 +00002330
2331 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2332 {
2333 oi->thread_send_lsack =
2334 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2335 }
paul718e3742002-12-13 20:15:29 +00002336
2337 return 0;
2338}
2339
David Lamparter6b0655a2014-06-04 06:53:35 +02002340
hasso508e53e2004-05-18 18:57:06 +00002341/* Commands */
2342DEFUN (debug_ospf6_message,
2343 debug_ospf6_message_cmd,
2344 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2345 DEBUG_STR
2346 OSPF6_STR
2347 "Debug OSPFv3 message\n"
2348 "Debug Unknown message\n"
2349 "Debug Hello message\n"
2350 "Debug Database Description message\n"
2351 "Debug Link State Request message\n"
2352 "Debug Link State Update message\n"
2353 "Debug Link State Acknowledgement message\n"
2354 "Debug All message\n"
2355 )
paul718e3742002-12-13 20:15:29 +00002356{
hasso508e53e2004-05-18 18:57:06 +00002357 unsigned char level = 0;
2358 int type = 0;
paul718e3742002-12-13 20:15:29 +00002359 int i;
2360
hasso508e53e2004-05-18 18:57:06 +00002361 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002362
hasso508e53e2004-05-18 18:57:06 +00002363 /* check type */
2364 if (! strncmp (argv[0], "u", 1))
2365 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2366 else if (! strncmp (argv[0], "h", 1))
2367 type = OSPF6_MESSAGE_TYPE_HELLO;
2368 else if (! strncmp (argv[0], "d", 1))
2369 type = OSPF6_MESSAGE_TYPE_DBDESC;
2370 else if (! strncmp (argv[0], "lsr", 3))
2371 type = OSPF6_MESSAGE_TYPE_LSREQ;
2372 else if (! strncmp (argv[0], "lsu", 3))
2373 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2374 else if (! strncmp (argv[0], "lsa", 3))
2375 type = OSPF6_MESSAGE_TYPE_LSACK;
2376 else if (! strncmp (argv[0], "a", 1))
2377 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002378
hasso508e53e2004-05-18 18:57:06 +00002379 if (argc == 1)
2380 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2381 else if (! strncmp (argv[1], "s", 1))
2382 level = OSPF6_DEBUG_MESSAGE_SEND;
2383 else if (! strncmp (argv[1], "r", 1))
2384 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002385
hasso508e53e2004-05-18 18:57:06 +00002386 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002387 {
hasso508e53e2004-05-18 18:57:06 +00002388 for (i = 0; i < 6; i++)
2389 OSPF6_DEBUG_MESSAGE_ON (i, level);
2390 }
2391 else
2392 OSPF6_DEBUG_MESSAGE_ON (type, level);
2393
2394 return CMD_SUCCESS;
2395}
2396
2397ALIAS (debug_ospf6_message,
2398 debug_ospf6_message_sendrecv_cmd,
2399 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
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 "Debug only sending message\n"
2411 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002412 )
hasso508e53e2004-05-18 18:57:06 +00002413
David Lamparter6b0655a2014-06-04 06:53:35 +02002414
hasso508e53e2004-05-18 18:57:06 +00002415DEFUN (no_debug_ospf6_message,
2416 no_debug_ospf6_message_cmd,
2417 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2418 NO_STR
2419 DEBUG_STR
2420 OSPF6_STR
2421 "Debug OSPFv3 message\n"
2422 "Debug Unknown message\n"
2423 "Debug Hello message\n"
2424 "Debug Database Description message\n"
2425 "Debug Link State Request message\n"
2426 "Debug Link State Update message\n"
2427 "Debug Link State Acknowledgement message\n"
2428 "Debug All message\n"
2429 )
2430{
2431 unsigned char level = 0;
2432 int type = 0;
2433 int i;
2434
2435 assert (argc > 0);
2436
2437 /* check type */
2438 if (! strncmp (argv[0], "u", 1))
2439 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2440 else if (! strncmp (argv[0], "h", 1))
2441 type = OSPF6_MESSAGE_TYPE_HELLO;
2442 else if (! strncmp (argv[0], "d", 1))
2443 type = OSPF6_MESSAGE_TYPE_DBDESC;
2444 else if (! strncmp (argv[0], "lsr", 3))
2445 type = OSPF6_MESSAGE_TYPE_LSREQ;
2446 else if (! strncmp (argv[0], "lsu", 3))
2447 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2448 else if (! strncmp (argv[0], "lsa", 3))
2449 type = OSPF6_MESSAGE_TYPE_LSACK;
2450 else if (! strncmp (argv[0], "a", 1))
2451 type = OSPF6_MESSAGE_TYPE_ALL;
2452
2453 if (argc == 1)
2454 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2455 else if (! strncmp (argv[1], "s", 1))
2456 level = OSPF6_DEBUG_MESSAGE_SEND;
2457 else if (! strncmp (argv[1], "r", 1))
2458 level = OSPF6_DEBUG_MESSAGE_RECV;
2459
2460 if (type == OSPF6_MESSAGE_TYPE_ALL)
2461 {
2462 for (i = 0; i < 6; i++)
2463 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2464 }
2465 else
2466 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2467
2468 return CMD_SUCCESS;
2469}
2470
2471ALIAS (no_debug_ospf6_message,
2472 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002473 "no debug ospf6 message "
2474 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002475 NO_STR
2476 DEBUG_STR
2477 OSPF6_STR
2478 "Debug OSPFv3 message\n"
2479 "Debug Unknown message\n"
2480 "Debug Hello message\n"
2481 "Debug Database Description message\n"
2482 "Debug Link State Request message\n"
2483 "Debug Link State Update message\n"
2484 "Debug Link State Acknowledgement message\n"
2485 "Debug All message\n"
2486 "Debug only sending message\n"
2487 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002488 )
hasso508e53e2004-05-18 18:57:06 +00002489
2490int
2491config_write_ospf6_debug_message (struct vty *vty)
2492{
paul0c083ee2004-10-10 12:54:58 +00002493 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002494 "lsreq", "lsupdate", "lsack"};
2495 unsigned char s = 0, r = 0;
2496 int i;
2497
2498 for (i = 0; i < 6; i++)
2499 {
2500 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2501 s |= 1 << i;
2502 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2503 r |= 1 << i;
2504 }
2505
2506 if (s == 0x3f && r == 0x3f)
2507 {
hasso049207c2004-08-04 20:02:13 +00002508 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002509 return 0;
2510 }
2511
hasso508e53e2004-05-18 18:57:06 +00002512 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002513 {
hasso049207c2004-08-04 20:02:13 +00002514 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002515 return 0;
2516 }
2517 else if (s == 0 && r == 0x3f)
2518 {
hasso049207c2004-08-04 20:02:13 +00002519 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002520 return 0;
paul718e3742002-12-13 20:15:29 +00002521 }
2522
hasso508e53e2004-05-18 18:57:06 +00002523 /* Unknown message is logged by default */
2524 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2525 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002526 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002527 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002528 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002529 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002530 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002531
hasso508e53e2004-05-18 18:57:06 +00002532 for (i = 1; i < 6; i++)
2533 {
2534 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2535 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002536 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002537 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2538 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002539 VNL);
hasso508e53e2004-05-18 18:57:06 +00002540 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2541 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002542 VNL);
hasso508e53e2004-05-18 18:57:06 +00002543 }
paul718e3742002-12-13 20:15:29 +00002544
2545 return 0;
2546}
2547
paul718e3742002-12-13 20:15:29 +00002548void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002549install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002550{
hasso508e53e2004-05-18 18:57:06 +00002551 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2552 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2553 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2554 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2555 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2556 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2557 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2558 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002559}
2560
paul718e3742002-12-13 20:15:29 +00002561