blob: 362e8a96e1a6a0bb619bef3b1cc39b9ed40218a4 [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 Ovsienko552563a2011-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 Tejblum82a963a2011-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 Ovsienko552563a2011-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 Tejblumab1be8a2011-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 Ovsienko552563a2011-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
1571int
1572ospf6_receive (struct thread *thread)
1573{
paul0c083ee2004-10-10 12:54:58 +00001574 int sockfd;
1575 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001576 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001577 struct in6_addr src, dst;
1578 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001579 struct iovec iovector[2];
1580 struct ospf6_interface *oi;
1581 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001582
1583 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001584 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001585 thread_add_read (master, ospf6_receive, NULL, sockfd);
1586
1587 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001588 memset (&src, 0, sizeof (src));
1589 memset (&dst, 0, sizeof (dst));
1590 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001591 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001592 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001593 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001594 iovector[1].iov_base = NULL;
1595 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001596
1597 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001598 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001599 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001600 {
hasso508e53e2004-05-18 18:57:06 +00001601 zlog_err ("Excess message read");
1602 return 0;
1603 }
paul718e3742002-12-13 20:15:29 +00001604
hasso508e53e2004-05-18 18:57:06 +00001605 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1606 if (oi == NULL || oi->area == NULL)
1607 {
hassoc6487d62004-12-24 06:00:11 +00001608 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001609 return 0;
1610 }
Denis Ovsienko552563a2011-09-26 13:18:51 +04001611 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1612 {
1613 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1614 zlog_debug ("%s: Ignore message on passive interface %s",
1615 __func__, oi->interface->name);
1616 return 0;
1617 }
hasso508e53e2004-05-18 18:57:06 +00001618
1619 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienko552563a2011-09-26 13:18:51 +04001620 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1621 return 0;
1622
1623 /* Being here means, that no sizing/alignment issues were detected in
1624 the input packet. This renders the additional checks performed below
1625 and also in the type-specific dispatching functions a dead code,
1626 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001627
1628 /* Log */
1629 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1630 {
1631 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1632 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001633 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001634 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001635 zlog_debug (" src: %s", srcname);
1636 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001637 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001638 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001639
1640 switch (oh->type)
1641 {
1642 case OSPF6_MESSAGE_TYPE_HELLO:
1643 ospf6_hello_print (oh);
1644 break;
1645 case OSPF6_MESSAGE_TYPE_DBDESC:
1646 ospf6_dbdesc_print (oh);
1647 break;
1648 case OSPF6_MESSAGE_TYPE_LSREQ:
1649 ospf6_lsreq_print (oh);
1650 break;
1651 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1652 ospf6_lsupdate_print (oh);
1653 break;
1654 case OSPF6_MESSAGE_TYPE_LSACK:
1655 ospf6_lsack_print (oh);
1656 break;
1657 default:
hassoc6487d62004-12-24 06:00:11 +00001658 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001659 break;
1660 }
1661 }
1662
hasso508e53e2004-05-18 18:57:06 +00001663 switch (oh->type)
1664 {
1665 case OSPF6_MESSAGE_TYPE_HELLO:
1666 ospf6_hello_recv (&src, &dst, oi, oh);
1667 break;
1668
1669 case OSPF6_MESSAGE_TYPE_DBDESC:
1670 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1671 break;
1672
1673 case OSPF6_MESSAGE_TYPE_LSREQ:
1674 ospf6_lsreq_recv (&src, &dst, oi, oh);
1675 break;
1676
1677 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1678 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1679 break;
1680
1681 case OSPF6_MESSAGE_TYPE_LSACK:
1682 ospf6_lsack_recv (&src, &dst, oi, oh);
1683 break;
1684
1685 default:
1686 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001687 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001688 break;
1689 }
1690
1691 return 0;
1692}
1693
Paul Jakma6ac29a52008-08-15 13:45:30 +01001694static void
hasso508e53e2004-05-18 18:57:06 +00001695ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1696 struct ospf6_interface *oi, struct ospf6_header *oh)
1697{
1698 int len;
1699 char srcname[64], dstname[64];
1700 struct iovec iovector[2];
1701
1702 /* initialize */
1703 iovector[0].iov_base = (caddr_t) oh;
1704 iovector[0].iov_len = ntohs (oh->length);
1705 iovector[1].iov_base = NULL;
1706 iovector[1].iov_len = 0;
1707
1708 /* fill OSPF header */
1709 oh->version = OSPFV3_VERSION;
1710 /* message type must be set before */
1711 /* message length must be set before */
1712 oh->router_id = oi->area->ospf6->router_id;
1713 oh->area_id = oi->area->area_id;
1714 /* checksum is calculated by kernel */
1715 oh->instance_id = oi->instance_id;
1716 oh->reserved = 0;
1717
1718 /* Log */
1719 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1720 {
1721 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1722 if (src)
1723 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1724 else
1725 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001726 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001727 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001728 zlog_debug (" src: %s", srcname);
1729 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001730
1731 switch (oh->type)
1732 {
1733 case OSPF6_MESSAGE_TYPE_HELLO:
1734 ospf6_hello_print (oh);
1735 break;
1736 case OSPF6_MESSAGE_TYPE_DBDESC:
1737 ospf6_dbdesc_print (oh);
1738 break;
1739 case OSPF6_MESSAGE_TYPE_LSREQ:
1740 ospf6_lsreq_print (oh);
1741 break;
1742 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1743 ospf6_lsupdate_print (oh);
1744 break;
1745 case OSPF6_MESSAGE_TYPE_LSACK:
1746 ospf6_lsack_print (oh);
1747 break;
1748 default:
hassoc6487d62004-12-24 06:00:11 +00001749 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001750 assert (0);
1751 break;
1752 }
1753 }
1754
1755 /* send message */
1756 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1757 if (len != ntohs (oh->length))
1758 zlog_err ("Could not send entire message");
1759}
1760
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001761static int
1762ospf6_packet_max(struct ospf6_interface *oi)
1763{
1764 return oi->ifmtu - sizeof(struct ip6_hdr);
1765}
1766
hasso508e53e2004-05-18 18:57:06 +00001767int
1768ospf6_hello_send (struct thread *thread)
1769{
1770 struct ospf6_interface *oi;
1771 struct ospf6_header *oh;
1772 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001773 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001774 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001775 struct ospf6_neighbor *on;
1776
1777 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1778 oi->thread_send_hello = (struct thread *) NULL;
1779
1780 if (oi->state <= OSPF6_INTERFACE_DOWN)
1781 {
1782 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001783 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001784 oi->interface->name);
1785 return 0;
1786 }
1787
1788 /* set next thread */
1789 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1790 oi, oi->hello_interval);
1791
hasso3b4cd3a2004-05-18 19:28:32 +00001792 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001793 oh = (struct ospf6_header *) sendbuf;
1794 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1795
1796 hello->interface_id = htonl (oi->interface->ifindex);
1797 hello->priority = oi->priority;
1798 hello->options[0] = oi->area->options[0];
1799 hello->options[1] = oi->area->options[1];
1800 hello->options[2] = oi->area->options[2];
1801 hello->hello_interval = htons (oi->hello_interval);
1802 hello->dead_interval = htons (oi->dead_interval);
1803 hello->drouter = oi->drouter;
1804 hello->bdrouter = oi->bdrouter;
1805
Paul Jakma6ac29a52008-08-15 13:45:30 +01001806 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001807
paul1eb8ef22005-04-07 07:30:20 +00001808 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001809 {
hasso508e53e2004-05-18 18:57:06 +00001810 if (on->state < OSPF6_NEIGHBOR_INIT)
1811 continue;
1812
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001813 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001814 {
1815 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001816 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001817 break;
1818 }
1819
1820 memcpy (p, &on->router_id, sizeof (u_int32_t));
1821 p += sizeof (u_int32_t);
1822 }
1823
1824 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1825 oh->length = htons (p - sendbuf);
1826
1827 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1828 return 0;
1829}
1830
1831int
1832ospf6_dbdesc_send (struct thread *thread)
1833{
1834 struct ospf6_neighbor *on;
1835 struct ospf6_header *oh;
1836 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001837 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001838 struct ospf6_lsa *lsa;
1839
1840 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1841 on->thread_send_dbdesc = (struct thread *) NULL;
1842
1843 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1844 {
1845 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001846 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1847 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001848 return 0;
1849 }
1850
1851 /* set next thread if master */
1852 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1853 on->thread_send_dbdesc =
1854 thread_add_timer (master, ospf6_dbdesc_send, on,
1855 on->ospf6_if->rxmt_interval);
1856
hasso3b4cd3a2004-05-18 19:28:32 +00001857 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001858 oh = (struct ospf6_header *) sendbuf;
1859 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1860 sizeof (struct ospf6_header));
1861
1862 /* if this is initial one, initialize sequence number for DbDesc */
1863 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1864 {
1865 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001866 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001867 tv.tv_sec = 1;
1868 on->dbdesc_seqnum = tv.tv_sec;
1869 }
1870
1871 dbdesc->options[0] = on->ospf6_if->area->options[0];
1872 dbdesc->options[1] = on->ospf6_if->area->options[1];
1873 dbdesc->options[2] = on->ospf6_if->area->options[2];
1874 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1875 dbdesc->bits = on->dbdesc_bits;
1876 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1877
1878 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001879 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001880 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1881 {
1882 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1883 lsa = ospf6_lsdb_next (lsa))
1884 {
1885 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1886
1887 /* MTU check */
1888 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001889 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001890 {
1891 ospf6_lsa_unlock (lsa);
1892 break;
1893 }
1894 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1895 p += sizeof (struct ospf6_lsa_header);
1896 }
1897 }
1898
1899 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1900 oh->length = htons (p - sendbuf);
1901
1902 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1903 on->ospf6_if, oh);
1904 return 0;
1905}
1906
1907int
1908ospf6_dbdesc_send_newone (struct thread *thread)
1909{
1910 struct ospf6_neighbor *on;
1911 struct ospf6_lsa *lsa;
1912 unsigned int size = 0;
1913
1914 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001915 ospf6_lsdb_remove_all (on->dbdesc_list);
1916
1917 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1918 so that ospf6_send_dbdesc () can send those LSAs */
1919 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1920 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1921 lsa = ospf6_lsdb_next (lsa))
1922 {
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001923 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001924 {
1925 ospf6_lsa_unlock (lsa);
1926 break;
1927 }
1928
hasso508e53e2004-05-18 18:57:06 +00001929 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1930 ospf6_lsdb_remove (lsa, on->summary_list);
1931 size += sizeof (struct ospf6_lsa_header);
1932 }
1933
1934 if (on->summary_list->count == 0)
1935 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1936
1937 /* If slave, More bit check must be done here */
1938 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1939 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1940 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1941 thread_add_event (master, exchange_done, on, 0);
1942
1943 thread_execute (master, ospf6_dbdesc_send, on, 0);
1944 return 0;
1945}
1946
1947int
1948ospf6_lsreq_send (struct thread *thread)
1949{
1950 struct ospf6_neighbor *on;
1951 struct ospf6_header *oh;
1952 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001953 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001954 struct ospf6_lsa *lsa;
1955
1956 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1957 on->thread_send_lsreq = (struct thread *) NULL;
1958
1959 /* LSReq will be sent only in ExStart or Loading */
1960 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1961 on->state != OSPF6_NEIGHBOR_LOADING)
1962 {
1963 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001964 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1965 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001966 return 0;
1967 }
1968
1969 /* schedule loading_done if request list is empty */
1970 if (on->request_list->count == 0)
1971 {
1972 thread_add_event (master, loading_done, on, 0);
1973 return 0;
1974 }
1975
1976 /* set next thread */
1977 on->thread_send_lsreq =
1978 thread_add_timer (master, ospf6_lsreq_send, on,
1979 on->ospf6_if->rxmt_interval);
1980
hasso3b4cd3a2004-05-18 19:28:32 +00001981 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001982 oh = (struct ospf6_header *) sendbuf;
1983
1984 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001985 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001986 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1987 lsa = ospf6_lsdb_next (lsa))
1988 {
1989 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001990 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001991 {
1992 ospf6_lsa_unlock (lsa);
1993 break;
1994 }
1995
1996 e = (struct ospf6_lsreq_entry *) p;
1997 e->type = lsa->header->type;
1998 e->id = lsa->header->id;
1999 e->adv_router = lsa->header->adv_router;
2000 p += sizeof (struct ospf6_lsreq_entry);
2001 }
2002
2003 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
2004 oh->length = htons (p - sendbuf);
2005
2006 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2007 on->ospf6_if, oh);
2008 return 0;
2009}
2010
2011int
2012ospf6_lsupdate_send_neighbor (struct thread *thread)
2013{
2014 struct ospf6_neighbor *on;
2015 struct ospf6_header *oh;
2016 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002017 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002018 int num;
2019 struct ospf6_lsa *lsa;
2020
2021 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2022 on->thread_send_lsupdate = (struct thread *) NULL;
2023
hasso6452df02004-08-15 05:52:07 +00002024 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002025 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00002026
hasso508e53e2004-05-18 18:57:06 +00002027 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2028 {
2029 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002030 zlog_debug ("Quit to send (neighbor state %s)",
2031 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002032 return 0;
2033 }
2034
2035 /* if we have nothing to send, return */
2036 if (on->lsupdate_list->count == 0 &&
2037 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00002038 {
2039 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002040 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00002041 return 0;
2042 }
hasso508e53e2004-05-18 18:57:06 +00002043
hasso3b4cd3a2004-05-18 19:28:32 +00002044 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002045 oh = (struct ospf6_header *) sendbuf;
2046 lsupdate = (struct ospf6_lsupdate *)
2047 ((caddr_t) oh + sizeof (struct ospf6_header));
2048
Paul Jakma6ac29a52008-08-15 13:45:30 +01002049 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002050 num = 0;
2051
2052 /* lsupdate_list lists those LSA which doesn't need to be
2053 retransmitted. remove those from the list */
2054 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2055 lsa = ospf6_lsdb_next (lsa))
2056 {
2057 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002058 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002059 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002060 {
2061 ospf6_lsa_unlock (lsa);
2062 break;
2063 }
2064
hasso508e53e2004-05-18 18:57:06 +00002065 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2066 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2067 p += OSPF6_LSA_SIZE (lsa->header);
2068 num++;
2069
2070 assert (lsa->lock == 2);
2071 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2072 }
2073
2074 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2075 lsa = ospf6_lsdb_next (lsa))
2076 {
2077 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002078 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002079 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002080 {
2081 ospf6_lsa_unlock (lsa);
2082 break;
2083 }
2084
hasso508e53e2004-05-18 18:57:06 +00002085 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2086 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2087 p += OSPF6_LSA_SIZE (lsa->header);
2088 num++;
2089 }
2090
2091 lsupdate->lsa_number = htonl (num);
2092
2093 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2094 oh->length = htons (p - sendbuf);
2095
2096 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2097 on->ospf6_if, oh);
2098
2099 if (on->lsupdate_list->count != 0 ||
2100 on->retrans_list->count != 0)
2101 {
2102 if (on->lsupdate_list->count != 0)
2103 on->thread_send_lsupdate =
2104 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2105 else
2106 on->thread_send_lsupdate =
2107 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2108 on->ospf6_if->rxmt_interval);
2109 }
2110
2111 return 0;
2112}
2113
2114int
2115ospf6_lsupdate_send_interface (struct thread *thread)
2116{
2117 struct ospf6_interface *oi;
2118 struct ospf6_header *oh;
2119 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002120 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002121 int num;
2122 struct ospf6_lsa *lsa;
2123
2124 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2125 oi->thread_send_lsupdate = (struct thread *) NULL;
2126
2127 if (oi->state <= OSPF6_INTERFACE_WAITING)
2128 {
2129 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002130 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2131 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002132 return 0;
2133 }
2134
2135 /* if we have nothing to send, return */
2136 if (oi->lsupdate_list->count == 0)
2137 return 0;
2138
hasso3b4cd3a2004-05-18 19:28:32 +00002139 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002140 oh = (struct ospf6_header *) sendbuf;
2141 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
2142 sizeof (struct ospf6_header));
2143
Paul Jakma6ac29a52008-08-15 13:45:30 +01002144 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002145 num = 0;
2146
2147 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2148 lsa = ospf6_lsdb_next (lsa))
2149 {
2150 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002151 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002152 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002153 {
2154 ospf6_lsa_unlock (lsa);
2155 break;
2156 }
2157
hasso508e53e2004-05-18 18:57:06 +00002158 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2159 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2160 p += OSPF6_LSA_SIZE (lsa->header);
2161 num++;
2162
2163 assert (lsa->lock == 2);
2164 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2165 }
2166
2167 lsupdate->lsa_number = htonl (num);
2168
2169 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2170 oh->length = htons (p - sendbuf);
2171
2172 if (oi->state == OSPF6_INTERFACE_DR ||
2173 oi->state == OSPF6_INTERFACE_BDR)
2174 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2175 else
2176 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2177
2178 if (oi->lsupdate_list->count > 0)
2179 {
2180 oi->thread_send_lsupdate =
2181 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2182 }
2183
2184 return 0;
2185}
2186
2187int
2188ospf6_lsack_send_neighbor (struct thread *thread)
2189{
2190 struct ospf6_neighbor *on;
2191 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002192 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002193 struct ospf6_lsa *lsa;
2194
2195 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2196 on->thread_send_lsack = (struct thread *) NULL;
2197
2198 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2199 {
2200 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002201 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2202 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002203 return 0;
2204 }
2205
2206 /* if we have nothing to send, return */
2207 if (on->lsack_list->count == 0)
2208 return 0;
2209
hasso3b4cd3a2004-05-18 19:28:32 +00002210 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002211 oh = (struct ospf6_header *) sendbuf;
2212
Paul Jakma6ac29a52008-08-15 13:45:30 +01002213 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002214
2215 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2216 lsa = ospf6_lsdb_next (lsa))
2217 {
2218 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002219 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002220 {
2221 /* if we run out of packet size/space here,
2222 better to try again soon. */
2223 THREAD_OFF (on->thread_send_lsack);
2224 on->thread_send_lsack =
2225 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2226
2227 ospf6_lsa_unlock (lsa);
2228 break;
2229 }
2230
2231 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2232 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2233 p += sizeof (struct ospf6_lsa_header);
2234
2235 assert (lsa->lock == 2);
2236 ospf6_lsdb_remove (lsa, on->lsack_list);
2237 }
2238
2239 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2240 oh->length = htons (p - sendbuf);
2241
2242 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2243 on->ospf6_if, oh);
2244 return 0;
2245}
2246
2247int
2248ospf6_lsack_send_interface (struct thread *thread)
2249{
2250 struct ospf6_interface *oi;
2251 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002252 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002253 struct ospf6_lsa *lsa;
2254
2255 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2256 oi->thread_send_lsack = (struct thread *) NULL;
2257
2258 if (oi->state <= OSPF6_INTERFACE_WAITING)
2259 {
2260 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002261 zlog_debug ("Quit to send LSAck to interface %s state %s",
2262 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002263 return 0;
2264 }
2265
2266 /* if we have nothing to send, return */
2267 if (oi->lsack_list->count == 0)
2268 return 0;
2269
hasso3b4cd3a2004-05-18 19:28:32 +00002270 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002271 oh = (struct ospf6_header *) sendbuf;
2272
Paul Jakma6ac29a52008-08-15 13:45:30 +01002273 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002274
2275 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2276 lsa = ospf6_lsdb_next (lsa))
2277 {
2278 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002279 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002280 {
2281 /* if we run out of packet size/space here,
2282 better to try again soon. */
2283 THREAD_OFF (oi->thread_send_lsack);
2284 oi->thread_send_lsack =
2285 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2286
2287 ospf6_lsa_unlock (lsa);
2288 break;
2289 }
2290
2291 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2292 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2293 p += sizeof (struct ospf6_lsa_header);
2294
2295 assert (lsa->lock == 2);
2296 ospf6_lsdb_remove (lsa, oi->lsack_list);
2297 }
2298
2299 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2300 oh->length = htons (p - sendbuf);
2301
2302 if (oi->state == OSPF6_INTERFACE_DR ||
2303 oi->state == OSPF6_INTERFACE_BDR)
2304 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2305 else
2306 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2307
2308 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2309 {
2310 oi->thread_send_lsack =
2311 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2312 }
paul718e3742002-12-13 20:15:29 +00002313
2314 return 0;
2315}
2316
2317
hasso508e53e2004-05-18 18:57:06 +00002318/* Commands */
2319DEFUN (debug_ospf6_message,
2320 debug_ospf6_message_cmd,
2321 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2322 DEBUG_STR
2323 OSPF6_STR
2324 "Debug OSPFv3 message\n"
2325 "Debug Unknown message\n"
2326 "Debug Hello message\n"
2327 "Debug Database Description message\n"
2328 "Debug Link State Request message\n"
2329 "Debug Link State Update message\n"
2330 "Debug Link State Acknowledgement message\n"
2331 "Debug All message\n"
2332 )
paul718e3742002-12-13 20:15:29 +00002333{
hasso508e53e2004-05-18 18:57:06 +00002334 unsigned char level = 0;
2335 int type = 0;
paul718e3742002-12-13 20:15:29 +00002336 int i;
2337
hasso508e53e2004-05-18 18:57:06 +00002338 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002339
hasso508e53e2004-05-18 18:57:06 +00002340 /* check type */
2341 if (! strncmp (argv[0], "u", 1))
2342 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2343 else if (! strncmp (argv[0], "h", 1))
2344 type = OSPF6_MESSAGE_TYPE_HELLO;
2345 else if (! strncmp (argv[0], "d", 1))
2346 type = OSPF6_MESSAGE_TYPE_DBDESC;
2347 else if (! strncmp (argv[0], "lsr", 3))
2348 type = OSPF6_MESSAGE_TYPE_LSREQ;
2349 else if (! strncmp (argv[0], "lsu", 3))
2350 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2351 else if (! strncmp (argv[0], "lsa", 3))
2352 type = OSPF6_MESSAGE_TYPE_LSACK;
2353 else if (! strncmp (argv[0], "a", 1))
2354 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002355
hasso508e53e2004-05-18 18:57:06 +00002356 if (argc == 1)
2357 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2358 else if (! strncmp (argv[1], "s", 1))
2359 level = OSPF6_DEBUG_MESSAGE_SEND;
2360 else if (! strncmp (argv[1], "r", 1))
2361 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002362
hasso508e53e2004-05-18 18:57:06 +00002363 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002364 {
hasso508e53e2004-05-18 18:57:06 +00002365 for (i = 0; i < 6; i++)
2366 OSPF6_DEBUG_MESSAGE_ON (i, level);
2367 }
2368 else
2369 OSPF6_DEBUG_MESSAGE_ON (type, level);
2370
2371 return CMD_SUCCESS;
2372}
2373
2374ALIAS (debug_ospf6_message,
2375 debug_ospf6_message_sendrecv_cmd,
2376 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2377 DEBUG_STR
2378 OSPF6_STR
2379 "Debug OSPFv3 message\n"
2380 "Debug Unknown message\n"
2381 "Debug Hello message\n"
2382 "Debug Database Description message\n"
2383 "Debug Link State Request message\n"
2384 "Debug Link State Update message\n"
2385 "Debug Link State Acknowledgement message\n"
2386 "Debug All message\n"
2387 "Debug only sending message\n"
2388 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002389 )
hasso508e53e2004-05-18 18:57:06 +00002390
2391
2392DEFUN (no_debug_ospf6_message,
2393 no_debug_ospf6_message_cmd,
2394 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2395 NO_STR
2396 DEBUG_STR
2397 OSPF6_STR
2398 "Debug OSPFv3 message\n"
2399 "Debug Unknown message\n"
2400 "Debug Hello message\n"
2401 "Debug Database Description message\n"
2402 "Debug Link State Request message\n"
2403 "Debug Link State Update message\n"
2404 "Debug Link State Acknowledgement message\n"
2405 "Debug All message\n"
2406 )
2407{
2408 unsigned char level = 0;
2409 int type = 0;
2410 int i;
2411
2412 assert (argc > 0);
2413
2414 /* check type */
2415 if (! strncmp (argv[0], "u", 1))
2416 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2417 else if (! strncmp (argv[0], "h", 1))
2418 type = OSPF6_MESSAGE_TYPE_HELLO;
2419 else if (! strncmp (argv[0], "d", 1))
2420 type = OSPF6_MESSAGE_TYPE_DBDESC;
2421 else if (! strncmp (argv[0], "lsr", 3))
2422 type = OSPF6_MESSAGE_TYPE_LSREQ;
2423 else if (! strncmp (argv[0], "lsu", 3))
2424 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2425 else if (! strncmp (argv[0], "lsa", 3))
2426 type = OSPF6_MESSAGE_TYPE_LSACK;
2427 else if (! strncmp (argv[0], "a", 1))
2428 type = OSPF6_MESSAGE_TYPE_ALL;
2429
2430 if (argc == 1)
2431 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2432 else if (! strncmp (argv[1], "s", 1))
2433 level = OSPF6_DEBUG_MESSAGE_SEND;
2434 else if (! strncmp (argv[1], "r", 1))
2435 level = OSPF6_DEBUG_MESSAGE_RECV;
2436
2437 if (type == OSPF6_MESSAGE_TYPE_ALL)
2438 {
2439 for (i = 0; i < 6; i++)
2440 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2441 }
2442 else
2443 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2444
2445 return CMD_SUCCESS;
2446}
2447
2448ALIAS (no_debug_ospf6_message,
2449 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002450 "no debug ospf6 message "
2451 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002452 NO_STR
2453 DEBUG_STR
2454 OSPF6_STR
2455 "Debug OSPFv3 message\n"
2456 "Debug Unknown message\n"
2457 "Debug Hello message\n"
2458 "Debug Database Description message\n"
2459 "Debug Link State Request message\n"
2460 "Debug Link State Update message\n"
2461 "Debug Link State Acknowledgement message\n"
2462 "Debug All message\n"
2463 "Debug only sending message\n"
2464 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002465 )
hasso508e53e2004-05-18 18:57:06 +00002466
2467int
2468config_write_ospf6_debug_message (struct vty *vty)
2469{
paul0c083ee2004-10-10 12:54:58 +00002470 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002471 "lsreq", "lsupdate", "lsack"};
2472 unsigned char s = 0, r = 0;
2473 int i;
2474
2475 for (i = 0; i < 6; i++)
2476 {
2477 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2478 s |= 1 << i;
2479 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2480 r |= 1 << i;
2481 }
2482
2483 if (s == 0x3f && r == 0x3f)
2484 {
hasso049207c2004-08-04 20:02:13 +00002485 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002486 return 0;
2487 }
2488
hasso508e53e2004-05-18 18:57:06 +00002489 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002490 {
hasso049207c2004-08-04 20:02:13 +00002491 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002492 return 0;
2493 }
2494 else if (s == 0 && r == 0x3f)
2495 {
hasso049207c2004-08-04 20:02:13 +00002496 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002497 return 0;
paul718e3742002-12-13 20:15:29 +00002498 }
2499
hasso508e53e2004-05-18 18:57:06 +00002500 /* Unknown message is logged by default */
2501 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2502 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002503 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002504 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002505 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002506 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002507 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002508
hasso508e53e2004-05-18 18:57:06 +00002509 for (i = 1; i < 6; i++)
2510 {
2511 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2512 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002513 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002514 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2515 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002516 VNL);
hasso508e53e2004-05-18 18:57:06 +00002517 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2518 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002519 VNL);
hasso508e53e2004-05-18 18:57:06 +00002520 }
paul718e3742002-12-13 20:15:29 +00002521
2522 return 0;
2523}
2524
paul718e3742002-12-13 20:15:29 +00002525void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002526install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002527{
hasso508e53e2004-05-18 18:57:06 +00002528 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2529 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2530 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2531 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2532 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2533 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2534 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2535 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002536}
2537
paul718e3742002-12-13 20:15:29 +00002538