blob: 42521a2d9afc46e6447e719ffcfefbe9c06b1d9d [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};
paul0c083ee2004-10-10 12:54:58 +000053const char *ospf6_message_type_str[] =
hasso508e53e2004-05-18 18:57:06 +000054 { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
55
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040056/* Minimum (besides the standard OSPF packet header) lengths for OSPF
57 packets of particular types, offset is the "type" field. */
58const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
59{
60 0,
61 OSPF6_HELLO_MIN_SIZE,
62 OSPF6_DB_DESC_MIN_SIZE,
63 OSPF6_LS_REQ_MIN_SIZE,
64 OSPF6_LS_UPD_MIN_SIZE,
65 OSPF6_LS_ACK_MIN_SIZE
66};
67
68/* Minimum (besides the standard LSA header) lengths for LSAs of particular
69 types, offset is the "LSA function code" portion of "LSA type" field. */
70const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
71{
72 0,
73 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
74 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
75 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
76 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
77 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
78 /* 0x2006 */ 0,
79 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
80 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
81 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
82};
83
hasso508e53e2004-05-18 18:57:06 +000084/* print functions */
85
86static void
87ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000088{
hasso508e53e2004-05-18 18:57:06 +000089 char router_id[16], area_id[16];
90 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
91 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000092
hassoc6487d62004-12-24 06:00:11 +000093 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +000094 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +000095 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +000096 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +000097}
paul718e3742002-12-13 20:15:29 +000098
99void
hasso508e53e2004-05-18 18:57:06 +0000100ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000101{
paul718e3742002-12-13 20:15:29 +0000102 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000103 char options[16];
104 char drouter[16], bdrouter[16], neighbor[16];
105 char *p;
paul718e3742002-12-13 20:15:29 +0000106
hasso508e53e2004-05-18 18:57:06 +0000107 ospf6_header_print (oh);
108 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000109
hasso508e53e2004-05-18 18:57:06 +0000110 hello = (struct ospf6_hello *)
111 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000112
hasso508e53e2004-05-18 18:57:06 +0000113 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
114 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
115 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000116
hassoc6487d62004-12-24 06:00:11 +0000117 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000118 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000119 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000120 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000121 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000122
hasso508e53e2004-05-18 18:57:06 +0000123 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
124 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
125 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000126 {
hasso508e53e2004-05-18 18:57:06 +0000127 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000128 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000129 }
hasso508e53e2004-05-18 18:57:06 +0000130
131 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000132 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000133}
134
hasso508e53e2004-05-18 18:57:06 +0000135void
136ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000137{
paul718e3742002-12-13 20:15:29 +0000138 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000139 char options[16];
140 char *p;
paul718e3742002-12-13 20:15:29 +0000141
hasso508e53e2004-05-18 18:57:06 +0000142 ospf6_header_print (oh);
143 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000144
hasso508e53e2004-05-18 18:57:06 +0000145 dbdesc = (struct ospf6_dbdesc *)
146 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000147
hasso508e53e2004-05-18 18:57:06 +0000148 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000149
hassoc6487d62004-12-24 06:00:11 +0000150 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000151 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000152 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000153 dbdesc->reserved2,
154 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
155 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
156 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
157 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000158
hasso508e53e2004-05-18 18:57:06 +0000159 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
160 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
161 p += sizeof (struct ospf6_lsa_header))
162 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
163
164 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000165 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000166}
167
hasso508e53e2004-05-18 18:57:06 +0000168void
169ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000170{
hasso508e53e2004-05-18 18:57:06 +0000171 char id[16], adv_router[16];
172 char *p;
paul718e3742002-12-13 20:15:29 +0000173
hasso508e53e2004-05-18 18:57:06 +0000174 ospf6_header_print (oh);
175 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000176
hasso508e53e2004-05-18 18:57:06 +0000177 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
178 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
179 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000180 {
hasso508e53e2004-05-18 18:57:06 +0000181 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
182 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
183 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000184 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000185 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000186 }
hasso508e53e2004-05-18 18:57:06 +0000187
188 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000189 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000190}
191
hasso508e53e2004-05-18 18:57:06 +0000192void
193ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000194{
paul718e3742002-12-13 20:15:29 +0000195 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000196 u_long num;
197 char *p;
paul718e3742002-12-13 20:15:29 +0000198
hasso508e53e2004-05-18 18:57:06 +0000199 ospf6_header_print (oh);
200 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000201
hasso508e53e2004-05-18 18:57:06 +0000202 lsupdate = (struct ospf6_lsupdate *)
203 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000204
hasso508e53e2004-05-18 18:57:06 +0000205 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000206 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000207
hasso508e53e2004-05-18 18:57:06 +0000208 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
209 p < OSPF6_MESSAGE_END (oh) &&
210 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
211 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000212 {
hasso508e53e2004-05-18 18:57:06 +0000213 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
214 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
215 {
hassoc6487d62004-12-24 06:00:11 +0000216 zlog_debug (" Malformed LSA length, quit printing");
hasso508e53e2004-05-18 18:57:06 +0000217 break;
218 }
219 }
paul718e3742002-12-13 20:15:29 +0000220
hasso508e53e2004-05-18 18:57:06 +0000221 if (p != OSPF6_MESSAGE_END (oh))
222 {
223 char buf[32];
224
225 int num = 0;
226 memset (buf, 0, sizeof (buf));
227
hassoc6487d62004-12-24 06:00:11 +0000228 zlog_debug (" Trailing garbage exists");
hasso508e53e2004-05-18 18:57:06 +0000229 while (p < OSPF6_MESSAGE_END (oh))
230 {
231 snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
232 num++;
233 if (num == 8)
234 {
hassoc6487d62004-12-24 06:00:11 +0000235 zlog_debug (" %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000236 memset (buf, 0, sizeof (buf));
237 num = 0;
238 }
239 }
240 if (num)
hassoc6487d62004-12-24 06:00:11 +0000241 zlog_debug (" %s", buf);
paul718e3742002-12-13 20:15:29 +0000242 }
243}
244
hasso508e53e2004-05-18 18:57:06 +0000245void
246ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000247{
hasso508e53e2004-05-18 18:57:06 +0000248 char *p;
paul718e3742002-12-13 20:15:29 +0000249
hasso508e53e2004-05-18 18:57:06 +0000250 ospf6_header_print (oh);
251 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000252
hasso508e53e2004-05-18 18:57:06 +0000253 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
254 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
255 p += sizeof (struct ospf6_lsa_header))
256 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
257
258 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000259 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000260}
261
Paul Jakma6ac29a52008-08-15 13:45:30 +0100262static void
hasso508e53e2004-05-18 18:57:06 +0000263ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
264 struct ospf6_interface *oi, struct ospf6_header *oh)
265{
266 struct ospf6_hello *hello;
267 struct ospf6_neighbor *on;
268 char *p;
269 int twoway = 0;
270 int neighborchange = 0;
271 int backupseen = 0;
272
hasso508e53e2004-05-18 18:57:06 +0000273 hello = (struct ospf6_hello *)
274 ((caddr_t) oh + sizeof (struct ospf6_header));
275
paul718e3742002-12-13 20:15:29 +0000276 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000277 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000278 {
hasso508e53e2004-05-18 18:57:06 +0000279 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000280 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000281 return;
282 }
283
284 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000285 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000286 {
hasso508e53e2004-05-18 18:57:06 +0000287 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000288 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000289 return;
290 }
291
hasso508e53e2004-05-18 18:57:06 +0000292 /* E-bit check */
293 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
294 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000295 {
hasso508e53e2004-05-18 18:57:06 +0000296 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000297 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000298 return;
299 }
300
hasso508e53e2004-05-18 18:57:06 +0000301 /* Find neighbor, create if not exist */
302 on = ospf6_neighbor_lookup (oh->router_id, oi);
303 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000304 {
hasso508e53e2004-05-18 18:57:06 +0000305 on = ospf6_neighbor_create (oh->router_id, oi);
306 on->prev_drouter = on->drouter = hello->drouter;
307 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
308 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000309 }
310
hasso7b6ae022005-06-24 08:17:51 +0000311 /* always override neighbor's source address and ifindex */
312 on->ifindex = ntohl (hello->interface_id);
313 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
314
paul718e3742002-12-13 20:15:29 +0000315 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000316 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
317 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
318 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000319 {
hasso508e53e2004-05-18 18:57:06 +0000320 u_int32_t *router_id = (u_int32_t *) p;
321
322 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000323 twoway++;
paul718e3742002-12-13 20:15:29 +0000324 }
325
hasso508e53e2004-05-18 18:57:06 +0000326 if (p != OSPF6_MESSAGE_END (oh))
327 {
328 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000329 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000330 }
331
332 /* RouterPriority check */
333 if (on->priority != hello->priority)
334 {
335 on->priority = hello->priority;
336 neighborchange++;
337 }
338
339 /* DR check */
340 if (on->drouter != hello->drouter)
341 {
342 on->prev_drouter = on->drouter;
343 on->drouter = hello->drouter;
344 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
345 neighborchange++;
346 }
347
348 /* BDR check */
349 if (on->bdrouter != hello->bdrouter)
350 {
351 on->prev_bdrouter = on->bdrouter;
352 on->bdrouter = hello->bdrouter;
353 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
354 neighborchange++;
355 }
paul718e3742002-12-13 20:15:29 +0000356
357 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000358 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000359 {
hasso508e53e2004-05-18 18:57:06 +0000360 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000361 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000362 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000363 backupseen++;
364 }
365
hasso508e53e2004-05-18 18:57:06 +0000366 /* Execute neighbor events */
367 thread_execute (master, hello_received, on, 0);
368 if (twoway)
369 thread_execute (master, twoway_received, on, 0);
370 else
371 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000372
hasso508e53e2004-05-18 18:57:06 +0000373 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000374 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000375 thread_add_event (master, backup_seen, oi, 0);
376 if (neighborchange)
377 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000378}
379
hasso508e53e2004-05-18 18:57:06 +0000380static void
381ospf6_dbdesc_recv_master (struct ospf6_header *oh,
382 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000383{
paul718e3742002-12-13 20:15:29 +0000384 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000385 char *p;
paul718e3742002-12-13 20:15:29 +0000386
hasso508e53e2004-05-18 18:57:06 +0000387 dbdesc = (struct ospf6_dbdesc *)
388 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000389
hasso508e53e2004-05-18 18:57:06 +0000390 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000391 {
hasso508e53e2004-05-18 18:57:06 +0000392 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000393 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000394 return;
395 }
396
hasso508e53e2004-05-18 18:57:06 +0000397 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000398 {
hasso508e53e2004-05-18 18:57:06 +0000399 case OSPF6_NEIGHBOR_TWOWAY:
400 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000401 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000402 return;
403
404 case OSPF6_NEIGHBOR_INIT:
405 thread_execute (master, twoway_received, on, 0);
406 if (on->state != OSPF6_NEIGHBOR_EXSTART)
407 {
408 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000409 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000410 return;
411 }
412 /* else fall through to ExStart */
413
414 case OSPF6_NEIGHBOR_EXSTART:
415 /* if neighbor obeys us as our slave, schedule negotiation_done
416 and process LSA Headers. Otherwise, ignore this message */
417 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
418 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
419 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
420 {
421 /* execute NegotiationDone */
422 thread_execute (master, negotiation_done, on, 0);
423
424 /* Record neighbor options */
425 memcpy (on->options, dbdesc->options, sizeof (on->options));
426 }
427 else
428 {
429 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000430 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000431 return;
432 }
433 /* fall through to exchange */
434
435 case OSPF6_NEIGHBOR_EXCHANGE:
436 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
437 {
438 /* Duplicated DatabaseDescription is dropped by master */
439 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000440 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000441 return;
442 }
443
444 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
445 {
446 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000447 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000448 thread_add_event (master, seqnumber_mismatch, on, 0);
449 return;
450 }
451
452 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
453 {
454 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000455 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000456 thread_add_event (master, seqnumber_mismatch, on, 0);
457 return;
458 }
459
460 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
461 {
462 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000463 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000464 thread_add_event (master, seqnumber_mismatch, on, 0);
465 return;
466 }
467
468 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
469 {
470 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000471 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000472 (u_long) on->dbdesc_seqnum);
473 thread_add_event (master, seqnumber_mismatch, on, 0);
474 return;
475 }
476 break;
477
478 case OSPF6_NEIGHBOR_LOADING:
479 case OSPF6_NEIGHBOR_FULL:
480 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
481 {
482 /* Duplicated DatabaseDescription is dropped by master */
483 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000484 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000485 return;
486 }
487
488 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000489 zlog_debug ("Not duplicate dbdesc in state %s",
490 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000491 thread_add_event (master, seqnumber_mismatch, on, 0);
492 return;
493
494 default:
495 assert (0);
496 break;
497 }
498
499 /* Process LSA headers */
500 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
501 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
502 p += sizeof (struct ospf6_lsa_header))
503 {
504 struct ospf6_lsa *his, *mine;
505 struct ospf6_lsdb *lsdb = NULL;
506
507 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000508
509 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000510 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000511
512 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000513 {
hasso6452df02004-08-15 05:52:07 +0000514 case OSPF6_SCOPE_LINKLOCAL:
515 lsdb = on->ospf6_if->lsdb;
516 break;
517 case OSPF6_SCOPE_AREA:
518 lsdb = on->ospf6_if->area->lsdb;
519 break;
520 case OSPF6_SCOPE_AS:
521 lsdb = on->ospf6_if->area->ospf6->lsdb;
522 break;
523 case OSPF6_SCOPE_RESERVED:
524 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000525 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000526 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000527 continue;
528 break;
hasso508e53e2004-05-18 18:57:06 +0000529 }
530
531 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000532 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000533 {
534 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000535 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000536 ospf6_lsa_delete (his);
537 thread_add_event (master, seqnumber_mismatch, on, 0);
538 return;
539 }
540
541 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
542 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000543 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000544 {
hasso6452df02004-08-15 05:52:07 +0000545 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000546 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000547 ospf6_lsdb_add (his, on->request_list);
548 }
549 else if (ospf6_lsa_compare (his, mine) < 0)
550 {
551 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000552 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000553 ospf6_lsdb_add (his, on->request_list);
554 }
555 else
hasso6452df02004-08-15 05:52:07 +0000556 {
557 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000558 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000559 ospf6_lsa_delete (his);
560 }
hasso508e53e2004-05-18 18:57:06 +0000561 }
562
563 if (p != OSPF6_MESSAGE_END (oh))
564 {
565 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000566 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000567 }
568
569 /* Increment sequence number */
570 on->dbdesc_seqnum ++;
571
572 /* schedule send lsreq */
573 if (on->thread_send_lsreq == NULL)
574 on->thread_send_lsreq =
575 thread_add_event (master, ospf6_lsreq_send, on, 0);
576
577 THREAD_OFF (on->thread_send_dbdesc);
578
579 /* More bit check */
580 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
581 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
582 thread_add_event (master, exchange_done, on, 0);
583 else
584 on->thread_send_dbdesc =
585 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
586
587 /* save last received dbdesc */
588 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
589}
590
591static void
592ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
593 struct ospf6_neighbor *on)
594{
595 struct ospf6_dbdesc *dbdesc;
596 char *p;
597
598 dbdesc = (struct ospf6_dbdesc *)
599 ((caddr_t) oh + sizeof (struct ospf6_header));
600
601 if (on->state < OSPF6_NEIGHBOR_INIT)
602 {
603 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000604 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000605 return;
606 }
607
hasso508e53e2004-05-18 18:57:06 +0000608 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000609 {
hasso508e53e2004-05-18 18:57:06 +0000610 case OSPF6_NEIGHBOR_TWOWAY:
611 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000612 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000613 return;
614
615 case OSPF6_NEIGHBOR_INIT:
616 thread_execute (master, twoway_received, on, 0);
617 if (on->state != OSPF6_NEIGHBOR_EXSTART)
618 {
619 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000620 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000621 return;
622 }
623 /* else fall through to ExStart */
624
625 case OSPF6_NEIGHBOR_EXSTART:
626 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
627 and process LSA Headers. Otherwise, ignore this message */
628 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
629 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
630 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
631 ntohs (oh->length) == sizeof (struct ospf6_header) +
632 sizeof (struct ospf6_dbdesc))
633 {
634 /* set the master/slave bit to slave */
635 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
636
637 /* set the DD sequence number to one specified by master */
638 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
639
640 /* schedule NegotiationDone */
641 thread_execute (master, negotiation_done, on, 0);
642
643 /* Record neighbor options */
644 memcpy (on->options, dbdesc->options, sizeof (on->options));
645 }
646 else
647 {
648 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000649 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000650 return;
651 }
652 break;
653
654 case OSPF6_NEIGHBOR_EXCHANGE:
655 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
656 {
657 /* Duplicated DatabaseDescription causes slave to retransmit */
658 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000659 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000660 THREAD_OFF (on->thread_send_dbdesc);
661 on->thread_send_dbdesc =
662 thread_add_event (master, ospf6_dbdesc_send, on, 0);
663 return;
664 }
665
666 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
667 {
668 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000669 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000670 thread_add_event (master, seqnumber_mismatch, on, 0);
671 return;
672 }
673
674 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
675 {
676 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000677 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000678 thread_add_event (master, seqnumber_mismatch, on, 0);
679 return;
680 }
681
682 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
683 {
684 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000685 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000686 thread_add_event (master, seqnumber_mismatch, on, 0);
687 return;
688 }
689
690 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
691 {
692 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000693 zlog_debug ("Sequence number mismatch (%#lx expected)",
694 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000695 thread_add_event (master, seqnumber_mismatch, on, 0);
696 return;
697 }
698 break;
699
700 case OSPF6_NEIGHBOR_LOADING:
701 case OSPF6_NEIGHBOR_FULL:
702 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
703 {
704 /* Duplicated DatabaseDescription causes slave to retransmit */
705 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000706 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000707 THREAD_OFF (on->thread_send_dbdesc);
708 on->thread_send_dbdesc =
709 thread_add_event (master, ospf6_dbdesc_send, on, 0);
710 return;
711 }
712
713 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000714 zlog_debug ("Not duplicate dbdesc in state %s",
715 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000716 thread_add_event (master, seqnumber_mismatch, on, 0);
717 return;
718
719 default:
720 assert (0);
721 break;
paul718e3742002-12-13 20:15:29 +0000722 }
723
hasso508e53e2004-05-18 18:57:06 +0000724 /* Process LSA headers */
725 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
726 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
727 p += sizeof (struct ospf6_lsa_header))
728 {
729 struct ospf6_lsa *his, *mine;
730 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000731
hasso508e53e2004-05-18 18:57:06 +0000732 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000733
734 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000735 {
hasso6452df02004-08-15 05:52:07 +0000736 case OSPF6_SCOPE_LINKLOCAL:
737 lsdb = on->ospf6_if->lsdb;
738 break;
739 case OSPF6_SCOPE_AREA:
740 lsdb = on->ospf6_if->area->lsdb;
741 break;
742 case OSPF6_SCOPE_AS:
743 lsdb = on->ospf6_if->area->ospf6->lsdb;
744 break;
745 case OSPF6_SCOPE_RESERVED:
746 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000747 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000748 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000749 continue;
750 break;
hasso508e53e2004-05-18 18:57:06 +0000751 }
752
hasso6452df02004-08-15 05:52:07 +0000753 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
754 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000755 {
756 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000757 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000758 ospf6_lsa_delete (his);
759 thread_add_event (master, seqnumber_mismatch, on, 0);
760 return;
761 }
762
763 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
764 his->header->adv_router, lsdb);
765 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
766 {
hasso6452df02004-08-15 05:52:07 +0000767 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000768 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000769 ospf6_lsdb_add (his, on->request_list);
770 }
771 else
772 ospf6_lsa_delete (his);
773 }
774
775 if (p != OSPF6_MESSAGE_END (oh))
776 {
777 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000778 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000779 }
780
781 /* Set sequence number to Master's */
782 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
783
784 /* schedule send lsreq */
785 if (on->thread_send_lsreq == NULL)
786 on->thread_send_lsreq =
787 thread_add_event (master, ospf6_lsreq_send, on, 0);
788
789 THREAD_OFF (on->thread_send_dbdesc);
790 on->thread_send_dbdesc =
791 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
792
793 /* save last received dbdesc */
794 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000795}
796
Paul Jakma6ac29a52008-08-15 13:45:30 +0100797static void
hasso508e53e2004-05-18 18:57:06 +0000798ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
799 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000800{
hasso508e53e2004-05-18 18:57:06 +0000801 struct ospf6_neighbor *on;
802 struct ospf6_dbdesc *dbdesc;
803
hasso508e53e2004-05-18 18:57:06 +0000804 on = ospf6_neighbor_lookup (oh->router_id, oi);
805 if (on == NULL)
806 {
807 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000808 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000809 return;
810 }
811
hasso508e53e2004-05-18 18:57:06 +0000812 dbdesc = (struct ospf6_dbdesc *)
813 ((caddr_t) oh + sizeof (struct ospf6_header));
814
815 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400816 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000817 {
818 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000819 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000820 return;
821 }
822
823 if (dbdesc->reserved1 || dbdesc->reserved2)
824 {
825 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000826 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
827 on->name);
hasso508e53e2004-05-18 18:57:06 +0000828 dbdesc->reserved1 = 0;
829 dbdesc->reserved2 = 0;
830 }
831
832 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
833 ospf6_dbdesc_recv_master (oh, on);
834 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
835 ospf6_dbdesc_recv_slave (oh, on);
836 else
837 {
838 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000839 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000840 }
841}
842
Paul Jakma6ac29a52008-08-15 13:45:30 +0100843static void
hasso508e53e2004-05-18 18:57:06 +0000844ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
845 struct ospf6_interface *oi, struct ospf6_header *oh)
846{
847 struct ospf6_neighbor *on;
848 char *p;
849 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000850 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000851 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000852
hasso508e53e2004-05-18 18:57:06 +0000853 on = ospf6_neighbor_lookup (oh->router_id, oi);
854 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000855 {
hasso508e53e2004-05-18 18:57:06 +0000856 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000857 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000858 return;
859 }
860
hasso508e53e2004-05-18 18:57:06 +0000861 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
862 on->state != OSPF6_NEIGHBOR_LOADING &&
863 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000864 {
hasso508e53e2004-05-18 18:57:06 +0000865 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000866 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000867 return;
868 }
869
hasso508e53e2004-05-18 18:57:06 +0000870 /* Process each request */
871 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
872 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
873 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000874 {
hasso508e53e2004-05-18 18:57:06 +0000875 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000876
877 switch (OSPF6_LSA_SCOPE (e->type))
878 {
879 case OSPF6_SCOPE_LINKLOCAL:
880 lsdb = on->ospf6_if->lsdb;
881 break;
882 case OSPF6_SCOPE_AREA:
883 lsdb = on->ospf6_if->area->lsdb;
884 break;
885 case OSPF6_SCOPE_AS:
886 lsdb = on->ospf6_if->area->ospf6->lsdb;
887 break;
888 default:
889 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000890 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000891 continue;
892 break;
893 }
paul718e3742002-12-13 20:15:29 +0000894
hasso508e53e2004-05-18 18:57:06 +0000895 /* Find database copy */
896 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
897 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000898 {
hasso508e53e2004-05-18 18:57:06 +0000899 char id[16], adv_router[16];
900 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
901 {
902 inet_ntop (AF_INET, &e->id, id, sizeof (id));
903 inet_ntop (AF_INET, &e->adv_router, adv_router,
904 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000905 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
906 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000907 }
908 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000909 return;
910 }
911
hasso508e53e2004-05-18 18:57:06 +0000912 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000913 }
914
hasso508e53e2004-05-18 18:57:06 +0000915 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000916 {
hasso508e53e2004-05-18 18:57:06 +0000917 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000918 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000919 }
920
hasso508e53e2004-05-18 18:57:06 +0000921 /* schedule send lsupdate */
922 THREAD_OFF (on->thread_send_lsupdate);
923 on->thread_send_lsupdate =
924 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000925}
926
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400927/* Verify, that the specified memory area contains exactly N valid IPv6
928 prefixes as specified by RFC5340, A.4.1. */
929static unsigned
930ospf6_prefixes_examin
931(
932 struct ospf6_prefix *current, /* start of buffer */
933 unsigned length,
934 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
935)
936{
937 u_char requested_pfx_bytes;
938 u_int32_t real_num_pfxs = 0;
939
940 while (length)
941 {
942 if (length < OSPF6_PREFIX_MIN_SIZE)
943 {
944 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
945 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
946 return MSG_NG;
947 }
948 /* safe to look deeper */
949 if (current->prefix_length > IPV6_MAX_BITLEN)
950 {
951 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
952 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
953 return MSG_NG;
954 }
955 /* covers both fixed- and variable-sized fields */
956 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
957 if (requested_pfx_bytes > length)
958 {
959 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
960 zlog_debug ("%s: undersized IPv6 prefix", __func__);
961 return MSG_NG;
962 }
963 /* next prefix */
964 length -= requested_pfx_bytes;
965 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
966 real_num_pfxs++;
967 }
968 if (real_num_pfxs != req_num_pfxs)
969 {
970 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
971 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
972 __func__, req_num_pfxs, real_num_pfxs);
973 return MSG_NG;
974 }
975 return MSG_OK;
976}
977
978/* Verify an LSA to have a valid length and dispatch further (where
979 appropriate) to check if the contents, including nested IPv6 prefixes,
980 is properly sized/aligned within the LSA. Note that this function gets
981 LSA type in network byte order, uses in host byte order and passes to
982 ospf6_lstype_name() in network byte order again. */
983static unsigned
984ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
985{
986 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
987 struct ospf6_as_external_lsa *as_external_lsa;
988 struct ospf6_link_lsa *link_lsa;
989 unsigned exp_length;
990 u_int8_t ltindex;
991 u_int16_t lsatype;
992
993 /* In case an additional minimum length constraint is defined for current
994 LSA type, make sure that this constraint is met. */
995 lsatype = ntohs (lsah->type);
996 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
997 if
998 (
999 ltindex < OSPF6_LSTYPE_SIZE &&
1000 ospf6_lsa_minlen[ltindex] &&
1001 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
1002 )
1003 {
1004 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1005 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
1006 return MSG_NG;
1007 }
1008 switch (lsatype)
1009 {
1010 case OSPF6_LSTYPE_ROUTER:
1011 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
1012 by N>=0 interface descriptions. */
1013 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
1014 {
1015 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1016 zlog_debug ("%s: interface description alignment error", __func__);
1017 return MSG_NG;
1018 }
1019 break;
1020 case OSPF6_LSTYPE_NETWORK:
1021 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1022 followed by N>=0 attached router descriptions. */
1023 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
1024 {
1025 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1026 zlog_debug ("%s: router description alignment error", __func__);
1027 return MSG_NG;
1028 }
1029 break;
1030 case OSPF6_LSTYPE_INTER_PREFIX:
1031 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
1032 followed by 3-4 fields of a single IPv6 prefix. */
1033 if (headeronly)
1034 break;
1035 return ospf6_prefixes_examin
1036 (
1037 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1038 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1039 1
1040 );
1041 case OSPF6_LSTYPE_INTER_ROUTER:
1042 /* RFC5340 A.4.6, fixed-size LSA. */
1043 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1044 {
1045 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1046 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1047 return MSG_NG;
1048 }
1049 break;
1050 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1051 case OSPF6_LSTYPE_TYPE_7:
1052 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1053 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1054 16 bytes of forwarding address, 4 bytes of external route tag,
1055 4 bytes of referenced link state ID. */
1056 if (headeronly)
1057 break;
1058 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1059 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1060 /* To find out if the last optional field (Referenced Link State ID) is
1061 assumed in this LSA, we need to access fixed fields of the IPv6
1062 prefix before ospf6_prefix_examin() confirms its sizing. */
1063 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1064 {
1065 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1066 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1067 return MSG_NG;
1068 }
1069 /* forwarding address */
1070 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1071 exp_length += 16;
1072 /* external route tag */
1073 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1074 exp_length += 4;
1075 /* referenced link state ID */
1076 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1077 exp_length += 4;
1078 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1079 this check does not include any IPv6 prefix fields. */
1080 if (exp_length > lsalen)
1081 {
1082 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1083 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1084 return MSG_NG;
1085 }
1086 /* The last call completely covers the remainder (IPv6 prefix). */
1087 return ospf6_prefixes_examin
1088 (
1089 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1090 lsalen - exp_length,
1091 1
1092 );
1093 case OSPF6_LSTYPE_LINK:
1094 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1095 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1096 if (headeronly)
1097 break;
1098 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1099 return ospf6_prefixes_examin
1100 (
1101 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1102 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1103 ntohl (link_lsa->prefix_num) /* 32 bits */
1104 );
1105 case OSPF6_LSTYPE_INTRA_PREFIX:
1106 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1107 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1108 if (headeronly)
1109 break;
1110 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1111 return ospf6_prefixes_examin
1112 (
1113 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1114 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1115 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1116 );
1117 }
1118 /* No additional validation is possible for unknown LSA types, which are
1119 themselves valid in OPSFv3, hence the default decision is to accept. */
1120 return MSG_OK;
1121}
1122
1123/* Verify if the provided input buffer is a valid sequence of LSAs. This
1124 includes verification of LSA blocks length/alignment and dispatching
1125 of deeper-level checks. */
1126static unsigned
1127ospf6_lsaseq_examin
1128(
1129 struct ospf6_lsa_header *lsah, /* start of buffered data */
1130 size_t length,
1131 const u_char headeronly,
1132 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1133 and treat the difference as an error. */
1134 const u_int32_t declared_num_lsas
1135)
1136{
1137 u_int32_t counted_lsas = 0;
1138
1139 while (length)
1140 {
1141 u_int16_t lsalen;
1142 if (length < OSPF6_LSA_HEADER_SIZE)
1143 {
1144 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1145 zlog_debug ("%s: undersized (%u B) trailing (#%u) LSA header",
1146 __func__, length, counted_lsas);
1147 return MSG_NG;
1148 }
1149 /* save on ntohs() calls here and in the LSA validator */
1150 lsalen = OSPF6_LSA_SIZE (lsah);
1151 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1152 {
1153 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1154 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1155 __func__, counted_lsas, lsalen);
1156 return MSG_NG;
1157 }
1158 if (headeronly)
1159 {
1160 /* less checks here and in ospf6_lsa_examin() */
1161 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1162 {
1163 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1164 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1165 ospf6_lstype_name (lsah->type), counted_lsas);
1166 return MSG_NG;
1167 }
1168 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1169 length -= OSPF6_LSA_HEADER_SIZE;
1170 }
1171 else
1172 {
1173 /* make sure the input buffer is deep enough before further checks */
1174 if (lsalen > length)
1175 {
1176 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1177 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %u B",
1178 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1179 return MSG_NG;
1180 }
1181 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1182 {
1183 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1184 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1185 ospf6_lstype_name (lsah->type), counted_lsas);
1186 return MSG_NG;
1187 }
1188 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1189 length -= lsalen;
1190 }
1191 counted_lsas++;
1192 }
1193
1194 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1195 {
1196 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1197 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1198 __func__, declared_num_lsas, counted_lsas);
1199 return MSG_NG;
1200 }
1201 return MSG_OK;
1202}
1203
1204/* Verify a complete OSPF packet for proper sizing/alignment. */
1205static unsigned
1206ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1207{
1208 struct ospf6_lsupdate *lsupd;
1209 unsigned test;
1210
1211 /* length, 1st approximation */
1212 if (bytesonwire < OSPF6_HEADER_SIZE)
1213 {
1214 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1215 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1216 return MSG_NG;
1217 }
1218 /* Now it is safe to access header fields. */
1219 if (bytesonwire != ntohs (oh->length))
1220 {
1221 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1222 zlog_debug ("%s: packet length error (%u real, %u declared)",
1223 __func__, bytesonwire, ntohs (oh->length));
1224 return MSG_NG;
1225 }
1226 /* version check */
1227 if (oh->version != OSPFV3_VERSION)
1228 {
1229 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1230 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1231 return MSG_NG;
1232 }
1233 /* length, 2nd approximation */
1234 if
1235 (
1236 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1237 ospf6_packet_minlen[oh->type] &&
1238 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1239 )
1240 {
1241 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1242 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
1243 bytesonwire, ospf6_message_type_str[oh->type]);
1244 return MSG_NG;
1245 }
1246 /* type-specific deeper validation */
1247 switch (oh->type)
1248 {
1249 case OSPF6_MESSAGE_TYPE_HELLO:
1250 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1251 by N>=0 router-IDs. */
1252 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1253 return MSG_OK;
1254 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1255 zlog_debug ("%s: alignment error in %s packet",
1256 __func__, ospf6_message_type_str[oh->type]);
1257 return MSG_NG;
1258 case OSPF6_MESSAGE_TYPE_DBDESC:
1259 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1260 by N>=0 header-only LSAs. */
1261 test = ospf6_lsaseq_examin
1262 (
1263 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1264 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1265 1,
1266 0
1267 );
1268 break;
1269 case OSPF6_MESSAGE_TYPE_LSREQ:
1270 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1271 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1272 return MSG_OK;
1273 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1274 zlog_debug ("%s: alignment error in %s packet",
1275 __func__, ospf6_message_type_str[oh->type]);
1276 return MSG_NG;
1277 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1278 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1279 by N>=0 full LSAs (with N declared beforehand). */
1280 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1281 test = ospf6_lsaseq_examin
1282 (
1283 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1284 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1285 0,
1286 ntohl (lsupd->lsa_number) /* 32 bits */
1287 );
1288 break;
1289 case OSPF6_MESSAGE_TYPE_LSACK:
1290 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1291 test = ospf6_lsaseq_examin
1292 (
1293 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1294 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1295 1,
1296 0
1297 );
1298 break;
1299 default:
1300 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1301 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1302 return MSG_NG;
1303 }
1304 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1305 zlog_debug ("%s: anomaly in %s packet", __func__, ospf6_message_type_str[oh->type]);
1306 return test;
1307}
1308
1309/* Verify particular fields of otherwise correct received OSPF packet to
1310 meet the requirements of RFC. */
1311static int
1312ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1313{
1314 char buf[2][INET_ADDRSTRLEN];
1315
1316 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1317 return MSG_NG;
1318
1319 /* Area-ID check */
1320 if (oh->area_id != oi->area->area_id)
1321 {
1322 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1323 {
1324 if (oh->area_id == BACKBONE_AREA_ID)
1325 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1326 else
1327 zlog_debug
1328 (
1329 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1330 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1331 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1332 );
1333 }
1334 return MSG_NG;
1335 }
1336
1337 /* Instance-ID check */
1338 if (oh->instance_id != oi->instance_id)
1339 {
1340 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1341 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1342 return MSG_NG;
1343 }
1344
1345 /* Router-ID check */
1346 if (oh->router_id == oi->area->ospf6->router_id)
1347 {
1348 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1349 return MSG_NG;
1350 }
1351 return MSG_OK;
1352}
1353
Paul Jakma6ac29a52008-08-15 13:45:30 +01001354static void
hasso508e53e2004-05-18 18:57:06 +00001355ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1356 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001357{
hasso508e53e2004-05-18 18:57:06 +00001358 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001359 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001360 unsigned long num;
1361 char *p;
paul718e3742002-12-13 20:15:29 +00001362
hasso508e53e2004-05-18 18:57:06 +00001363 on = ospf6_neighbor_lookup (oh->router_id, oi);
1364 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001365 {
hasso508e53e2004-05-18 18:57:06 +00001366 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001367 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001368 return;
1369 }
1370
hasso508e53e2004-05-18 18:57:06 +00001371 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1372 on->state != OSPF6_NEIGHBOR_LOADING &&
1373 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001374 {
hasso508e53e2004-05-18 18:57:06 +00001375 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001376 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001377 return;
1378 }
1379
hasso508e53e2004-05-18 18:57:06 +00001380 lsupdate = (struct ospf6_lsupdate *)
1381 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001382
hasso508e53e2004-05-18 18:57:06 +00001383 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +00001384
hasso508e53e2004-05-18 18:57:06 +00001385 /* Process LSAs */
1386 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1387 p < OSPF6_MESSAGE_END (oh) &&
1388 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1389 p += OSPF6_LSA_SIZE (p))
1390 {
1391 if (num == 0)
1392 break;
1393 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
1394 {
1395 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001396 zlog_debug ("Malformed LSA length, quit processing");
hasso508e53e2004-05-18 18:57:06 +00001397 break;
1398 }
1399
hasso6452df02004-08-15 05:52:07 +00001400 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001401 num--;
1402 }
1403
1404 if (num != 0)
1405 {
1406 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001407 zlog_debug ("Malformed LSA number or LSA length");
hasso508e53e2004-05-18 18:57:06 +00001408 }
1409 if (p != OSPF6_MESSAGE_END (oh))
1410 {
1411 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001412 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001413 }
paul718e3742002-12-13 20:15:29 +00001414
1415 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1416 with the proper Link State Update packet(s), the Link state request
1417 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001418 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001419 can be recognized as a response to our previous LS Request */
1420 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1421 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1422 on->state == OSPF6_NEIGHBOR_LOADING))
1423 {
1424 THREAD_OFF (on->thread_send_lsreq);
1425 on->thread_send_lsreq =
1426 thread_add_event (master, ospf6_lsreq_send, on, 0);
1427 }
paul718e3742002-12-13 20:15:29 +00001428}
1429
Paul Jakma6ac29a52008-08-15 13:45:30 +01001430static void
hasso508e53e2004-05-18 18:57:06 +00001431ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1432 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001433{
hasso508e53e2004-05-18 18:57:06 +00001434 struct ospf6_neighbor *on;
1435 char *p;
1436 struct ospf6_lsa *his, *mine;
1437 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001438
hasso508e53e2004-05-18 18:57:06 +00001439 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001440
hasso508e53e2004-05-18 18:57:06 +00001441 on = ospf6_neighbor_lookup (oh->router_id, oi);
1442 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001443 {
hasso508e53e2004-05-18 18:57:06 +00001444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001445 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001446 return;
1447 }
1448
hasso508e53e2004-05-18 18:57:06 +00001449 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1450 on->state != OSPF6_NEIGHBOR_LOADING &&
1451 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001452 {
hasso508e53e2004-05-18 18:57:06 +00001453 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001454 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001455 return;
1456 }
1457
hasso508e53e2004-05-18 18:57:06 +00001458 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1459 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1460 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001461 {
hasso508e53e2004-05-18 18:57:06 +00001462 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001463
hasso6452df02004-08-15 05:52:07 +00001464 switch (OSPF6_LSA_SCOPE (his->header->type))
1465 {
1466 case OSPF6_SCOPE_LINKLOCAL:
1467 lsdb = on->ospf6_if->lsdb;
1468 break;
1469 case OSPF6_SCOPE_AREA:
1470 lsdb = on->ospf6_if->area->lsdb;
1471 break;
1472 case OSPF6_SCOPE_AS:
1473 lsdb = on->ospf6_if->area->ospf6->lsdb;
1474 break;
1475 case OSPF6_SCOPE_RESERVED:
1476 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001477 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001478 ospf6_lsa_delete (his);
1479 continue;
1480 break;
1481 }
1482
1483 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001484 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001485
1486 /* Find database copy */
1487 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1488 his->header->adv_router, lsdb);
1489 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001490 {
hasso508e53e2004-05-18 18:57:06 +00001491 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001492 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001493 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001494 continue;
1495 }
1496
hasso508e53e2004-05-18 18:57:06 +00001497 /* Check if the LSA is on his retrans-list */
1498 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1499 his->header->adv_router, on->retrans_list);
1500 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001501 {
hasso508e53e2004-05-18 18:57:06 +00001502 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001503 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001504 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001505 continue;
1506 }
1507
hasso508e53e2004-05-18 18:57:06 +00001508 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001509 {
hasso508e53e2004-05-18 18:57:06 +00001510 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001511 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001512 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001513 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001514 ospf6_lsa_delete (his);
1515 continue;
paul718e3742002-12-13 20:15:29 +00001516 }
1517
hasso6452df02004-08-15 05:52:07 +00001518 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001519 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1520 on->name);
hasso508e53e2004-05-18 18:57:06 +00001521
Paul Jakma932bf192006-05-15 10:42:24 +00001522 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001523 if (OSPF6_LSA_IS_MAXAGE (mine))
1524 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001525 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001526 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001527 }
1528
hasso508e53e2004-05-18 18:57:06 +00001529 if (p != OSPF6_MESSAGE_END (oh))
1530 {
1531 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001532 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001533 }
paul718e3742002-12-13 20:15:29 +00001534}
1535
Paul Jakma6ac29a52008-08-15 13:45:30 +01001536static u_char *recvbuf = NULL;
1537static u_char *sendbuf = NULL;
1538static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001539
1540int
paul0c083ee2004-10-10 12:54:58 +00001541ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001542{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001543 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001544
1545 if (size <= iobuflen)
1546 return iobuflen;
1547
1548 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1549 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1550 if (recvnew == NULL || sendnew == NULL)
1551 {
hassob596c712004-07-09 18:33:43 +00001552 if (recvnew)
1553 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1554 if (sendnew)
1555 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001556 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001557 return iobuflen;
1558 }
1559
1560 if (recvbuf)
1561 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1562 if (sendbuf)
1563 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1564 recvbuf = recvnew;
1565 sendbuf = sendnew;
1566 iobuflen = size;
1567
1568 return iobuflen;
1569}
paul718e3742002-12-13 20:15:29 +00001570
Tom Goffae2254a2010-11-10 13:01:41 -08001571void
1572ospf6_message_terminate (void)
1573{
1574 if (recvbuf)
1575 {
1576 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1577 recvbuf = NULL;
1578 }
1579
1580 if (sendbuf)
1581 {
1582 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1583 sendbuf = NULL;
1584 }
1585
1586 iobuflen = 0;
1587}
1588
paul718e3742002-12-13 20:15:29 +00001589int
1590ospf6_receive (struct thread *thread)
1591{
paul0c083ee2004-10-10 12:54:58 +00001592 int sockfd;
1593 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001594 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001595 struct in6_addr src, dst;
1596 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001597 struct iovec iovector[2];
1598 struct ospf6_interface *oi;
1599 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001600
1601 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001602 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001603 thread_add_read (master, ospf6_receive, NULL, sockfd);
1604
1605 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001606 memset (&src, 0, sizeof (src));
1607 memset (&dst, 0, sizeof (dst));
1608 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001609 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001610 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001611 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001612 iovector[1].iov_base = NULL;
1613 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001614
1615 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001616 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001617 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001618 {
hasso508e53e2004-05-18 18:57:06 +00001619 zlog_err ("Excess message read");
1620 return 0;
1621 }
paul718e3742002-12-13 20:15:29 +00001622
hasso508e53e2004-05-18 18:57:06 +00001623 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1624 if (oi == NULL || oi->area == NULL)
1625 {
hassoc6487d62004-12-24 06:00:11 +00001626 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001627 return 0;
1628 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001629 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1630 {
1631 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1632 zlog_debug ("%s: Ignore message on passive interface %s",
1633 __func__, oi->interface->name);
1634 return 0;
1635 }
hasso508e53e2004-05-18 18:57:06 +00001636
1637 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001638 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1639 return 0;
1640
1641 /* Being here means, that no sizing/alignment issues were detected in
1642 the input packet. This renders the additional checks performed below
1643 and also in the type-specific dispatching functions a dead code,
1644 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001645
1646 /* Log */
1647 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1648 {
1649 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1650 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001651 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001652 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001653 zlog_debug (" src: %s", srcname);
1654 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001655 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001656 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001657
1658 switch (oh->type)
1659 {
1660 case OSPF6_MESSAGE_TYPE_HELLO:
1661 ospf6_hello_print (oh);
1662 break;
1663 case OSPF6_MESSAGE_TYPE_DBDESC:
1664 ospf6_dbdesc_print (oh);
1665 break;
1666 case OSPF6_MESSAGE_TYPE_LSREQ:
1667 ospf6_lsreq_print (oh);
1668 break;
1669 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1670 ospf6_lsupdate_print (oh);
1671 break;
1672 case OSPF6_MESSAGE_TYPE_LSACK:
1673 ospf6_lsack_print (oh);
1674 break;
1675 default:
hassoc6487d62004-12-24 06:00:11 +00001676 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001677 break;
1678 }
1679 }
1680
hasso508e53e2004-05-18 18:57:06 +00001681 switch (oh->type)
1682 {
1683 case OSPF6_MESSAGE_TYPE_HELLO:
1684 ospf6_hello_recv (&src, &dst, oi, oh);
1685 break;
1686
1687 case OSPF6_MESSAGE_TYPE_DBDESC:
1688 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1689 break;
1690
1691 case OSPF6_MESSAGE_TYPE_LSREQ:
1692 ospf6_lsreq_recv (&src, &dst, oi, oh);
1693 break;
1694
1695 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1696 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1697 break;
1698
1699 case OSPF6_MESSAGE_TYPE_LSACK:
1700 ospf6_lsack_recv (&src, &dst, oi, oh);
1701 break;
1702
1703 default:
1704 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001705 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001706 break;
1707 }
1708
1709 return 0;
1710}
1711
Paul Jakma6ac29a52008-08-15 13:45:30 +01001712static void
hasso508e53e2004-05-18 18:57:06 +00001713ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1714 struct ospf6_interface *oi, struct ospf6_header *oh)
1715{
1716 int len;
1717 char srcname[64], dstname[64];
1718 struct iovec iovector[2];
1719
1720 /* initialize */
1721 iovector[0].iov_base = (caddr_t) oh;
1722 iovector[0].iov_len = ntohs (oh->length);
1723 iovector[1].iov_base = NULL;
1724 iovector[1].iov_len = 0;
1725
1726 /* fill OSPF header */
1727 oh->version = OSPFV3_VERSION;
1728 /* message type must be set before */
1729 /* message length must be set before */
1730 oh->router_id = oi->area->ospf6->router_id;
1731 oh->area_id = oi->area->area_id;
1732 /* checksum is calculated by kernel */
1733 oh->instance_id = oi->instance_id;
1734 oh->reserved = 0;
1735
1736 /* Log */
1737 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1738 {
1739 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1740 if (src)
1741 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1742 else
1743 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001744 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001745 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001746 zlog_debug (" src: %s", srcname);
1747 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001748
1749 switch (oh->type)
1750 {
1751 case OSPF6_MESSAGE_TYPE_HELLO:
1752 ospf6_hello_print (oh);
1753 break;
1754 case OSPF6_MESSAGE_TYPE_DBDESC:
1755 ospf6_dbdesc_print (oh);
1756 break;
1757 case OSPF6_MESSAGE_TYPE_LSREQ:
1758 ospf6_lsreq_print (oh);
1759 break;
1760 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1761 ospf6_lsupdate_print (oh);
1762 break;
1763 case OSPF6_MESSAGE_TYPE_LSACK:
1764 ospf6_lsack_print (oh);
1765 break;
1766 default:
hassoc6487d62004-12-24 06:00:11 +00001767 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001768 assert (0);
1769 break;
1770 }
1771 }
1772
1773 /* send message */
1774 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1775 if (len != ntohs (oh->length))
1776 zlog_err ("Could not send entire message");
1777}
1778
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001779static int
1780ospf6_packet_max(struct ospf6_interface *oi)
1781{
1782 return oi->ifmtu - sizeof(struct ip6_hdr);
1783}
1784
hasso508e53e2004-05-18 18:57:06 +00001785int
1786ospf6_hello_send (struct thread *thread)
1787{
1788 struct ospf6_interface *oi;
1789 struct ospf6_header *oh;
1790 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001791 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001792 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001793 struct ospf6_neighbor *on;
1794
1795 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1796 oi->thread_send_hello = (struct thread *) NULL;
1797
1798 if (oi->state <= OSPF6_INTERFACE_DOWN)
1799 {
1800 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001801 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001802 oi->interface->name);
1803 return 0;
1804 }
1805
1806 /* set next thread */
1807 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1808 oi, oi->hello_interval);
1809
hasso3b4cd3a2004-05-18 19:28:32 +00001810 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001811 oh = (struct ospf6_header *) sendbuf;
1812 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1813
1814 hello->interface_id = htonl (oi->interface->ifindex);
1815 hello->priority = oi->priority;
1816 hello->options[0] = oi->area->options[0];
1817 hello->options[1] = oi->area->options[1];
1818 hello->options[2] = oi->area->options[2];
1819 hello->hello_interval = htons (oi->hello_interval);
1820 hello->dead_interval = htons (oi->dead_interval);
1821 hello->drouter = oi->drouter;
1822 hello->bdrouter = oi->bdrouter;
1823
Paul Jakma6ac29a52008-08-15 13:45:30 +01001824 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001825
paul1eb8ef22005-04-07 07:30:20 +00001826 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001827 {
hasso508e53e2004-05-18 18:57:06 +00001828 if (on->state < OSPF6_NEIGHBOR_INIT)
1829 continue;
1830
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001831 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001832 {
1833 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001834 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001835 break;
1836 }
1837
1838 memcpy (p, &on->router_id, sizeof (u_int32_t));
1839 p += sizeof (u_int32_t);
1840 }
1841
1842 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1843 oh->length = htons (p - sendbuf);
1844
1845 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1846 return 0;
1847}
1848
1849int
1850ospf6_dbdesc_send (struct thread *thread)
1851{
1852 struct ospf6_neighbor *on;
1853 struct ospf6_header *oh;
1854 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001855 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001856 struct ospf6_lsa *lsa;
1857
1858 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1859 on->thread_send_dbdesc = (struct thread *) NULL;
1860
1861 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1862 {
1863 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001864 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1865 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001866 return 0;
1867 }
1868
1869 /* set next thread if master */
1870 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1871 on->thread_send_dbdesc =
1872 thread_add_timer (master, ospf6_dbdesc_send, on,
1873 on->ospf6_if->rxmt_interval);
1874
hasso3b4cd3a2004-05-18 19:28:32 +00001875 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001876 oh = (struct ospf6_header *) sendbuf;
1877 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1878 sizeof (struct ospf6_header));
1879
1880 /* if this is initial one, initialize sequence number for DbDesc */
1881 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1882 {
1883 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001884 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001885 tv.tv_sec = 1;
1886 on->dbdesc_seqnum = tv.tv_sec;
1887 }
1888
1889 dbdesc->options[0] = on->ospf6_if->area->options[0];
1890 dbdesc->options[1] = on->ospf6_if->area->options[1];
1891 dbdesc->options[2] = on->ospf6_if->area->options[2];
1892 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1893 dbdesc->bits = on->dbdesc_bits;
1894 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1895
1896 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001897 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001898 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1899 {
1900 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1901 lsa = ospf6_lsdb_next (lsa))
1902 {
1903 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1904
1905 /* MTU check */
1906 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001907 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001908 {
1909 ospf6_lsa_unlock (lsa);
1910 break;
1911 }
1912 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1913 p += sizeof (struct ospf6_lsa_header);
1914 }
1915 }
1916
1917 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1918 oh->length = htons (p - sendbuf);
1919
1920 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1921 on->ospf6_if, oh);
1922 return 0;
1923}
1924
1925int
1926ospf6_dbdesc_send_newone (struct thread *thread)
1927{
1928 struct ospf6_neighbor *on;
1929 struct ospf6_lsa *lsa;
1930 unsigned int size = 0;
1931
1932 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001933 ospf6_lsdb_remove_all (on->dbdesc_list);
1934
1935 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1936 so that ospf6_send_dbdesc () can send those LSAs */
1937 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1938 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1939 lsa = ospf6_lsdb_next (lsa))
1940 {
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001941 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001942 {
1943 ospf6_lsa_unlock (lsa);
1944 break;
1945 }
1946
hasso508e53e2004-05-18 18:57:06 +00001947 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1948 ospf6_lsdb_remove (lsa, on->summary_list);
1949 size += sizeof (struct ospf6_lsa_header);
1950 }
1951
1952 if (on->summary_list->count == 0)
1953 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1954
1955 /* If slave, More bit check must be done here */
1956 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1957 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1958 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1959 thread_add_event (master, exchange_done, on, 0);
1960
1961 thread_execute (master, ospf6_dbdesc_send, on, 0);
1962 return 0;
1963}
1964
1965int
1966ospf6_lsreq_send (struct thread *thread)
1967{
1968 struct ospf6_neighbor *on;
1969 struct ospf6_header *oh;
1970 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001971 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001972 struct ospf6_lsa *lsa;
1973
1974 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1975 on->thread_send_lsreq = (struct thread *) NULL;
1976
1977 /* LSReq will be sent only in ExStart or Loading */
1978 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1979 on->state != OSPF6_NEIGHBOR_LOADING)
1980 {
1981 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001982 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1983 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001984 return 0;
1985 }
1986
1987 /* schedule loading_done if request list is empty */
1988 if (on->request_list->count == 0)
1989 {
1990 thread_add_event (master, loading_done, on, 0);
1991 return 0;
1992 }
1993
1994 /* set next thread */
1995 on->thread_send_lsreq =
1996 thread_add_timer (master, ospf6_lsreq_send, on,
1997 on->ospf6_if->rxmt_interval);
1998
hasso3b4cd3a2004-05-18 19:28:32 +00001999 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002000 oh = (struct ospf6_header *) sendbuf;
2001
2002 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01002003 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002004 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
2005 lsa = ospf6_lsdb_next (lsa))
2006 {
2007 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002008 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002009 {
2010 ospf6_lsa_unlock (lsa);
2011 break;
2012 }
2013
2014 e = (struct ospf6_lsreq_entry *) p;
2015 e->type = lsa->header->type;
2016 e->id = lsa->header->id;
2017 e->adv_router = lsa->header->adv_router;
2018 p += sizeof (struct ospf6_lsreq_entry);
2019 }
2020
2021 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
2022 oh->length = htons (p - sendbuf);
2023
2024 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2025 on->ospf6_if, oh);
2026 return 0;
2027}
2028
2029int
2030ospf6_lsupdate_send_neighbor (struct thread *thread)
2031{
2032 struct ospf6_neighbor *on;
2033 struct ospf6_header *oh;
2034 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002035 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002036 int num;
2037 struct ospf6_lsa *lsa;
2038
2039 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2040 on->thread_send_lsupdate = (struct thread *) NULL;
2041
hasso6452df02004-08-15 05:52:07 +00002042 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002043 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00002044
hasso508e53e2004-05-18 18:57:06 +00002045 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2046 {
2047 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002048 zlog_debug ("Quit to send (neighbor state %s)",
2049 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002050 return 0;
2051 }
2052
2053 /* if we have nothing to send, return */
2054 if (on->lsupdate_list->count == 0 &&
2055 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00002056 {
2057 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002058 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00002059 return 0;
2060 }
hasso508e53e2004-05-18 18:57:06 +00002061
hasso3b4cd3a2004-05-18 19:28:32 +00002062 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002063 oh = (struct ospf6_header *) sendbuf;
2064 lsupdate = (struct ospf6_lsupdate *)
2065 ((caddr_t) oh + sizeof (struct ospf6_header));
2066
Paul Jakma6ac29a52008-08-15 13:45:30 +01002067 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002068 num = 0;
2069
2070 /* lsupdate_list lists those LSA which doesn't need to be
2071 retransmitted. remove those from the list */
2072 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2073 lsa = ospf6_lsdb_next (lsa))
2074 {
2075 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002076 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002077 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002078 {
2079 ospf6_lsa_unlock (lsa);
2080 break;
2081 }
2082
hasso508e53e2004-05-18 18:57:06 +00002083 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2084 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2085 p += OSPF6_LSA_SIZE (lsa->header);
2086 num++;
2087
2088 assert (lsa->lock == 2);
2089 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2090 }
2091
2092 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2093 lsa = ospf6_lsdb_next (lsa))
2094 {
2095 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002096 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002097 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002098 {
2099 ospf6_lsa_unlock (lsa);
2100 break;
2101 }
2102
hasso508e53e2004-05-18 18:57:06 +00002103 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2104 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2105 p += OSPF6_LSA_SIZE (lsa->header);
2106 num++;
2107 }
2108
2109 lsupdate->lsa_number = htonl (num);
2110
2111 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2112 oh->length = htons (p - sendbuf);
2113
2114 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2115 on->ospf6_if, oh);
2116
2117 if (on->lsupdate_list->count != 0 ||
2118 on->retrans_list->count != 0)
2119 {
2120 if (on->lsupdate_list->count != 0)
2121 on->thread_send_lsupdate =
2122 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2123 else
2124 on->thread_send_lsupdate =
2125 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2126 on->ospf6_if->rxmt_interval);
2127 }
2128
2129 return 0;
2130}
2131
2132int
2133ospf6_lsupdate_send_interface (struct thread *thread)
2134{
2135 struct ospf6_interface *oi;
2136 struct ospf6_header *oh;
2137 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002138 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002139 int num;
2140 struct ospf6_lsa *lsa;
2141
2142 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2143 oi->thread_send_lsupdate = (struct thread *) NULL;
2144
2145 if (oi->state <= OSPF6_INTERFACE_WAITING)
2146 {
2147 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002148 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2149 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002150 return 0;
2151 }
2152
2153 /* if we have nothing to send, return */
2154 if (oi->lsupdate_list->count == 0)
2155 return 0;
2156
hasso3b4cd3a2004-05-18 19:28:32 +00002157 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002158 oh = (struct ospf6_header *) sendbuf;
2159 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
2160 sizeof (struct ospf6_header));
2161
Paul Jakma6ac29a52008-08-15 13:45:30 +01002162 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002163 num = 0;
2164
2165 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2166 lsa = ospf6_lsdb_next (lsa))
2167 {
2168 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002169 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002170 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002171 {
2172 ospf6_lsa_unlock (lsa);
2173 break;
2174 }
2175
hasso508e53e2004-05-18 18:57:06 +00002176 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2177 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2178 p += OSPF6_LSA_SIZE (lsa->header);
2179 num++;
2180
2181 assert (lsa->lock == 2);
2182 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2183 }
2184
2185 lsupdate->lsa_number = htonl (num);
2186
2187 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2188 oh->length = htons (p - sendbuf);
2189
2190 if (oi->state == OSPF6_INTERFACE_DR ||
2191 oi->state == OSPF6_INTERFACE_BDR)
2192 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2193 else
2194 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2195
2196 if (oi->lsupdate_list->count > 0)
2197 {
2198 oi->thread_send_lsupdate =
2199 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2200 }
2201
2202 return 0;
2203}
2204
2205int
2206ospf6_lsack_send_neighbor (struct thread *thread)
2207{
2208 struct ospf6_neighbor *on;
2209 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002210 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002211 struct ospf6_lsa *lsa;
2212
2213 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2214 on->thread_send_lsack = (struct thread *) NULL;
2215
2216 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2217 {
2218 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002219 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2220 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002221 return 0;
2222 }
2223
2224 /* if we have nothing to send, return */
2225 if (on->lsack_list->count == 0)
2226 return 0;
2227
hasso3b4cd3a2004-05-18 19:28:32 +00002228 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002229 oh = (struct ospf6_header *) sendbuf;
2230
Paul Jakma6ac29a52008-08-15 13:45:30 +01002231 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002232
2233 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2234 lsa = ospf6_lsdb_next (lsa))
2235 {
2236 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002237 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002238 {
2239 /* if we run out of packet size/space here,
2240 better to try again soon. */
2241 THREAD_OFF (on->thread_send_lsack);
2242 on->thread_send_lsack =
2243 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2244
2245 ospf6_lsa_unlock (lsa);
2246 break;
2247 }
2248
2249 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2250 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2251 p += sizeof (struct ospf6_lsa_header);
2252
2253 assert (lsa->lock == 2);
2254 ospf6_lsdb_remove (lsa, on->lsack_list);
2255 }
2256
2257 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2258 oh->length = htons (p - sendbuf);
2259
2260 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2261 on->ospf6_if, oh);
2262 return 0;
2263}
2264
2265int
2266ospf6_lsack_send_interface (struct thread *thread)
2267{
2268 struct ospf6_interface *oi;
2269 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002270 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002271 struct ospf6_lsa *lsa;
2272
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))
hasso508e53e2004-05-18 18:57:06 +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);
2304
2305 ospf6_lsa_unlock (lsa);
2306 break;
2307 }
2308
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);
2315 }
2316
2317 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2318 oh->length = htons (p - sendbuf);
2319
2320 if (oi->state == OSPF6_INTERFACE_DR ||
2321 oi->state == OSPF6_INTERFACE_BDR)
2322 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2323 else
2324 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2325
2326 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2327 {
2328 oi->thread_send_lsack =
2329 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2330 }
paul718e3742002-12-13 20:15:29 +00002331
2332 return 0;
2333}
2334
2335
hasso508e53e2004-05-18 18:57:06 +00002336/* Commands */
2337DEFUN (debug_ospf6_message,
2338 debug_ospf6_message_cmd,
2339 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2340 DEBUG_STR
2341 OSPF6_STR
2342 "Debug OSPFv3 message\n"
2343 "Debug Unknown message\n"
2344 "Debug Hello message\n"
2345 "Debug Database Description message\n"
2346 "Debug Link State Request message\n"
2347 "Debug Link State Update message\n"
2348 "Debug Link State Acknowledgement message\n"
2349 "Debug All message\n"
2350 )
paul718e3742002-12-13 20:15:29 +00002351{
hasso508e53e2004-05-18 18:57:06 +00002352 unsigned char level = 0;
2353 int type = 0;
paul718e3742002-12-13 20:15:29 +00002354 int i;
2355
hasso508e53e2004-05-18 18:57:06 +00002356 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002357
hasso508e53e2004-05-18 18:57:06 +00002358 /* check type */
2359 if (! strncmp (argv[0], "u", 1))
2360 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2361 else if (! strncmp (argv[0], "h", 1))
2362 type = OSPF6_MESSAGE_TYPE_HELLO;
2363 else if (! strncmp (argv[0], "d", 1))
2364 type = OSPF6_MESSAGE_TYPE_DBDESC;
2365 else if (! strncmp (argv[0], "lsr", 3))
2366 type = OSPF6_MESSAGE_TYPE_LSREQ;
2367 else if (! strncmp (argv[0], "lsu", 3))
2368 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2369 else if (! strncmp (argv[0], "lsa", 3))
2370 type = OSPF6_MESSAGE_TYPE_LSACK;
2371 else if (! strncmp (argv[0], "a", 1))
2372 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002373
hasso508e53e2004-05-18 18:57:06 +00002374 if (argc == 1)
2375 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2376 else if (! strncmp (argv[1], "s", 1))
2377 level = OSPF6_DEBUG_MESSAGE_SEND;
2378 else if (! strncmp (argv[1], "r", 1))
2379 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002380
hasso508e53e2004-05-18 18:57:06 +00002381 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002382 {
hasso508e53e2004-05-18 18:57:06 +00002383 for (i = 0; i < 6; i++)
2384 OSPF6_DEBUG_MESSAGE_ON (i, level);
2385 }
2386 else
2387 OSPF6_DEBUG_MESSAGE_ON (type, level);
2388
2389 return CMD_SUCCESS;
2390}
2391
2392ALIAS (debug_ospf6_message,
2393 debug_ospf6_message_sendrecv_cmd,
2394 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2395 DEBUG_STR
2396 OSPF6_STR
2397 "Debug OSPFv3 message\n"
2398 "Debug Unknown message\n"
2399 "Debug Hello message\n"
2400 "Debug Database Description message\n"
2401 "Debug Link State Request message\n"
2402 "Debug Link State Update message\n"
2403 "Debug Link State Acknowledgement message\n"
2404 "Debug All message\n"
2405 "Debug only sending message\n"
2406 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002407 )
hasso508e53e2004-05-18 18:57:06 +00002408
2409
2410DEFUN (no_debug_ospf6_message,
2411 no_debug_ospf6_message_cmd,
2412 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2413 NO_STR
2414 DEBUG_STR
2415 OSPF6_STR
2416 "Debug OSPFv3 message\n"
2417 "Debug Unknown message\n"
2418 "Debug Hello message\n"
2419 "Debug Database Description message\n"
2420 "Debug Link State Request message\n"
2421 "Debug Link State Update message\n"
2422 "Debug Link State Acknowledgement message\n"
2423 "Debug All message\n"
2424 )
2425{
2426 unsigned char level = 0;
2427 int type = 0;
2428 int i;
2429
2430 assert (argc > 0);
2431
2432 /* check type */
2433 if (! strncmp (argv[0], "u", 1))
2434 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2435 else if (! strncmp (argv[0], "h", 1))
2436 type = OSPF6_MESSAGE_TYPE_HELLO;
2437 else if (! strncmp (argv[0], "d", 1))
2438 type = OSPF6_MESSAGE_TYPE_DBDESC;
2439 else if (! strncmp (argv[0], "lsr", 3))
2440 type = OSPF6_MESSAGE_TYPE_LSREQ;
2441 else if (! strncmp (argv[0], "lsu", 3))
2442 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2443 else if (! strncmp (argv[0], "lsa", 3))
2444 type = OSPF6_MESSAGE_TYPE_LSACK;
2445 else if (! strncmp (argv[0], "a", 1))
2446 type = OSPF6_MESSAGE_TYPE_ALL;
2447
2448 if (argc == 1)
2449 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2450 else if (! strncmp (argv[1], "s", 1))
2451 level = OSPF6_DEBUG_MESSAGE_SEND;
2452 else if (! strncmp (argv[1], "r", 1))
2453 level = OSPF6_DEBUG_MESSAGE_RECV;
2454
2455 if (type == OSPF6_MESSAGE_TYPE_ALL)
2456 {
2457 for (i = 0; i < 6; i++)
2458 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2459 }
2460 else
2461 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2462
2463 return CMD_SUCCESS;
2464}
2465
2466ALIAS (no_debug_ospf6_message,
2467 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002468 "no debug ospf6 message "
2469 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002470 NO_STR
2471 DEBUG_STR
2472 OSPF6_STR
2473 "Debug OSPFv3 message\n"
2474 "Debug Unknown message\n"
2475 "Debug Hello message\n"
2476 "Debug Database Description message\n"
2477 "Debug Link State Request message\n"
2478 "Debug Link State Update message\n"
2479 "Debug Link State Acknowledgement message\n"
2480 "Debug All message\n"
2481 "Debug only sending message\n"
2482 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002483 )
hasso508e53e2004-05-18 18:57:06 +00002484
2485int
2486config_write_ospf6_debug_message (struct vty *vty)
2487{
paul0c083ee2004-10-10 12:54:58 +00002488 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002489 "lsreq", "lsupdate", "lsack"};
2490 unsigned char s = 0, r = 0;
2491 int i;
2492
2493 for (i = 0; i < 6; i++)
2494 {
2495 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2496 s |= 1 << i;
2497 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2498 r |= 1 << i;
2499 }
2500
2501 if (s == 0x3f && r == 0x3f)
2502 {
hasso049207c2004-08-04 20:02:13 +00002503 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002504 return 0;
2505 }
2506
hasso508e53e2004-05-18 18:57:06 +00002507 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002508 {
hasso049207c2004-08-04 20:02:13 +00002509 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002510 return 0;
2511 }
2512 else if (s == 0 && r == 0x3f)
2513 {
hasso049207c2004-08-04 20:02:13 +00002514 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002515 return 0;
paul718e3742002-12-13 20:15:29 +00002516 }
2517
hasso508e53e2004-05-18 18:57:06 +00002518 /* Unknown message is logged by default */
2519 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2520 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002521 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002522 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002523 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002524 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002525 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002526
hasso508e53e2004-05-18 18:57:06 +00002527 for (i = 1; i < 6; i++)
2528 {
2529 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2530 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002531 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002532 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2533 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002534 VNL);
hasso508e53e2004-05-18 18:57:06 +00002535 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2536 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002537 VNL);
hasso508e53e2004-05-18 18:57:06 +00002538 }
paul718e3742002-12-13 20:15:29 +00002539
2540 return 0;
2541}
2542
paul718e3742002-12-13 20:15:29 +00002543void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002544install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002545{
hasso508e53e2004-05-18 18:57:06 +00002546 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2547 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2548 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2549 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2550 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2551 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2552 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2553 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002554}
2555
paul718e3742002-12-13 20:15:29 +00002556