blob: beec272b3f79f0e4c2f92365cb83fb19a973f07a [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
42#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000043#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000044
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +040045#include <netinet/ip6.h>
46
hasso508e53e2004-05-18 18:57:06 +000047unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
paul0c083ee2004-10-10 12:54:58 +000048const char *ospf6_message_type_str[] =
hasso508e53e2004-05-18 18:57:06 +000049 { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
50
51/* print functions */
52
53static void
54ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000055{
hasso508e53e2004-05-18 18:57:06 +000056 char router_id[16], area_id[16];
57 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
58 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000059
hassoc6487d62004-12-24 06:00:11 +000060 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +000061 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +000062 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +000063 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +000064}
paul718e3742002-12-13 20:15:29 +000065
66void
hasso508e53e2004-05-18 18:57:06 +000067ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000068{
paul718e3742002-12-13 20:15:29 +000069 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +000070 char options[16];
71 char drouter[16], bdrouter[16], neighbor[16];
72 char *p;
paul718e3742002-12-13 20:15:29 +000073
hasso508e53e2004-05-18 18:57:06 +000074 ospf6_header_print (oh);
75 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +000076
hasso508e53e2004-05-18 18:57:06 +000077 hello = (struct ospf6_hello *)
78 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +000079
hasso508e53e2004-05-18 18:57:06 +000080 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
81 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
82 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +000083
hassoc6487d62004-12-24 06:00:11 +000084 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +000085 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +000086 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +000087 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +000088 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +000089
hasso508e53e2004-05-18 18:57:06 +000090 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
91 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
92 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +000093 {
hasso508e53e2004-05-18 18:57:06 +000094 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +000095 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +000096 }
hasso508e53e2004-05-18 18:57:06 +000097
98 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +000099 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000100}
101
hasso508e53e2004-05-18 18:57:06 +0000102void
103ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000104{
paul718e3742002-12-13 20:15:29 +0000105 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000106 char options[16];
107 char *p;
paul718e3742002-12-13 20:15:29 +0000108
hasso508e53e2004-05-18 18:57:06 +0000109 ospf6_header_print (oh);
110 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000111
hasso508e53e2004-05-18 18:57:06 +0000112 dbdesc = (struct ospf6_dbdesc *)
113 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000114
hasso508e53e2004-05-18 18:57:06 +0000115 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000116
hassoc6487d62004-12-24 06:00:11 +0000117 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000118 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000119 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000120 dbdesc->reserved2,
121 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
122 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
123 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
124 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000125
hasso508e53e2004-05-18 18:57:06 +0000126 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
127 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
128 p += sizeof (struct ospf6_lsa_header))
129 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
130
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_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000137{
hasso508e53e2004-05-18 18:57:06 +0000138 char id[16], adv_router[16];
139 char *p;
paul718e3742002-12-13 20:15:29 +0000140
hasso508e53e2004-05-18 18:57:06 +0000141 ospf6_header_print (oh);
142 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000143
hasso508e53e2004-05-18 18:57:06 +0000144 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
145 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
146 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000147 {
hasso508e53e2004-05-18 18:57:06 +0000148 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
149 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
150 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000151 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000152 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000153 }
hasso508e53e2004-05-18 18:57:06 +0000154
155 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000156 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000157}
158
hasso508e53e2004-05-18 18:57:06 +0000159void
160ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000161{
paul718e3742002-12-13 20:15:29 +0000162 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000163 u_long num;
164 char *p;
paul718e3742002-12-13 20:15:29 +0000165
hasso508e53e2004-05-18 18:57:06 +0000166 ospf6_header_print (oh);
167 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000168
hasso508e53e2004-05-18 18:57:06 +0000169 lsupdate = (struct ospf6_lsupdate *)
170 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000171
hasso508e53e2004-05-18 18:57:06 +0000172 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000173 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000174
hasso508e53e2004-05-18 18:57:06 +0000175 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
176 p < OSPF6_MESSAGE_END (oh) &&
177 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
178 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000179 {
hasso508e53e2004-05-18 18:57:06 +0000180 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
181 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
182 {
hassoc6487d62004-12-24 06:00:11 +0000183 zlog_debug (" Malformed LSA length, quit printing");
hasso508e53e2004-05-18 18:57:06 +0000184 break;
185 }
186 }
paul718e3742002-12-13 20:15:29 +0000187
hasso508e53e2004-05-18 18:57:06 +0000188 if (p != OSPF6_MESSAGE_END (oh))
189 {
190 char buf[32];
191
192 int num = 0;
193 memset (buf, 0, sizeof (buf));
194
hassoc6487d62004-12-24 06:00:11 +0000195 zlog_debug (" Trailing garbage exists");
hasso508e53e2004-05-18 18:57:06 +0000196 while (p < OSPF6_MESSAGE_END (oh))
197 {
198 snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
199 num++;
200 if (num == 8)
201 {
hassoc6487d62004-12-24 06:00:11 +0000202 zlog_debug (" %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000203 memset (buf, 0, sizeof (buf));
204 num = 0;
205 }
206 }
207 if (num)
hassoc6487d62004-12-24 06:00:11 +0000208 zlog_debug (" %s", buf);
paul718e3742002-12-13 20:15:29 +0000209 }
210}
211
hasso508e53e2004-05-18 18:57:06 +0000212void
213ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000214{
hasso508e53e2004-05-18 18:57:06 +0000215 char *p;
paul718e3742002-12-13 20:15:29 +0000216
hasso508e53e2004-05-18 18:57:06 +0000217 ospf6_header_print (oh);
218 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000219
hasso508e53e2004-05-18 18:57:06 +0000220 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
221 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
222 p += sizeof (struct ospf6_lsa_header))
223 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
224
225 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000226 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000227}
228
hasso508e53e2004-05-18 18:57:06 +0000229/* Receive function */
hasso508e53e2004-05-18 18:57:06 +0000230static int
231ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst,
232 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000233{
paul718e3742002-12-13 20:15:29 +0000234 u_char type;
hasso508e53e2004-05-18 18:57:06 +0000235 type = OSPF6_MESSAGE_TYPE_CANONICAL (oh->type);
paul718e3742002-12-13 20:15:29 +0000236
hasso508e53e2004-05-18 18:57:06 +0000237 /* version check */
238 if (oh->version != OSPFV3_VERSION)
paul718e3742002-12-13 20:15:29 +0000239 {
hasso508e53e2004-05-18 18:57:06 +0000240 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000241 zlog_debug ("Message with unknown version");
hasso508e53e2004-05-18 18:57:06 +0000242 return MSG_NG;
paul718e3742002-12-13 20:15:29 +0000243 }
244
hasso508e53e2004-05-18 18:57:06 +0000245 /* Area-ID check */
246 if (oh->area_id != oi->area->area_id)
247 {
hasso6452df02004-08-15 05:52:07 +0000248 if (oh->area_id == BACKBONE_AREA_ID)
hasso508e53e2004-05-18 18:57:06 +0000249 {
250 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000251 zlog_debug ("Message may be via Virtual Link: not supported");
hasso508e53e2004-05-18 18:57:06 +0000252 return MSG_NG;
253 }
254
255 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000256 zlog_debug ("Area-ID mismatch");
hasso508e53e2004-05-18 18:57:06 +0000257 return MSG_NG;
258 }
259
260 /* Instance-ID check */
261 if (oh->instance_id != oi->instance_id)
262 {
263 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000264 zlog_debug ("Instance-ID mismatch");
hasso508e53e2004-05-18 18:57:06 +0000265 return MSG_NG;
266 }
267
268 /* Router-ID check */
269 if (oh->router_id == oi->area->ospf6->router_id)
270 zlog_warn ("Detect duplicate Router-ID");
271
272 return MSG_OK;
273}
274
Paul Jakma6ac29a52008-08-15 13:45:30 +0100275static void
hasso508e53e2004-05-18 18:57:06 +0000276ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
277 struct ospf6_interface *oi, struct ospf6_header *oh)
278{
279 struct ospf6_hello *hello;
280 struct ospf6_neighbor *on;
281 char *p;
282 int twoway = 0;
283 int neighborchange = 0;
284 int backupseen = 0;
285
286 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
287 return;
288
289 hello = (struct ospf6_hello *)
290 ((caddr_t) oh + sizeof (struct ospf6_header));
291
paul718e3742002-12-13 20:15:29 +0000292 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000293 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000294 {
hasso508e53e2004-05-18 18:57:06 +0000295 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000296 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000297 return;
298 }
299
300 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000301 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000302 {
hasso508e53e2004-05-18 18:57:06 +0000303 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000304 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000305 return;
306 }
307
hasso508e53e2004-05-18 18:57:06 +0000308 /* E-bit check */
309 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
310 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000311 {
hasso508e53e2004-05-18 18:57:06 +0000312 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000313 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000314 return;
315 }
316
hasso508e53e2004-05-18 18:57:06 +0000317 /* Find neighbor, create if not exist */
318 on = ospf6_neighbor_lookup (oh->router_id, oi);
319 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000320 {
hasso508e53e2004-05-18 18:57:06 +0000321 on = ospf6_neighbor_create (oh->router_id, oi);
322 on->prev_drouter = on->drouter = hello->drouter;
323 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
324 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000325 }
326
hasso7b6ae022005-06-24 08:17:51 +0000327 /* always override neighbor's source address and ifindex */
328 on->ifindex = ntohl (hello->interface_id);
329 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
330
paul718e3742002-12-13 20:15:29 +0000331 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000332 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
333 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
334 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000335 {
hasso508e53e2004-05-18 18:57:06 +0000336 u_int32_t *router_id = (u_int32_t *) p;
337
338 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000339 twoway++;
paul718e3742002-12-13 20:15:29 +0000340 }
341
hasso508e53e2004-05-18 18:57:06 +0000342 if (p != OSPF6_MESSAGE_END (oh))
343 {
344 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000345 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000346 }
347
348 /* RouterPriority check */
349 if (on->priority != hello->priority)
350 {
351 on->priority = hello->priority;
352 neighborchange++;
353 }
354
355 /* DR check */
356 if (on->drouter != hello->drouter)
357 {
358 on->prev_drouter = on->drouter;
359 on->drouter = hello->drouter;
360 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
361 neighborchange++;
362 }
363
364 /* BDR check */
365 if (on->bdrouter != hello->bdrouter)
366 {
367 on->prev_bdrouter = on->bdrouter;
368 on->bdrouter = hello->bdrouter;
369 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
370 neighborchange++;
371 }
paul718e3742002-12-13 20:15:29 +0000372
373 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000374 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000375 {
hasso508e53e2004-05-18 18:57:06 +0000376 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000377 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000378 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000379 backupseen++;
380 }
381
hasso508e53e2004-05-18 18:57:06 +0000382 /* Execute neighbor events */
383 thread_execute (master, hello_received, on, 0);
384 if (twoway)
385 thread_execute (master, twoway_received, on, 0);
386 else
387 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000388
hasso508e53e2004-05-18 18:57:06 +0000389 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000390 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000391 thread_add_event (master, backup_seen, oi, 0);
392 if (neighborchange)
393 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000394}
395
hasso508e53e2004-05-18 18:57:06 +0000396static void
397ospf6_dbdesc_recv_master (struct ospf6_header *oh,
398 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000399{
paul718e3742002-12-13 20:15:29 +0000400 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000401 char *p;
paul718e3742002-12-13 20:15:29 +0000402
hasso508e53e2004-05-18 18:57:06 +0000403 dbdesc = (struct ospf6_dbdesc *)
404 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000405
hasso508e53e2004-05-18 18:57:06 +0000406 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000407 {
hasso508e53e2004-05-18 18:57:06 +0000408 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000409 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000410 return;
411 }
412
hasso508e53e2004-05-18 18:57:06 +0000413 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000414 {
hasso508e53e2004-05-18 18:57:06 +0000415 case OSPF6_NEIGHBOR_TWOWAY:
416 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000417 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000418 return;
419
420 case OSPF6_NEIGHBOR_INIT:
421 thread_execute (master, twoway_received, on, 0);
422 if (on->state != OSPF6_NEIGHBOR_EXSTART)
423 {
424 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000425 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000426 return;
427 }
428 /* else fall through to ExStart */
429
430 case OSPF6_NEIGHBOR_EXSTART:
431 /* if neighbor obeys us as our slave, schedule negotiation_done
432 and process LSA Headers. Otherwise, ignore this message */
433 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
434 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
435 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
436 {
437 /* execute NegotiationDone */
438 thread_execute (master, negotiation_done, on, 0);
439
440 /* Record neighbor options */
441 memcpy (on->options, dbdesc->options, sizeof (on->options));
442 }
443 else
444 {
445 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000446 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000447 return;
448 }
449 /* fall through to exchange */
450
451 case OSPF6_NEIGHBOR_EXCHANGE:
452 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
453 {
454 /* Duplicated DatabaseDescription is dropped by master */
455 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000456 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000457 return;
458 }
459
460 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
461 {
462 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000463 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000464 thread_add_event (master, seqnumber_mismatch, on, 0);
465 return;
466 }
467
468 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
469 {
470 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000471 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000472 thread_add_event (master, seqnumber_mismatch, on, 0);
473 return;
474 }
475
476 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
477 {
478 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000479 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000480 thread_add_event (master, seqnumber_mismatch, on, 0);
481 return;
482 }
483
484 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
485 {
486 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000487 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000488 (u_long) on->dbdesc_seqnum);
489 thread_add_event (master, seqnumber_mismatch, on, 0);
490 return;
491 }
492 break;
493
494 case OSPF6_NEIGHBOR_LOADING:
495 case OSPF6_NEIGHBOR_FULL:
496 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
497 {
498 /* Duplicated DatabaseDescription is dropped by master */
499 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000500 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000501 return;
502 }
503
504 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000505 zlog_debug ("Not duplicate dbdesc in state %s",
506 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000507 thread_add_event (master, seqnumber_mismatch, on, 0);
508 return;
509
510 default:
511 assert (0);
512 break;
513 }
514
515 /* Process LSA headers */
516 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
517 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
518 p += sizeof (struct ospf6_lsa_header))
519 {
520 struct ospf6_lsa *his, *mine;
521 struct ospf6_lsdb *lsdb = NULL;
522
523 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000524
525 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000526 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000527
528 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000529 {
hasso6452df02004-08-15 05:52:07 +0000530 case OSPF6_SCOPE_LINKLOCAL:
531 lsdb = on->ospf6_if->lsdb;
532 break;
533 case OSPF6_SCOPE_AREA:
534 lsdb = on->ospf6_if->area->lsdb;
535 break;
536 case OSPF6_SCOPE_AS:
537 lsdb = on->ospf6_if->area->ospf6->lsdb;
538 break;
539 case OSPF6_SCOPE_RESERVED:
540 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000541 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000542 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000543 continue;
544 break;
hasso508e53e2004-05-18 18:57:06 +0000545 }
546
547 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000548 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000549 {
550 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000551 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000552 ospf6_lsa_delete (his);
553 thread_add_event (master, seqnumber_mismatch, on, 0);
554 return;
555 }
556
557 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
558 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000559 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000560 {
hasso6452df02004-08-15 05:52:07 +0000561 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000562 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000563 ospf6_lsdb_add (his, on->request_list);
564 }
565 else if (ospf6_lsa_compare (his, mine) < 0)
566 {
567 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000568 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000569 ospf6_lsdb_add (his, on->request_list);
570 }
571 else
hasso6452df02004-08-15 05:52:07 +0000572 {
573 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000574 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000575 ospf6_lsa_delete (his);
576 }
hasso508e53e2004-05-18 18:57:06 +0000577 }
578
579 if (p != OSPF6_MESSAGE_END (oh))
580 {
581 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000582 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000583 }
584
585 /* Increment sequence number */
586 on->dbdesc_seqnum ++;
587
588 /* schedule send lsreq */
589 if (on->thread_send_lsreq == NULL)
590 on->thread_send_lsreq =
591 thread_add_event (master, ospf6_lsreq_send, on, 0);
592
593 THREAD_OFF (on->thread_send_dbdesc);
594
595 /* More bit check */
596 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
597 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
598 thread_add_event (master, exchange_done, on, 0);
599 else
600 on->thread_send_dbdesc =
601 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
602
603 /* save last received dbdesc */
604 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
605}
606
607static void
608ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
609 struct ospf6_neighbor *on)
610{
611 struct ospf6_dbdesc *dbdesc;
612 char *p;
613
614 dbdesc = (struct ospf6_dbdesc *)
615 ((caddr_t) oh + sizeof (struct ospf6_header));
616
617 if (on->state < OSPF6_NEIGHBOR_INIT)
618 {
619 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000620 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000621 return;
622 }
623
hasso508e53e2004-05-18 18:57:06 +0000624 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000625 {
hasso508e53e2004-05-18 18:57:06 +0000626 case OSPF6_NEIGHBOR_TWOWAY:
627 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000628 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000629 return;
630
631 case OSPF6_NEIGHBOR_INIT:
632 thread_execute (master, twoway_received, on, 0);
633 if (on->state != OSPF6_NEIGHBOR_EXSTART)
634 {
635 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000636 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000637 return;
638 }
639 /* else fall through to ExStart */
640
641 case OSPF6_NEIGHBOR_EXSTART:
642 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
643 and process LSA Headers. Otherwise, ignore this message */
644 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
645 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
646 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
647 ntohs (oh->length) == sizeof (struct ospf6_header) +
648 sizeof (struct ospf6_dbdesc))
649 {
650 /* set the master/slave bit to slave */
651 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
652
653 /* set the DD sequence number to one specified by master */
654 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
655
656 /* schedule NegotiationDone */
657 thread_execute (master, negotiation_done, on, 0);
658
659 /* Record neighbor options */
660 memcpy (on->options, dbdesc->options, sizeof (on->options));
661 }
662 else
663 {
664 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000665 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000666 return;
667 }
668 break;
669
670 case OSPF6_NEIGHBOR_EXCHANGE:
671 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
672 {
673 /* Duplicated DatabaseDescription causes slave to retransmit */
674 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000675 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000676 THREAD_OFF (on->thread_send_dbdesc);
677 on->thread_send_dbdesc =
678 thread_add_event (master, ospf6_dbdesc_send, on, 0);
679 return;
680 }
681
682 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
683 {
684 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000685 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000686 thread_add_event (master, seqnumber_mismatch, on, 0);
687 return;
688 }
689
690 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
691 {
692 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000693 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000694 thread_add_event (master, seqnumber_mismatch, on, 0);
695 return;
696 }
697
698 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
699 {
700 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000701 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000702 thread_add_event (master, seqnumber_mismatch, on, 0);
703 return;
704 }
705
706 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
707 {
708 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000709 zlog_debug ("Sequence number mismatch (%#lx expected)",
710 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000711 thread_add_event (master, seqnumber_mismatch, on, 0);
712 return;
713 }
714 break;
715
716 case OSPF6_NEIGHBOR_LOADING:
717 case OSPF6_NEIGHBOR_FULL:
718 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
719 {
720 /* Duplicated DatabaseDescription causes slave to retransmit */
721 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000722 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000723 THREAD_OFF (on->thread_send_dbdesc);
724 on->thread_send_dbdesc =
725 thread_add_event (master, ospf6_dbdesc_send, on, 0);
726 return;
727 }
728
729 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000730 zlog_debug ("Not duplicate dbdesc in state %s",
731 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000732 thread_add_event (master, seqnumber_mismatch, on, 0);
733 return;
734
735 default:
736 assert (0);
737 break;
paul718e3742002-12-13 20:15:29 +0000738 }
739
hasso508e53e2004-05-18 18:57:06 +0000740 /* Process LSA headers */
741 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
742 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
743 p += sizeof (struct ospf6_lsa_header))
744 {
745 struct ospf6_lsa *his, *mine;
746 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000747
hasso508e53e2004-05-18 18:57:06 +0000748 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000749
750 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000751 {
hasso6452df02004-08-15 05:52:07 +0000752 case OSPF6_SCOPE_LINKLOCAL:
753 lsdb = on->ospf6_if->lsdb;
754 break;
755 case OSPF6_SCOPE_AREA:
756 lsdb = on->ospf6_if->area->lsdb;
757 break;
758 case OSPF6_SCOPE_AS:
759 lsdb = on->ospf6_if->area->ospf6->lsdb;
760 break;
761 case OSPF6_SCOPE_RESERVED:
762 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000763 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000764 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000765 continue;
766 break;
hasso508e53e2004-05-18 18:57:06 +0000767 }
768
hasso6452df02004-08-15 05:52:07 +0000769 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
770 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000771 {
772 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000773 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000774 ospf6_lsa_delete (his);
775 thread_add_event (master, seqnumber_mismatch, on, 0);
776 return;
777 }
778
779 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
780 his->header->adv_router, lsdb);
781 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
782 {
hasso6452df02004-08-15 05:52:07 +0000783 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000784 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000785 ospf6_lsdb_add (his, on->request_list);
786 }
787 else
788 ospf6_lsa_delete (his);
789 }
790
791 if (p != OSPF6_MESSAGE_END (oh))
792 {
793 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000794 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000795 }
796
797 /* Set sequence number to Master's */
798 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
799
800 /* schedule send lsreq */
801 if (on->thread_send_lsreq == NULL)
802 on->thread_send_lsreq =
803 thread_add_event (master, ospf6_lsreq_send, on, 0);
804
805 THREAD_OFF (on->thread_send_dbdesc);
806 on->thread_send_dbdesc =
807 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
808
809 /* save last received dbdesc */
810 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000811}
812
Paul Jakma6ac29a52008-08-15 13:45:30 +0100813static void
hasso508e53e2004-05-18 18:57:06 +0000814ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
815 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000816{
hasso508e53e2004-05-18 18:57:06 +0000817 struct ospf6_neighbor *on;
818 struct ospf6_dbdesc *dbdesc;
819
820 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
821 return;
822
823 on = ospf6_neighbor_lookup (oh->router_id, oi);
824 if (on == NULL)
825 {
826 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000827 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000828 return;
829 }
830
hasso508e53e2004-05-18 18:57:06 +0000831 dbdesc = (struct ospf6_dbdesc *)
832 ((caddr_t) oh + sizeof (struct ospf6_header));
833
834 /* Interface MTU check */
Dmitrij Tejblumab1be8a2011-04-22 19:27:54 +0400835 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000836 {
837 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000838 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000839 return;
840 }
841
842 if (dbdesc->reserved1 || dbdesc->reserved2)
843 {
844 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000845 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
846 on->name);
hasso508e53e2004-05-18 18:57:06 +0000847 dbdesc->reserved1 = 0;
848 dbdesc->reserved2 = 0;
849 }
850
851 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
852 ospf6_dbdesc_recv_master (oh, on);
853 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
854 ospf6_dbdesc_recv_slave (oh, on);
855 else
856 {
857 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000858 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000859 }
860}
861
Paul Jakma6ac29a52008-08-15 13:45:30 +0100862static void
hasso508e53e2004-05-18 18:57:06 +0000863ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
864 struct ospf6_interface *oi, struct ospf6_header *oh)
865{
866 struct ospf6_neighbor *on;
867 char *p;
868 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000869 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000870 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000871
hasso508e53e2004-05-18 18:57:06 +0000872 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
873 return;
paul718e3742002-12-13 20:15:29 +0000874
hasso508e53e2004-05-18 18:57:06 +0000875 on = ospf6_neighbor_lookup (oh->router_id, oi);
876 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000877 {
hasso508e53e2004-05-18 18:57:06 +0000878 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000879 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000880 return;
881 }
882
hasso508e53e2004-05-18 18:57:06 +0000883 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
884 on->state != OSPF6_NEIGHBOR_LOADING &&
885 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000886 {
hasso508e53e2004-05-18 18:57:06 +0000887 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000888 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000889 return;
890 }
891
hasso508e53e2004-05-18 18:57:06 +0000892 /* Process each request */
893 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
894 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
895 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000896 {
hasso508e53e2004-05-18 18:57:06 +0000897 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000898
899 switch (OSPF6_LSA_SCOPE (e->type))
900 {
901 case OSPF6_SCOPE_LINKLOCAL:
902 lsdb = on->ospf6_if->lsdb;
903 break;
904 case OSPF6_SCOPE_AREA:
905 lsdb = on->ospf6_if->area->lsdb;
906 break;
907 case OSPF6_SCOPE_AS:
908 lsdb = on->ospf6_if->area->ospf6->lsdb;
909 break;
910 default:
911 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000912 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000913 continue;
914 break;
915 }
paul718e3742002-12-13 20:15:29 +0000916
hasso508e53e2004-05-18 18:57:06 +0000917 /* Find database copy */
918 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
919 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000920 {
hasso508e53e2004-05-18 18:57:06 +0000921 char id[16], adv_router[16];
922 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
923 {
924 inet_ntop (AF_INET, &e->id, id, sizeof (id));
925 inet_ntop (AF_INET, &e->adv_router, adv_router,
926 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000927 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
928 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000929 }
930 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000931 return;
932 }
933
hasso508e53e2004-05-18 18:57:06 +0000934 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000935 }
936
hasso508e53e2004-05-18 18:57:06 +0000937 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000938 {
hasso508e53e2004-05-18 18:57:06 +0000939 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000940 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000941 }
942
hasso508e53e2004-05-18 18:57:06 +0000943 /* schedule send lsupdate */
944 THREAD_OFF (on->thread_send_lsupdate);
945 on->thread_send_lsupdate =
946 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000947}
948
Paul Jakma6ac29a52008-08-15 13:45:30 +0100949static void
hasso508e53e2004-05-18 18:57:06 +0000950ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
951 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000952{
hasso508e53e2004-05-18 18:57:06 +0000953 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +0000954 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000955 unsigned long num;
956 char *p;
paul718e3742002-12-13 20:15:29 +0000957
hasso508e53e2004-05-18 18:57:06 +0000958 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
959 return;
paul718e3742002-12-13 20:15:29 +0000960
hasso508e53e2004-05-18 18:57:06 +0000961 on = ospf6_neighbor_lookup (oh->router_id, oi);
962 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000963 {
hasso508e53e2004-05-18 18:57:06 +0000964 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000965 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000966 return;
967 }
968
hasso508e53e2004-05-18 18:57:06 +0000969 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
970 on->state != OSPF6_NEIGHBOR_LOADING &&
971 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000972 {
hasso508e53e2004-05-18 18:57:06 +0000973 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000974 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000975 return;
976 }
977
hasso508e53e2004-05-18 18:57:06 +0000978 lsupdate = (struct ospf6_lsupdate *)
979 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000980
hasso508e53e2004-05-18 18:57:06 +0000981 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +0000982
hasso508e53e2004-05-18 18:57:06 +0000983 /* Process LSAs */
984 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
985 p < OSPF6_MESSAGE_END (oh) &&
986 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
987 p += OSPF6_LSA_SIZE (p))
988 {
989 if (num == 0)
990 break;
991 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
992 {
993 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000994 zlog_debug ("Malformed LSA length, quit processing");
hasso508e53e2004-05-18 18:57:06 +0000995 break;
996 }
997
hasso6452df02004-08-15 05:52:07 +0000998 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000999 num--;
1000 }
1001
1002 if (num != 0)
1003 {
1004 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001005 zlog_debug ("Malformed LSA number or LSA length");
hasso508e53e2004-05-18 18:57:06 +00001006 }
1007 if (p != OSPF6_MESSAGE_END (oh))
1008 {
1009 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001010 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001011 }
paul718e3742002-12-13 20:15:29 +00001012
1013 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1014 with the proper Link State Update packet(s), the Link state request
1015 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001016 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001017 can be recognized as a response to our previous LS Request */
1018 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1019 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1020 on->state == OSPF6_NEIGHBOR_LOADING))
1021 {
1022 THREAD_OFF (on->thread_send_lsreq);
1023 on->thread_send_lsreq =
1024 thread_add_event (master, ospf6_lsreq_send, on, 0);
1025 }
paul718e3742002-12-13 20:15:29 +00001026}
1027
Paul Jakma6ac29a52008-08-15 13:45:30 +01001028static void
hasso508e53e2004-05-18 18:57:06 +00001029ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1030 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001031{
hasso508e53e2004-05-18 18:57:06 +00001032 struct ospf6_neighbor *on;
1033 char *p;
1034 struct ospf6_lsa *his, *mine;
1035 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001036
hasso508e53e2004-05-18 18:57:06 +00001037 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1038 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
1039 return;
paul718e3742002-12-13 20:15:29 +00001040
hasso508e53e2004-05-18 18:57:06 +00001041 on = ospf6_neighbor_lookup (oh->router_id, oi);
1042 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001043 {
hasso508e53e2004-05-18 18:57:06 +00001044 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001045 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001046 return;
1047 }
1048
hasso508e53e2004-05-18 18:57:06 +00001049 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1050 on->state != OSPF6_NEIGHBOR_LOADING &&
1051 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001052 {
hasso508e53e2004-05-18 18:57:06 +00001053 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001054 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001055 return;
1056 }
1057
hasso508e53e2004-05-18 18:57:06 +00001058 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1059 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1060 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001061 {
hasso508e53e2004-05-18 18:57:06 +00001062 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001063
hasso6452df02004-08-15 05:52:07 +00001064 switch (OSPF6_LSA_SCOPE (his->header->type))
1065 {
1066 case OSPF6_SCOPE_LINKLOCAL:
1067 lsdb = on->ospf6_if->lsdb;
1068 break;
1069 case OSPF6_SCOPE_AREA:
1070 lsdb = on->ospf6_if->area->lsdb;
1071 break;
1072 case OSPF6_SCOPE_AS:
1073 lsdb = on->ospf6_if->area->ospf6->lsdb;
1074 break;
1075 case OSPF6_SCOPE_RESERVED:
1076 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001077 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001078 ospf6_lsa_delete (his);
1079 continue;
1080 break;
1081 }
1082
1083 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001084 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001085
1086 /* Find database copy */
1087 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1088 his->header->adv_router, lsdb);
1089 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001090 {
hasso508e53e2004-05-18 18:57:06 +00001091 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001092 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001093 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001094 continue;
1095 }
1096
hasso508e53e2004-05-18 18:57:06 +00001097 /* Check if the LSA is on his retrans-list */
1098 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1099 his->header->adv_router, on->retrans_list);
1100 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001101 {
hasso508e53e2004-05-18 18:57:06 +00001102 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001103 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001104 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001105 continue;
1106 }
1107
hasso508e53e2004-05-18 18:57:06 +00001108 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001109 {
hasso508e53e2004-05-18 18:57:06 +00001110 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001111 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001112 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001113 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001114 ospf6_lsa_delete (his);
1115 continue;
paul718e3742002-12-13 20:15:29 +00001116 }
1117
hasso6452df02004-08-15 05:52:07 +00001118 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001119 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1120 on->name);
hasso508e53e2004-05-18 18:57:06 +00001121
Paul Jakma932bf192006-05-15 10:42:24 +00001122 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001123 if (OSPF6_LSA_IS_MAXAGE (mine))
1124 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001125 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001126 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001127 }
1128
hasso508e53e2004-05-18 18:57:06 +00001129 if (p != OSPF6_MESSAGE_END (oh))
1130 {
1131 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001132 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001133 }
paul718e3742002-12-13 20:15:29 +00001134}
1135
Paul Jakma6ac29a52008-08-15 13:45:30 +01001136static u_char *recvbuf = NULL;
1137static u_char *sendbuf = NULL;
1138static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001139
1140int
paul0c083ee2004-10-10 12:54:58 +00001141ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001142{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001143 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001144
1145 if (size <= iobuflen)
1146 return iobuflen;
1147
1148 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1149 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1150 if (recvnew == NULL || sendnew == NULL)
1151 {
hassob596c712004-07-09 18:33:43 +00001152 if (recvnew)
1153 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1154 if (sendnew)
1155 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001156 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001157 return iobuflen;
1158 }
1159
1160 if (recvbuf)
1161 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1162 if (sendbuf)
1163 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1164 recvbuf = recvnew;
1165 sendbuf = sendnew;
1166 iobuflen = size;
1167
1168 return iobuflen;
1169}
paul718e3742002-12-13 20:15:29 +00001170
1171int
1172ospf6_receive (struct thread *thread)
1173{
paul0c083ee2004-10-10 12:54:58 +00001174 int sockfd;
1175 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001176 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001177 struct in6_addr src, dst;
1178 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001179 struct iovec iovector[2];
1180 struct ospf6_interface *oi;
1181 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001182
1183 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001184 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001185 thread_add_read (master, ospf6_receive, NULL, sockfd);
1186
1187 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001188 memset (&src, 0, sizeof (src));
1189 memset (&dst, 0, sizeof (dst));
1190 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001191 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001192 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001193 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001194 iovector[1].iov_base = NULL;
1195 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001196
1197 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001198 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001199 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001200 {
hasso508e53e2004-05-18 18:57:06 +00001201 zlog_err ("Excess message read");
1202 return 0;
1203 }
1204 else if (len < sizeof (struct ospf6_header))
1205 {
1206 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001207 return 0;
1208 }
1209
hasso508e53e2004-05-18 18:57:06 +00001210 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1211 if (oi == NULL || oi->area == NULL)
1212 {
hassoc6487d62004-12-24 06:00:11 +00001213 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001214 return 0;
1215 }
1216
1217 oh = (struct ospf6_header *) recvbuf;
1218
1219 /* Log */
1220 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1221 {
1222 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1223 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001224 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001225 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001226 zlog_debug (" src: %s", srcname);
1227 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001228 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001229 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001230
1231 switch (oh->type)
1232 {
1233 case OSPF6_MESSAGE_TYPE_HELLO:
1234 ospf6_hello_print (oh);
1235 break;
1236 case OSPF6_MESSAGE_TYPE_DBDESC:
1237 ospf6_dbdesc_print (oh);
1238 break;
1239 case OSPF6_MESSAGE_TYPE_LSREQ:
1240 ospf6_lsreq_print (oh);
1241 break;
1242 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1243 ospf6_lsupdate_print (oh);
1244 break;
1245 case OSPF6_MESSAGE_TYPE_LSACK:
1246 ospf6_lsack_print (oh);
1247 break;
1248 default:
hassoc6487d62004-12-24 06:00:11 +00001249 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001250 break;
1251 }
1252 }
1253
1254 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1255 {
1256 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001257 zlog_debug ("Ignore message on passive interface %s",
hasso508e53e2004-05-18 18:57:06 +00001258 oi->interface->name);
1259 return 0;
1260 }
1261
1262 switch (oh->type)
1263 {
1264 case OSPF6_MESSAGE_TYPE_HELLO:
1265 ospf6_hello_recv (&src, &dst, oi, oh);
1266 break;
1267
1268 case OSPF6_MESSAGE_TYPE_DBDESC:
1269 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1270 break;
1271
1272 case OSPF6_MESSAGE_TYPE_LSREQ:
1273 ospf6_lsreq_recv (&src, &dst, oi, oh);
1274 break;
1275
1276 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1277 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1278 break;
1279
1280 case OSPF6_MESSAGE_TYPE_LSACK:
1281 ospf6_lsack_recv (&src, &dst, oi, oh);
1282 break;
1283
1284 default:
1285 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001286 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001287 break;
1288 }
1289
1290 return 0;
1291}
1292
Paul Jakma6ac29a52008-08-15 13:45:30 +01001293static void
hasso508e53e2004-05-18 18:57:06 +00001294ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1295 struct ospf6_interface *oi, struct ospf6_header *oh)
1296{
1297 int len;
1298 char srcname[64], dstname[64];
1299 struct iovec iovector[2];
1300
1301 /* initialize */
1302 iovector[0].iov_base = (caddr_t) oh;
1303 iovector[0].iov_len = ntohs (oh->length);
1304 iovector[1].iov_base = NULL;
1305 iovector[1].iov_len = 0;
1306
1307 /* fill OSPF header */
1308 oh->version = OSPFV3_VERSION;
1309 /* message type must be set before */
1310 /* message length must be set before */
1311 oh->router_id = oi->area->ospf6->router_id;
1312 oh->area_id = oi->area->area_id;
1313 /* checksum is calculated by kernel */
1314 oh->instance_id = oi->instance_id;
1315 oh->reserved = 0;
1316
1317 /* Log */
1318 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1319 {
1320 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1321 if (src)
1322 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1323 else
1324 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001325 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001326 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001327 zlog_debug (" src: %s", srcname);
1328 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001329
1330 switch (oh->type)
1331 {
1332 case OSPF6_MESSAGE_TYPE_HELLO:
1333 ospf6_hello_print (oh);
1334 break;
1335 case OSPF6_MESSAGE_TYPE_DBDESC:
1336 ospf6_dbdesc_print (oh);
1337 break;
1338 case OSPF6_MESSAGE_TYPE_LSREQ:
1339 ospf6_lsreq_print (oh);
1340 break;
1341 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1342 ospf6_lsupdate_print (oh);
1343 break;
1344 case OSPF6_MESSAGE_TYPE_LSACK:
1345 ospf6_lsack_print (oh);
1346 break;
1347 default:
hassoc6487d62004-12-24 06:00:11 +00001348 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001349 assert (0);
1350 break;
1351 }
1352 }
1353
1354 /* send message */
1355 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1356 if (len != ntohs (oh->length))
1357 zlog_err ("Could not send entire message");
1358}
1359
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001360static int
1361ospf6_packet_max(struct ospf6_interface *oi)
1362{
1363 return oi->ifmtu - sizeof(struct ip6_hdr);
1364}
1365
hasso508e53e2004-05-18 18:57:06 +00001366int
1367ospf6_hello_send (struct thread *thread)
1368{
1369 struct ospf6_interface *oi;
1370 struct ospf6_header *oh;
1371 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001372 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001373 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001374 struct ospf6_neighbor *on;
1375
1376 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1377 oi->thread_send_hello = (struct thread *) NULL;
1378
1379 if (oi->state <= OSPF6_INTERFACE_DOWN)
1380 {
1381 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001382 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001383 oi->interface->name);
1384 return 0;
1385 }
1386
1387 /* set next thread */
1388 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1389 oi, oi->hello_interval);
1390
hasso3b4cd3a2004-05-18 19:28:32 +00001391 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001392 oh = (struct ospf6_header *) sendbuf;
1393 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1394
1395 hello->interface_id = htonl (oi->interface->ifindex);
1396 hello->priority = oi->priority;
1397 hello->options[0] = oi->area->options[0];
1398 hello->options[1] = oi->area->options[1];
1399 hello->options[2] = oi->area->options[2];
1400 hello->hello_interval = htons (oi->hello_interval);
1401 hello->dead_interval = htons (oi->dead_interval);
1402 hello->drouter = oi->drouter;
1403 hello->bdrouter = oi->bdrouter;
1404
Paul Jakma6ac29a52008-08-15 13:45:30 +01001405 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001406
paul1eb8ef22005-04-07 07:30:20 +00001407 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001408 {
hasso508e53e2004-05-18 18:57:06 +00001409 if (on->state < OSPF6_NEIGHBOR_INIT)
1410 continue;
1411
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001412 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001413 {
1414 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001415 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001416 break;
1417 }
1418
1419 memcpy (p, &on->router_id, sizeof (u_int32_t));
1420 p += sizeof (u_int32_t);
1421 }
1422
1423 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1424 oh->length = htons (p - sendbuf);
1425
1426 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1427 return 0;
1428}
1429
1430int
1431ospf6_dbdesc_send (struct thread *thread)
1432{
1433 struct ospf6_neighbor *on;
1434 struct ospf6_header *oh;
1435 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001436 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001437 struct ospf6_lsa *lsa;
1438
1439 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1440 on->thread_send_dbdesc = (struct thread *) NULL;
1441
1442 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1443 {
1444 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001445 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1446 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001447 return 0;
1448 }
1449
1450 /* set next thread if master */
1451 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1452 on->thread_send_dbdesc =
1453 thread_add_timer (master, ospf6_dbdesc_send, on,
1454 on->ospf6_if->rxmt_interval);
1455
hasso3b4cd3a2004-05-18 19:28:32 +00001456 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001457 oh = (struct ospf6_header *) sendbuf;
1458 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1459 sizeof (struct ospf6_header));
1460
1461 /* if this is initial one, initialize sequence number for DbDesc */
1462 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1463 {
1464 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001465 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001466 tv.tv_sec = 1;
1467 on->dbdesc_seqnum = tv.tv_sec;
1468 }
1469
1470 dbdesc->options[0] = on->ospf6_if->area->options[0];
1471 dbdesc->options[1] = on->ospf6_if->area->options[1];
1472 dbdesc->options[2] = on->ospf6_if->area->options[2];
1473 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1474 dbdesc->bits = on->dbdesc_bits;
1475 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1476
1477 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001478 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001479 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1480 {
1481 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1482 lsa = ospf6_lsdb_next (lsa))
1483 {
1484 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1485
1486 /* MTU check */
1487 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001488 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001489 {
1490 ospf6_lsa_unlock (lsa);
1491 break;
1492 }
1493 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1494 p += sizeof (struct ospf6_lsa_header);
1495 }
1496 }
1497
1498 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1499 oh->length = htons (p - sendbuf);
1500
1501 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1502 on->ospf6_if, oh);
1503 return 0;
1504}
1505
1506int
1507ospf6_dbdesc_send_newone (struct thread *thread)
1508{
1509 struct ospf6_neighbor *on;
1510 struct ospf6_lsa *lsa;
1511 unsigned int size = 0;
1512
1513 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001514 ospf6_lsdb_remove_all (on->dbdesc_list);
1515
1516 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1517 so that ospf6_send_dbdesc () can send those LSAs */
1518 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1519 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1520 lsa = ospf6_lsdb_next (lsa))
1521 {
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001522 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001523 {
1524 ospf6_lsa_unlock (lsa);
1525 break;
1526 }
1527
hasso508e53e2004-05-18 18:57:06 +00001528 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1529 ospf6_lsdb_remove (lsa, on->summary_list);
1530 size += sizeof (struct ospf6_lsa_header);
1531 }
1532
1533 if (on->summary_list->count == 0)
1534 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1535
1536 /* If slave, More bit check must be done here */
1537 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1538 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1539 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1540 thread_add_event (master, exchange_done, on, 0);
1541
1542 thread_execute (master, ospf6_dbdesc_send, on, 0);
1543 return 0;
1544}
1545
1546int
1547ospf6_lsreq_send (struct thread *thread)
1548{
1549 struct ospf6_neighbor *on;
1550 struct ospf6_header *oh;
1551 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001552 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001553 struct ospf6_lsa *lsa;
1554
1555 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1556 on->thread_send_lsreq = (struct thread *) NULL;
1557
1558 /* LSReq will be sent only in ExStart or Loading */
1559 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1560 on->state != OSPF6_NEIGHBOR_LOADING)
1561 {
1562 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001563 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1564 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001565 return 0;
1566 }
1567
1568 /* schedule loading_done if request list is empty */
1569 if (on->request_list->count == 0)
1570 {
1571 thread_add_event (master, loading_done, on, 0);
1572 return 0;
1573 }
1574
1575 /* set next thread */
1576 on->thread_send_lsreq =
1577 thread_add_timer (master, ospf6_lsreq_send, on,
1578 on->ospf6_if->rxmt_interval);
1579
hasso3b4cd3a2004-05-18 19:28:32 +00001580 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001581 oh = (struct ospf6_header *) sendbuf;
1582
1583 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001584 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001585 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1586 lsa = ospf6_lsdb_next (lsa))
1587 {
1588 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001589 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001590 {
1591 ospf6_lsa_unlock (lsa);
1592 break;
1593 }
1594
1595 e = (struct ospf6_lsreq_entry *) p;
1596 e->type = lsa->header->type;
1597 e->id = lsa->header->id;
1598 e->adv_router = lsa->header->adv_router;
1599 p += sizeof (struct ospf6_lsreq_entry);
1600 }
1601
1602 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1603 oh->length = htons (p - sendbuf);
1604
1605 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1606 on->ospf6_if, oh);
1607 return 0;
1608}
1609
1610int
1611ospf6_lsupdate_send_neighbor (struct thread *thread)
1612{
1613 struct ospf6_neighbor *on;
1614 struct ospf6_header *oh;
1615 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001616 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001617 int num;
1618 struct ospf6_lsa *lsa;
1619
1620 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1621 on->thread_send_lsupdate = (struct thread *) NULL;
1622
hasso6452df02004-08-15 05:52:07 +00001623 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001624 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001625
hasso508e53e2004-05-18 18:57:06 +00001626 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1627 {
1628 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001629 zlog_debug ("Quit to send (neighbor state %s)",
1630 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001631 return 0;
1632 }
1633
1634 /* if we have nothing to send, return */
1635 if (on->lsupdate_list->count == 0 &&
1636 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001637 {
1638 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001639 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001640 return 0;
1641 }
hasso508e53e2004-05-18 18:57:06 +00001642
hasso3b4cd3a2004-05-18 19:28:32 +00001643 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001644 oh = (struct ospf6_header *) sendbuf;
1645 lsupdate = (struct ospf6_lsupdate *)
1646 ((caddr_t) oh + sizeof (struct ospf6_header));
1647
Paul Jakma6ac29a52008-08-15 13:45:30 +01001648 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001649 num = 0;
1650
1651 /* lsupdate_list lists those LSA which doesn't need to be
1652 retransmitted. remove those from the list */
1653 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1654 lsa = ospf6_lsdb_next (lsa))
1655 {
1656 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001657 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001658 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001659 {
1660 ospf6_lsa_unlock (lsa);
1661 break;
1662 }
1663
hasso508e53e2004-05-18 18:57:06 +00001664 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1665 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1666 p += OSPF6_LSA_SIZE (lsa->header);
1667 num++;
1668
1669 assert (lsa->lock == 2);
1670 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1671 }
1672
1673 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1674 lsa = ospf6_lsdb_next (lsa))
1675 {
1676 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001677 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001678 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001679 {
1680 ospf6_lsa_unlock (lsa);
1681 break;
1682 }
1683
hasso508e53e2004-05-18 18:57:06 +00001684 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1685 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1686 p += OSPF6_LSA_SIZE (lsa->header);
1687 num++;
1688 }
1689
1690 lsupdate->lsa_number = htonl (num);
1691
1692 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1693 oh->length = htons (p - sendbuf);
1694
1695 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1696 on->ospf6_if, oh);
1697
1698 if (on->lsupdate_list->count != 0 ||
1699 on->retrans_list->count != 0)
1700 {
1701 if (on->lsupdate_list->count != 0)
1702 on->thread_send_lsupdate =
1703 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1704 else
1705 on->thread_send_lsupdate =
1706 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1707 on->ospf6_if->rxmt_interval);
1708 }
1709
1710 return 0;
1711}
1712
1713int
1714ospf6_lsupdate_send_interface (struct thread *thread)
1715{
1716 struct ospf6_interface *oi;
1717 struct ospf6_header *oh;
1718 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001719 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001720 int num;
1721 struct ospf6_lsa *lsa;
1722
1723 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1724 oi->thread_send_lsupdate = (struct thread *) NULL;
1725
1726 if (oi->state <= OSPF6_INTERFACE_WAITING)
1727 {
1728 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001729 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
1730 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001731 return 0;
1732 }
1733
1734 /* if we have nothing to send, return */
1735 if (oi->lsupdate_list->count == 0)
1736 return 0;
1737
hasso3b4cd3a2004-05-18 19:28:32 +00001738 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001739 oh = (struct ospf6_header *) sendbuf;
1740 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1741 sizeof (struct ospf6_header));
1742
Paul Jakma6ac29a52008-08-15 13:45:30 +01001743 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001744 num = 0;
1745
1746 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1747 lsa = ospf6_lsdb_next (lsa))
1748 {
1749 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001750 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001751 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001752 {
1753 ospf6_lsa_unlock (lsa);
1754 break;
1755 }
1756
hasso508e53e2004-05-18 18:57:06 +00001757 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1758 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1759 p += OSPF6_LSA_SIZE (lsa->header);
1760 num++;
1761
1762 assert (lsa->lock == 2);
1763 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1764 }
1765
1766 lsupdate->lsa_number = htonl (num);
1767
1768 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1769 oh->length = htons (p - sendbuf);
1770
1771 if (oi->state == OSPF6_INTERFACE_DR ||
1772 oi->state == OSPF6_INTERFACE_BDR)
1773 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1774 else
1775 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1776
1777 if (oi->lsupdate_list->count > 0)
1778 {
1779 oi->thread_send_lsupdate =
1780 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1781 }
1782
1783 return 0;
1784}
1785
1786int
1787ospf6_lsack_send_neighbor (struct thread *thread)
1788{
1789 struct ospf6_neighbor *on;
1790 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001791 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001792 struct ospf6_lsa *lsa;
1793
1794 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1795 on->thread_send_lsack = (struct thread *) NULL;
1796
1797 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1798 {
1799 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001800 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
1801 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001802 return 0;
1803 }
1804
1805 /* if we have nothing to send, return */
1806 if (on->lsack_list->count == 0)
1807 return 0;
1808
hasso3b4cd3a2004-05-18 19:28:32 +00001809 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001810 oh = (struct ospf6_header *) sendbuf;
1811
Paul Jakma6ac29a52008-08-15 13:45:30 +01001812 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001813
1814 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1815 lsa = ospf6_lsdb_next (lsa))
1816 {
1817 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001818 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001819 {
1820 /* if we run out of packet size/space here,
1821 better to try again soon. */
1822 THREAD_OFF (on->thread_send_lsack);
1823 on->thread_send_lsack =
1824 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1825
1826 ospf6_lsa_unlock (lsa);
1827 break;
1828 }
1829
1830 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1831 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1832 p += sizeof (struct ospf6_lsa_header);
1833
1834 assert (lsa->lock == 2);
1835 ospf6_lsdb_remove (lsa, on->lsack_list);
1836 }
1837
1838 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1839 oh->length = htons (p - sendbuf);
1840
1841 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1842 on->ospf6_if, oh);
1843 return 0;
1844}
1845
1846int
1847ospf6_lsack_send_interface (struct thread *thread)
1848{
1849 struct ospf6_interface *oi;
1850 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001851 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001852 struct ospf6_lsa *lsa;
1853
1854 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1855 oi->thread_send_lsack = (struct thread *) NULL;
1856
1857 if (oi->state <= OSPF6_INTERFACE_WAITING)
1858 {
1859 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001860 zlog_debug ("Quit to send LSAck to interface %s state %s",
1861 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001862 return 0;
1863 }
1864
1865 /* if we have nothing to send, return */
1866 if (oi->lsack_list->count == 0)
1867 return 0;
1868
hasso3b4cd3a2004-05-18 19:28:32 +00001869 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001870 oh = (struct ospf6_header *) sendbuf;
1871
Paul Jakma6ac29a52008-08-15 13:45:30 +01001872 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001873
1874 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1875 lsa = ospf6_lsdb_next (lsa))
1876 {
1877 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001878 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001879 {
1880 /* if we run out of packet size/space here,
1881 better to try again soon. */
1882 THREAD_OFF (oi->thread_send_lsack);
1883 oi->thread_send_lsack =
1884 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1885
1886 ospf6_lsa_unlock (lsa);
1887 break;
1888 }
1889
1890 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1891 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1892 p += sizeof (struct ospf6_lsa_header);
1893
1894 assert (lsa->lock == 2);
1895 ospf6_lsdb_remove (lsa, oi->lsack_list);
1896 }
1897
1898 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1899 oh->length = htons (p - sendbuf);
1900
1901 if (oi->state == OSPF6_INTERFACE_DR ||
1902 oi->state == OSPF6_INTERFACE_BDR)
1903 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1904 else
1905 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1906
1907 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1908 {
1909 oi->thread_send_lsack =
1910 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1911 }
paul718e3742002-12-13 20:15:29 +00001912
1913 return 0;
1914}
1915
1916
hasso508e53e2004-05-18 18:57:06 +00001917/* Commands */
1918DEFUN (debug_ospf6_message,
1919 debug_ospf6_message_cmd,
1920 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1921 DEBUG_STR
1922 OSPF6_STR
1923 "Debug OSPFv3 message\n"
1924 "Debug Unknown message\n"
1925 "Debug Hello message\n"
1926 "Debug Database Description message\n"
1927 "Debug Link State Request message\n"
1928 "Debug Link State Update message\n"
1929 "Debug Link State Acknowledgement message\n"
1930 "Debug All message\n"
1931 )
paul718e3742002-12-13 20:15:29 +00001932{
hasso508e53e2004-05-18 18:57:06 +00001933 unsigned char level = 0;
1934 int type = 0;
paul718e3742002-12-13 20:15:29 +00001935 int i;
1936
hasso508e53e2004-05-18 18:57:06 +00001937 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001938
hasso508e53e2004-05-18 18:57:06 +00001939 /* check type */
1940 if (! strncmp (argv[0], "u", 1))
1941 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1942 else if (! strncmp (argv[0], "h", 1))
1943 type = OSPF6_MESSAGE_TYPE_HELLO;
1944 else if (! strncmp (argv[0], "d", 1))
1945 type = OSPF6_MESSAGE_TYPE_DBDESC;
1946 else if (! strncmp (argv[0], "lsr", 3))
1947 type = OSPF6_MESSAGE_TYPE_LSREQ;
1948 else if (! strncmp (argv[0], "lsu", 3))
1949 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1950 else if (! strncmp (argv[0], "lsa", 3))
1951 type = OSPF6_MESSAGE_TYPE_LSACK;
1952 else if (! strncmp (argv[0], "a", 1))
1953 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001954
hasso508e53e2004-05-18 18:57:06 +00001955 if (argc == 1)
1956 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1957 else if (! strncmp (argv[1], "s", 1))
1958 level = OSPF6_DEBUG_MESSAGE_SEND;
1959 else if (! strncmp (argv[1], "r", 1))
1960 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001961
hasso508e53e2004-05-18 18:57:06 +00001962 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001963 {
hasso508e53e2004-05-18 18:57:06 +00001964 for (i = 0; i < 6; i++)
1965 OSPF6_DEBUG_MESSAGE_ON (i, level);
1966 }
1967 else
1968 OSPF6_DEBUG_MESSAGE_ON (type, level);
1969
1970 return CMD_SUCCESS;
1971}
1972
1973ALIAS (debug_ospf6_message,
1974 debug_ospf6_message_sendrecv_cmd,
1975 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1976 DEBUG_STR
1977 OSPF6_STR
1978 "Debug OSPFv3 message\n"
1979 "Debug Unknown message\n"
1980 "Debug Hello message\n"
1981 "Debug Database Description message\n"
1982 "Debug Link State Request message\n"
1983 "Debug Link State Update message\n"
1984 "Debug Link State Acknowledgement message\n"
1985 "Debug All message\n"
1986 "Debug only sending message\n"
1987 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01001988 )
hasso508e53e2004-05-18 18:57:06 +00001989
1990
1991DEFUN (no_debug_ospf6_message,
1992 no_debug_ospf6_message_cmd,
1993 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1994 NO_STR
1995 DEBUG_STR
1996 OSPF6_STR
1997 "Debug OSPFv3 message\n"
1998 "Debug Unknown message\n"
1999 "Debug Hello message\n"
2000 "Debug Database Description message\n"
2001 "Debug Link State Request message\n"
2002 "Debug Link State Update message\n"
2003 "Debug Link State Acknowledgement message\n"
2004 "Debug All message\n"
2005 )
2006{
2007 unsigned char level = 0;
2008 int type = 0;
2009 int i;
2010
2011 assert (argc > 0);
2012
2013 /* check type */
2014 if (! strncmp (argv[0], "u", 1))
2015 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2016 else if (! strncmp (argv[0], "h", 1))
2017 type = OSPF6_MESSAGE_TYPE_HELLO;
2018 else if (! strncmp (argv[0], "d", 1))
2019 type = OSPF6_MESSAGE_TYPE_DBDESC;
2020 else if (! strncmp (argv[0], "lsr", 3))
2021 type = OSPF6_MESSAGE_TYPE_LSREQ;
2022 else if (! strncmp (argv[0], "lsu", 3))
2023 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2024 else if (! strncmp (argv[0], "lsa", 3))
2025 type = OSPF6_MESSAGE_TYPE_LSACK;
2026 else if (! strncmp (argv[0], "a", 1))
2027 type = OSPF6_MESSAGE_TYPE_ALL;
2028
2029 if (argc == 1)
2030 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2031 else if (! strncmp (argv[1], "s", 1))
2032 level = OSPF6_DEBUG_MESSAGE_SEND;
2033 else if (! strncmp (argv[1], "r", 1))
2034 level = OSPF6_DEBUG_MESSAGE_RECV;
2035
2036 if (type == OSPF6_MESSAGE_TYPE_ALL)
2037 {
2038 for (i = 0; i < 6; i++)
2039 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2040 }
2041 else
2042 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2043
2044 return CMD_SUCCESS;
2045}
2046
2047ALIAS (no_debug_ospf6_message,
2048 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002049 "no debug ospf6 message "
2050 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002051 NO_STR
2052 DEBUG_STR
2053 OSPF6_STR
2054 "Debug OSPFv3 message\n"
2055 "Debug Unknown message\n"
2056 "Debug Hello message\n"
2057 "Debug Database Description message\n"
2058 "Debug Link State Request message\n"
2059 "Debug Link State Update message\n"
2060 "Debug Link State Acknowledgement message\n"
2061 "Debug All message\n"
2062 "Debug only sending message\n"
2063 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002064 )
hasso508e53e2004-05-18 18:57:06 +00002065
2066int
2067config_write_ospf6_debug_message (struct vty *vty)
2068{
paul0c083ee2004-10-10 12:54:58 +00002069 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002070 "lsreq", "lsupdate", "lsack"};
2071 unsigned char s = 0, r = 0;
2072 int i;
2073
2074 for (i = 0; i < 6; i++)
2075 {
2076 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2077 s |= 1 << i;
2078 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2079 r |= 1 << i;
2080 }
2081
2082 if (s == 0x3f && r == 0x3f)
2083 {
hasso049207c2004-08-04 20:02:13 +00002084 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002085 return 0;
2086 }
2087
hasso508e53e2004-05-18 18:57:06 +00002088 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002089 {
hasso049207c2004-08-04 20:02:13 +00002090 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002091 return 0;
2092 }
2093 else if (s == 0 && r == 0x3f)
2094 {
hasso049207c2004-08-04 20:02:13 +00002095 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002096 return 0;
paul718e3742002-12-13 20:15:29 +00002097 }
2098
hasso508e53e2004-05-18 18:57:06 +00002099 /* Unknown message is logged by default */
2100 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2101 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002102 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002103 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002104 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002105 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002106 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002107
hasso508e53e2004-05-18 18:57:06 +00002108 for (i = 1; i < 6; i++)
2109 {
2110 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2111 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002112 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002113 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2114 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002115 VNL);
hasso508e53e2004-05-18 18:57:06 +00002116 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2117 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002118 VNL);
hasso508e53e2004-05-18 18:57:06 +00002119 }
paul718e3742002-12-13 20:15:29 +00002120
2121 return 0;
2122}
2123
paul718e3742002-12-13 20:15:29 +00002124void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002125install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002126{
hasso508e53e2004-05-18 18:57:06 +00002127 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2128 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2129 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2130 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2131 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2132 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2133 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2134 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002135}
2136
paul718e3742002-12-13 20:15:29 +00002137