blob: 4db19da757c01f9e6706b0a01d1632fe429cad9a [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 */
230#define MSG_OK 0
231#define MSG_NG 1
232static int
233ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst,
234 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000235{
paul718e3742002-12-13 20:15:29 +0000236 u_char type;
hasso508e53e2004-05-18 18:57:06 +0000237 type = OSPF6_MESSAGE_TYPE_CANONICAL (oh->type);
paul718e3742002-12-13 20:15:29 +0000238
hasso508e53e2004-05-18 18:57:06 +0000239 /* version check */
240 if (oh->version != OSPFV3_VERSION)
paul718e3742002-12-13 20:15:29 +0000241 {
hasso508e53e2004-05-18 18:57:06 +0000242 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000243 zlog_debug ("Message with unknown version");
hasso508e53e2004-05-18 18:57:06 +0000244 return MSG_NG;
paul718e3742002-12-13 20:15:29 +0000245 }
246
hasso508e53e2004-05-18 18:57:06 +0000247 /* Area-ID check */
248 if (oh->area_id != oi->area->area_id)
249 {
hasso6452df02004-08-15 05:52:07 +0000250 if (oh->area_id == BACKBONE_AREA_ID)
hasso508e53e2004-05-18 18:57:06 +0000251 {
252 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000253 zlog_debug ("Message may be via Virtual Link: not supported");
hasso508e53e2004-05-18 18:57:06 +0000254 return MSG_NG;
255 }
256
257 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000258 zlog_debug ("Area-ID mismatch");
hasso508e53e2004-05-18 18:57:06 +0000259 return MSG_NG;
260 }
261
262 /* Instance-ID check */
263 if (oh->instance_id != oi->instance_id)
264 {
265 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000266 zlog_debug ("Instance-ID mismatch");
hasso508e53e2004-05-18 18:57:06 +0000267 return MSG_NG;
268 }
269
270 /* Router-ID check */
271 if (oh->router_id == oi->area->ospf6->router_id)
272 zlog_warn ("Detect duplicate Router-ID");
273
274 return MSG_OK;
275}
276
Paul Jakma6ac29a52008-08-15 13:45:30 +0100277static void
hasso508e53e2004-05-18 18:57:06 +0000278ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
279 struct ospf6_interface *oi, struct ospf6_header *oh)
280{
281 struct ospf6_hello *hello;
282 struct ospf6_neighbor *on;
283 char *p;
284 int twoway = 0;
285 int neighborchange = 0;
286 int backupseen = 0;
287
288 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
289 return;
290
291 hello = (struct ospf6_hello *)
292 ((caddr_t) oh + sizeof (struct ospf6_header));
293
paul718e3742002-12-13 20:15:29 +0000294 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000295 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000296 {
hasso508e53e2004-05-18 18:57:06 +0000297 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000298 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000299 return;
300 }
301
302 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000303 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000304 {
hasso508e53e2004-05-18 18:57:06 +0000305 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000306 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000307 return;
308 }
309
hasso508e53e2004-05-18 18:57:06 +0000310 /* E-bit check */
311 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
312 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000313 {
hasso508e53e2004-05-18 18:57:06 +0000314 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000315 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000316 return;
317 }
318
hasso508e53e2004-05-18 18:57:06 +0000319 /* Find neighbor, create if not exist */
320 on = ospf6_neighbor_lookup (oh->router_id, oi);
321 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000322 {
hasso508e53e2004-05-18 18:57:06 +0000323 on = ospf6_neighbor_create (oh->router_id, oi);
324 on->prev_drouter = on->drouter = hello->drouter;
325 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
326 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000327 }
328
hasso7b6ae022005-06-24 08:17:51 +0000329 /* always override neighbor's source address and ifindex */
330 on->ifindex = ntohl (hello->interface_id);
331 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
332
paul718e3742002-12-13 20:15:29 +0000333 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000334 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
335 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
336 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000337 {
hasso508e53e2004-05-18 18:57:06 +0000338 u_int32_t *router_id = (u_int32_t *) p;
339
340 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000341 twoway++;
paul718e3742002-12-13 20:15:29 +0000342 }
343
hasso508e53e2004-05-18 18:57:06 +0000344 if (p != OSPF6_MESSAGE_END (oh))
345 {
346 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000347 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000348 }
349
350 /* RouterPriority check */
351 if (on->priority != hello->priority)
352 {
353 on->priority = hello->priority;
354 neighborchange++;
355 }
356
357 /* DR check */
358 if (on->drouter != hello->drouter)
359 {
360 on->prev_drouter = on->drouter;
361 on->drouter = hello->drouter;
362 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
363 neighborchange++;
364 }
365
366 /* BDR check */
367 if (on->bdrouter != hello->bdrouter)
368 {
369 on->prev_bdrouter = on->bdrouter;
370 on->bdrouter = hello->bdrouter;
371 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
372 neighborchange++;
373 }
paul718e3742002-12-13 20:15:29 +0000374
375 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000376 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000377 {
hasso508e53e2004-05-18 18:57:06 +0000378 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000379 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000380 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000381 backupseen++;
382 }
383
hasso508e53e2004-05-18 18:57:06 +0000384 /* Execute neighbor events */
385 thread_execute (master, hello_received, on, 0);
386 if (twoway)
387 thread_execute (master, twoway_received, on, 0);
388 else
389 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000390
hasso508e53e2004-05-18 18:57:06 +0000391 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000392 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000393 thread_add_event (master, backup_seen, oi, 0);
394 if (neighborchange)
395 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000396}
397
hasso508e53e2004-05-18 18:57:06 +0000398static void
399ospf6_dbdesc_recv_master (struct ospf6_header *oh,
400 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000401{
paul718e3742002-12-13 20:15:29 +0000402 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000403 char *p;
paul718e3742002-12-13 20:15:29 +0000404
hasso508e53e2004-05-18 18:57:06 +0000405 dbdesc = (struct ospf6_dbdesc *)
406 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000407
hasso508e53e2004-05-18 18:57:06 +0000408 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000409 {
hasso508e53e2004-05-18 18:57:06 +0000410 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000411 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000412 return;
413 }
414
hasso508e53e2004-05-18 18:57:06 +0000415 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000416 {
hasso508e53e2004-05-18 18:57:06 +0000417 case OSPF6_NEIGHBOR_TWOWAY:
418 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000419 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000420 return;
421
422 case OSPF6_NEIGHBOR_INIT:
423 thread_execute (master, twoway_received, on, 0);
424 if (on->state != OSPF6_NEIGHBOR_EXSTART)
425 {
426 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000427 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000428 return;
429 }
430 /* else fall through to ExStart */
431
432 case OSPF6_NEIGHBOR_EXSTART:
433 /* if neighbor obeys us as our slave, schedule negotiation_done
434 and process LSA Headers. Otherwise, ignore this message */
435 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
436 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
437 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
438 {
439 /* execute NegotiationDone */
440 thread_execute (master, negotiation_done, on, 0);
441
442 /* Record neighbor options */
443 memcpy (on->options, dbdesc->options, sizeof (on->options));
444 }
445 else
446 {
447 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000448 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000449 return;
450 }
451 /* fall through to exchange */
452
453 case OSPF6_NEIGHBOR_EXCHANGE:
454 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
455 {
456 /* Duplicated DatabaseDescription is dropped by master */
457 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000458 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000459 return;
460 }
461
462 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
463 {
464 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000465 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000466 thread_add_event (master, seqnumber_mismatch, on, 0);
467 return;
468 }
469
470 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
471 {
472 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000473 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000474 thread_add_event (master, seqnumber_mismatch, on, 0);
475 return;
476 }
477
478 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
479 {
480 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000481 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000482 thread_add_event (master, seqnumber_mismatch, on, 0);
483 return;
484 }
485
486 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
487 {
488 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000489 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000490 (u_long) on->dbdesc_seqnum);
491 thread_add_event (master, seqnumber_mismatch, on, 0);
492 return;
493 }
494 break;
495
496 case OSPF6_NEIGHBOR_LOADING:
497 case OSPF6_NEIGHBOR_FULL:
498 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
499 {
500 /* Duplicated DatabaseDescription is dropped by master */
501 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000502 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000503 return;
504 }
505
506 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000507 zlog_debug ("Not duplicate dbdesc in state %s",
508 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000509 thread_add_event (master, seqnumber_mismatch, on, 0);
510 return;
511
512 default:
513 assert (0);
514 break;
515 }
516
517 /* Process LSA headers */
518 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
519 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
520 p += sizeof (struct ospf6_lsa_header))
521 {
522 struct ospf6_lsa *his, *mine;
523 struct ospf6_lsdb *lsdb = NULL;
524
525 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000526
527 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000528 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000529
530 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000531 {
hasso6452df02004-08-15 05:52:07 +0000532 case OSPF6_SCOPE_LINKLOCAL:
533 lsdb = on->ospf6_if->lsdb;
534 break;
535 case OSPF6_SCOPE_AREA:
536 lsdb = on->ospf6_if->area->lsdb;
537 break;
538 case OSPF6_SCOPE_AS:
539 lsdb = on->ospf6_if->area->ospf6->lsdb;
540 break;
541 case OSPF6_SCOPE_RESERVED:
542 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000543 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000544 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000545 continue;
546 break;
hasso508e53e2004-05-18 18:57:06 +0000547 }
548
549 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000550 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000551 {
552 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000553 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000554 ospf6_lsa_delete (his);
555 thread_add_event (master, seqnumber_mismatch, on, 0);
556 return;
557 }
558
559 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
560 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000561 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000562 {
hasso6452df02004-08-15 05:52:07 +0000563 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000564 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000565 ospf6_lsdb_add (his, on->request_list);
566 }
567 else if (ospf6_lsa_compare (his, mine) < 0)
568 {
569 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000570 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000571 ospf6_lsdb_add (his, on->request_list);
572 }
573 else
hasso6452df02004-08-15 05:52:07 +0000574 {
575 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000576 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000577 ospf6_lsa_delete (his);
578 }
hasso508e53e2004-05-18 18:57:06 +0000579 }
580
581 if (p != OSPF6_MESSAGE_END (oh))
582 {
583 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000584 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000585 }
586
587 /* Increment sequence number */
588 on->dbdesc_seqnum ++;
589
590 /* schedule send lsreq */
591 if (on->thread_send_lsreq == NULL)
592 on->thread_send_lsreq =
593 thread_add_event (master, ospf6_lsreq_send, on, 0);
594
595 THREAD_OFF (on->thread_send_dbdesc);
596
597 /* More bit check */
598 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
599 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
600 thread_add_event (master, exchange_done, on, 0);
601 else
602 on->thread_send_dbdesc =
603 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
604
605 /* save last received dbdesc */
606 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
607}
608
609static void
610ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
611 struct ospf6_neighbor *on)
612{
613 struct ospf6_dbdesc *dbdesc;
614 char *p;
615
616 dbdesc = (struct ospf6_dbdesc *)
617 ((caddr_t) oh + sizeof (struct ospf6_header));
618
619 if (on->state < OSPF6_NEIGHBOR_INIT)
620 {
621 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000622 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000623 return;
624 }
625
hasso508e53e2004-05-18 18:57:06 +0000626 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000627 {
hasso508e53e2004-05-18 18:57:06 +0000628 case OSPF6_NEIGHBOR_TWOWAY:
629 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000630 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000631 return;
632
633 case OSPF6_NEIGHBOR_INIT:
634 thread_execute (master, twoway_received, on, 0);
635 if (on->state != OSPF6_NEIGHBOR_EXSTART)
636 {
637 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000638 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000639 return;
640 }
641 /* else fall through to ExStart */
642
643 case OSPF6_NEIGHBOR_EXSTART:
644 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
645 and process LSA Headers. Otherwise, ignore this message */
646 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
647 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
648 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
649 ntohs (oh->length) == sizeof (struct ospf6_header) +
650 sizeof (struct ospf6_dbdesc))
651 {
652 /* set the master/slave bit to slave */
653 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
654
655 /* set the DD sequence number to one specified by master */
656 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
657
658 /* schedule NegotiationDone */
659 thread_execute (master, negotiation_done, on, 0);
660
661 /* Record neighbor options */
662 memcpy (on->options, dbdesc->options, sizeof (on->options));
663 }
664 else
665 {
666 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000667 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000668 return;
669 }
670 break;
671
672 case OSPF6_NEIGHBOR_EXCHANGE:
673 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
674 {
675 /* Duplicated DatabaseDescription causes slave to retransmit */
676 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000677 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000678 THREAD_OFF (on->thread_send_dbdesc);
679 on->thread_send_dbdesc =
680 thread_add_event (master, ospf6_dbdesc_send, on, 0);
681 return;
682 }
683
684 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
685 {
686 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000687 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000688 thread_add_event (master, seqnumber_mismatch, on, 0);
689 return;
690 }
691
692 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
693 {
694 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000695 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000696 thread_add_event (master, seqnumber_mismatch, on, 0);
697 return;
698 }
699
700 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
701 {
702 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000703 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000704 thread_add_event (master, seqnumber_mismatch, on, 0);
705 return;
706 }
707
708 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
709 {
710 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000711 zlog_debug ("Sequence number mismatch (%#lx expected)",
712 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000713 thread_add_event (master, seqnumber_mismatch, on, 0);
714 return;
715 }
716 break;
717
718 case OSPF6_NEIGHBOR_LOADING:
719 case OSPF6_NEIGHBOR_FULL:
720 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
721 {
722 /* Duplicated DatabaseDescription causes slave to retransmit */
723 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000724 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000725 THREAD_OFF (on->thread_send_dbdesc);
726 on->thread_send_dbdesc =
727 thread_add_event (master, ospf6_dbdesc_send, on, 0);
728 return;
729 }
730
731 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000732 zlog_debug ("Not duplicate dbdesc in state %s",
733 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000734 thread_add_event (master, seqnumber_mismatch, on, 0);
735 return;
736
737 default:
738 assert (0);
739 break;
paul718e3742002-12-13 20:15:29 +0000740 }
741
hasso508e53e2004-05-18 18:57:06 +0000742 /* Process LSA headers */
743 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
744 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
745 p += sizeof (struct ospf6_lsa_header))
746 {
747 struct ospf6_lsa *his, *mine;
748 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000749
hasso508e53e2004-05-18 18:57:06 +0000750 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000751
752 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000753 {
hasso6452df02004-08-15 05:52:07 +0000754 case OSPF6_SCOPE_LINKLOCAL:
755 lsdb = on->ospf6_if->lsdb;
756 break;
757 case OSPF6_SCOPE_AREA:
758 lsdb = on->ospf6_if->area->lsdb;
759 break;
760 case OSPF6_SCOPE_AS:
761 lsdb = on->ospf6_if->area->ospf6->lsdb;
762 break;
763 case OSPF6_SCOPE_RESERVED:
764 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000765 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000766 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000767 continue;
768 break;
hasso508e53e2004-05-18 18:57:06 +0000769 }
770
hasso6452df02004-08-15 05:52:07 +0000771 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
772 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000773 {
774 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000775 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000776 ospf6_lsa_delete (his);
777 thread_add_event (master, seqnumber_mismatch, on, 0);
778 return;
779 }
780
781 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
782 his->header->adv_router, lsdb);
783 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
784 {
hasso6452df02004-08-15 05:52:07 +0000785 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000786 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000787 ospf6_lsdb_add (his, on->request_list);
788 }
789 else
790 ospf6_lsa_delete (his);
791 }
792
793 if (p != OSPF6_MESSAGE_END (oh))
794 {
795 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000796 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000797 }
798
799 /* Set sequence number to Master's */
800 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
801
802 /* schedule send lsreq */
803 if (on->thread_send_lsreq == NULL)
804 on->thread_send_lsreq =
805 thread_add_event (master, ospf6_lsreq_send, on, 0);
806
807 THREAD_OFF (on->thread_send_dbdesc);
808 on->thread_send_dbdesc =
809 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
810
811 /* save last received dbdesc */
812 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000813}
814
Paul Jakma6ac29a52008-08-15 13:45:30 +0100815static void
hasso508e53e2004-05-18 18:57:06 +0000816ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
817 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000818{
hasso508e53e2004-05-18 18:57:06 +0000819 struct ospf6_neighbor *on;
820 struct ospf6_dbdesc *dbdesc;
821
822 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
823 return;
824
825 on = ospf6_neighbor_lookup (oh->router_id, oi);
826 if (on == NULL)
827 {
828 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000829 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000830 return;
831 }
832
hasso508e53e2004-05-18 18:57:06 +0000833 dbdesc = (struct ospf6_dbdesc *)
834 ((caddr_t) oh + sizeof (struct ospf6_header));
835
836 /* Interface MTU check */
Dmitrij Tejblumab1be8a2011-04-22 19:27:54 +0400837 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000838 {
839 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000840 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000841 return;
842 }
843
844 if (dbdesc->reserved1 || dbdesc->reserved2)
845 {
846 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000847 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
848 on->name);
hasso508e53e2004-05-18 18:57:06 +0000849 dbdesc->reserved1 = 0;
850 dbdesc->reserved2 = 0;
851 }
852
853 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
854 ospf6_dbdesc_recv_master (oh, on);
855 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
856 ospf6_dbdesc_recv_slave (oh, on);
857 else
858 {
859 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000860 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000861 }
862}
863
Paul Jakma6ac29a52008-08-15 13:45:30 +0100864static void
hasso508e53e2004-05-18 18:57:06 +0000865ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
866 struct ospf6_interface *oi, struct ospf6_header *oh)
867{
868 struct ospf6_neighbor *on;
869 char *p;
870 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000871 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000872 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000873
hasso508e53e2004-05-18 18:57:06 +0000874 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
875 return;
paul718e3742002-12-13 20:15:29 +0000876
hasso508e53e2004-05-18 18:57:06 +0000877 on = ospf6_neighbor_lookup (oh->router_id, oi);
878 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000879 {
hasso508e53e2004-05-18 18:57:06 +0000880 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000881 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000882 return;
883 }
884
hasso508e53e2004-05-18 18:57:06 +0000885 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
886 on->state != OSPF6_NEIGHBOR_LOADING &&
887 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000888 {
hasso508e53e2004-05-18 18:57:06 +0000889 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000890 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000891 return;
892 }
893
hasso508e53e2004-05-18 18:57:06 +0000894 /* Process each request */
895 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
896 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
897 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000898 {
hasso508e53e2004-05-18 18:57:06 +0000899 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000900
901 switch (OSPF6_LSA_SCOPE (e->type))
902 {
903 case OSPF6_SCOPE_LINKLOCAL:
904 lsdb = on->ospf6_if->lsdb;
905 break;
906 case OSPF6_SCOPE_AREA:
907 lsdb = on->ospf6_if->area->lsdb;
908 break;
909 case OSPF6_SCOPE_AS:
910 lsdb = on->ospf6_if->area->ospf6->lsdb;
911 break;
912 default:
913 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000914 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000915 continue;
916 break;
917 }
paul718e3742002-12-13 20:15:29 +0000918
hasso508e53e2004-05-18 18:57:06 +0000919 /* Find database copy */
920 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
921 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000922 {
hasso508e53e2004-05-18 18:57:06 +0000923 char id[16], adv_router[16];
924 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
925 {
926 inet_ntop (AF_INET, &e->id, id, sizeof (id));
927 inet_ntop (AF_INET, &e->adv_router, adv_router,
928 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000929 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
930 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000931 }
932 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000933 return;
934 }
935
hasso508e53e2004-05-18 18:57:06 +0000936 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000937 }
938
hasso508e53e2004-05-18 18:57:06 +0000939 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000940 {
hasso508e53e2004-05-18 18:57:06 +0000941 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000942 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000943 }
944
hasso508e53e2004-05-18 18:57:06 +0000945 /* schedule send lsupdate */
946 THREAD_OFF (on->thread_send_lsupdate);
947 on->thread_send_lsupdate =
948 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000949}
950
Paul Jakma6ac29a52008-08-15 13:45:30 +0100951static void
hasso508e53e2004-05-18 18:57:06 +0000952ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
953 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000954{
hasso508e53e2004-05-18 18:57:06 +0000955 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +0000956 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000957 unsigned long num;
958 char *p;
paul718e3742002-12-13 20:15:29 +0000959
hasso508e53e2004-05-18 18:57:06 +0000960 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
961 return;
paul718e3742002-12-13 20:15:29 +0000962
hasso508e53e2004-05-18 18:57:06 +0000963 on = ospf6_neighbor_lookup (oh->router_id, oi);
964 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000965 {
hasso508e53e2004-05-18 18:57:06 +0000966 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000967 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000968 return;
969 }
970
hasso508e53e2004-05-18 18:57:06 +0000971 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
972 on->state != OSPF6_NEIGHBOR_LOADING &&
973 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000974 {
hasso508e53e2004-05-18 18:57:06 +0000975 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000976 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000977 return;
978 }
979
hasso508e53e2004-05-18 18:57:06 +0000980 lsupdate = (struct ospf6_lsupdate *)
981 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000982
hasso508e53e2004-05-18 18:57:06 +0000983 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +0000984
hasso508e53e2004-05-18 18:57:06 +0000985 /* Process LSAs */
986 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
987 p < OSPF6_MESSAGE_END (oh) &&
988 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
989 p += OSPF6_LSA_SIZE (p))
990 {
991 if (num == 0)
992 break;
993 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
994 {
995 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000996 zlog_debug ("Malformed LSA length, quit processing");
hasso508e53e2004-05-18 18:57:06 +0000997 break;
998 }
999
hasso6452df02004-08-15 05:52:07 +00001000 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001001 num--;
1002 }
1003
1004 if (num != 0)
1005 {
1006 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001007 zlog_debug ("Malformed LSA number or LSA length");
hasso508e53e2004-05-18 18:57:06 +00001008 }
1009 if (p != OSPF6_MESSAGE_END (oh))
1010 {
1011 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001012 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001013 }
paul718e3742002-12-13 20:15:29 +00001014
1015 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1016 with the proper Link State Update packet(s), the Link state request
1017 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001018 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001019 can be recognized as a response to our previous LS Request */
1020 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1021 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1022 on->state == OSPF6_NEIGHBOR_LOADING))
1023 {
1024 THREAD_OFF (on->thread_send_lsreq);
1025 on->thread_send_lsreq =
1026 thread_add_event (master, ospf6_lsreq_send, on, 0);
1027 }
paul718e3742002-12-13 20:15:29 +00001028}
1029
Paul Jakma6ac29a52008-08-15 13:45:30 +01001030static void
hasso508e53e2004-05-18 18:57:06 +00001031ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1032 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001033{
hasso508e53e2004-05-18 18:57:06 +00001034 struct ospf6_neighbor *on;
1035 char *p;
1036 struct ospf6_lsa *his, *mine;
1037 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001038
hasso508e53e2004-05-18 18:57:06 +00001039 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1040 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
1041 return;
paul718e3742002-12-13 20:15:29 +00001042
hasso508e53e2004-05-18 18:57:06 +00001043 on = ospf6_neighbor_lookup (oh->router_id, oi);
1044 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001045 {
hasso508e53e2004-05-18 18:57:06 +00001046 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001047 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001048 return;
1049 }
1050
hasso508e53e2004-05-18 18:57:06 +00001051 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1052 on->state != OSPF6_NEIGHBOR_LOADING &&
1053 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001054 {
hasso508e53e2004-05-18 18:57:06 +00001055 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001056 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001057 return;
1058 }
1059
hasso508e53e2004-05-18 18:57:06 +00001060 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1061 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1062 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001063 {
hasso508e53e2004-05-18 18:57:06 +00001064 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001065
hasso6452df02004-08-15 05:52:07 +00001066 switch (OSPF6_LSA_SCOPE (his->header->type))
1067 {
1068 case OSPF6_SCOPE_LINKLOCAL:
1069 lsdb = on->ospf6_if->lsdb;
1070 break;
1071 case OSPF6_SCOPE_AREA:
1072 lsdb = on->ospf6_if->area->lsdb;
1073 break;
1074 case OSPF6_SCOPE_AS:
1075 lsdb = on->ospf6_if->area->ospf6->lsdb;
1076 break;
1077 case OSPF6_SCOPE_RESERVED:
1078 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001079 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001080 ospf6_lsa_delete (his);
1081 continue;
1082 break;
1083 }
1084
1085 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001086 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001087
1088 /* Find database copy */
1089 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1090 his->header->adv_router, lsdb);
1091 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001092 {
hasso508e53e2004-05-18 18:57:06 +00001093 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001094 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001095 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001096 continue;
1097 }
1098
hasso508e53e2004-05-18 18:57:06 +00001099 /* Check if the LSA is on his retrans-list */
1100 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1101 his->header->adv_router, on->retrans_list);
1102 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001103 {
hasso508e53e2004-05-18 18:57:06 +00001104 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001105 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001106 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001107 continue;
1108 }
1109
hasso508e53e2004-05-18 18:57:06 +00001110 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001111 {
hasso508e53e2004-05-18 18:57:06 +00001112 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001113 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001114 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001115 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001116 ospf6_lsa_delete (his);
1117 continue;
paul718e3742002-12-13 20:15:29 +00001118 }
1119
hasso6452df02004-08-15 05:52:07 +00001120 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001121 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1122 on->name);
hasso508e53e2004-05-18 18:57:06 +00001123
Paul Jakma932bf192006-05-15 10:42:24 +00001124 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001125 if (OSPF6_LSA_IS_MAXAGE (mine))
1126 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001127 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001128 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001129 }
1130
hasso508e53e2004-05-18 18:57:06 +00001131 if (p != OSPF6_MESSAGE_END (oh))
1132 {
1133 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001134 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001135 }
paul718e3742002-12-13 20:15:29 +00001136}
1137
Paul Jakma6ac29a52008-08-15 13:45:30 +01001138static u_char *recvbuf = NULL;
1139static u_char *sendbuf = NULL;
1140static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001141
1142int
paul0c083ee2004-10-10 12:54:58 +00001143ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001144{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001145 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001146
1147 if (size <= iobuflen)
1148 return iobuflen;
1149
1150 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1151 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1152 if (recvnew == NULL || sendnew == NULL)
1153 {
hassob596c712004-07-09 18:33:43 +00001154 if (recvnew)
1155 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1156 if (sendnew)
1157 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001158 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001159 return iobuflen;
1160 }
1161
1162 if (recvbuf)
1163 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1164 if (sendbuf)
1165 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1166 recvbuf = recvnew;
1167 sendbuf = sendnew;
1168 iobuflen = size;
1169
1170 return iobuflen;
1171}
paul718e3742002-12-13 20:15:29 +00001172
1173int
1174ospf6_receive (struct thread *thread)
1175{
paul0c083ee2004-10-10 12:54:58 +00001176 int sockfd;
1177 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001178 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001179 struct in6_addr src, dst;
1180 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001181 struct iovec iovector[2];
1182 struct ospf6_interface *oi;
1183 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001184
1185 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001186 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001187 thread_add_read (master, ospf6_receive, NULL, sockfd);
1188
1189 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001190 memset (&src, 0, sizeof (src));
1191 memset (&dst, 0, sizeof (dst));
1192 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001193 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001194 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001195 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001196 iovector[1].iov_base = NULL;
1197 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001198
1199 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001200 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001201 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001202 {
hasso508e53e2004-05-18 18:57:06 +00001203 zlog_err ("Excess message read");
1204 return 0;
1205 }
1206 else if (len < sizeof (struct ospf6_header))
1207 {
1208 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001209 return 0;
1210 }
1211
hasso508e53e2004-05-18 18:57:06 +00001212 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1213 if (oi == NULL || oi->area == NULL)
1214 {
hassoc6487d62004-12-24 06:00:11 +00001215 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001216 return 0;
1217 }
1218
1219 oh = (struct ospf6_header *) recvbuf;
1220
1221 /* Log */
1222 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1223 {
1224 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1225 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001226 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001227 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001228 zlog_debug (" src: %s", srcname);
1229 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001230 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001231 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001232
1233 switch (oh->type)
1234 {
1235 case OSPF6_MESSAGE_TYPE_HELLO:
1236 ospf6_hello_print (oh);
1237 break;
1238 case OSPF6_MESSAGE_TYPE_DBDESC:
1239 ospf6_dbdesc_print (oh);
1240 break;
1241 case OSPF6_MESSAGE_TYPE_LSREQ:
1242 ospf6_lsreq_print (oh);
1243 break;
1244 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1245 ospf6_lsupdate_print (oh);
1246 break;
1247 case OSPF6_MESSAGE_TYPE_LSACK:
1248 ospf6_lsack_print (oh);
1249 break;
1250 default:
hassoc6487d62004-12-24 06:00:11 +00001251 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001252 break;
1253 }
1254 }
1255
1256 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1257 {
1258 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001259 zlog_debug ("Ignore message on passive interface %s",
hasso508e53e2004-05-18 18:57:06 +00001260 oi->interface->name);
1261 return 0;
1262 }
1263
1264 switch (oh->type)
1265 {
1266 case OSPF6_MESSAGE_TYPE_HELLO:
1267 ospf6_hello_recv (&src, &dst, oi, oh);
1268 break;
1269
1270 case OSPF6_MESSAGE_TYPE_DBDESC:
1271 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1272 break;
1273
1274 case OSPF6_MESSAGE_TYPE_LSREQ:
1275 ospf6_lsreq_recv (&src, &dst, oi, oh);
1276 break;
1277
1278 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1279 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1280 break;
1281
1282 case OSPF6_MESSAGE_TYPE_LSACK:
1283 ospf6_lsack_recv (&src, &dst, oi, oh);
1284 break;
1285
1286 default:
1287 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001288 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001289 break;
1290 }
1291
1292 return 0;
1293}
1294
Paul Jakma6ac29a52008-08-15 13:45:30 +01001295static void
hasso508e53e2004-05-18 18:57:06 +00001296ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1297 struct ospf6_interface *oi, struct ospf6_header *oh)
1298{
1299 int len;
1300 char srcname[64], dstname[64];
1301 struct iovec iovector[2];
1302
1303 /* initialize */
1304 iovector[0].iov_base = (caddr_t) oh;
1305 iovector[0].iov_len = ntohs (oh->length);
1306 iovector[1].iov_base = NULL;
1307 iovector[1].iov_len = 0;
1308
1309 /* fill OSPF header */
1310 oh->version = OSPFV3_VERSION;
1311 /* message type must be set before */
1312 /* message length must be set before */
1313 oh->router_id = oi->area->ospf6->router_id;
1314 oh->area_id = oi->area->area_id;
1315 /* checksum is calculated by kernel */
1316 oh->instance_id = oi->instance_id;
1317 oh->reserved = 0;
1318
1319 /* Log */
1320 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1321 {
1322 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1323 if (src)
1324 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1325 else
1326 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001327 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001328 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001329 zlog_debug (" src: %s", srcname);
1330 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001331
1332 switch (oh->type)
1333 {
1334 case OSPF6_MESSAGE_TYPE_HELLO:
1335 ospf6_hello_print (oh);
1336 break;
1337 case OSPF6_MESSAGE_TYPE_DBDESC:
1338 ospf6_dbdesc_print (oh);
1339 break;
1340 case OSPF6_MESSAGE_TYPE_LSREQ:
1341 ospf6_lsreq_print (oh);
1342 break;
1343 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1344 ospf6_lsupdate_print (oh);
1345 break;
1346 case OSPF6_MESSAGE_TYPE_LSACK:
1347 ospf6_lsack_print (oh);
1348 break;
1349 default:
hassoc6487d62004-12-24 06:00:11 +00001350 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001351 assert (0);
1352 break;
1353 }
1354 }
1355
1356 /* send message */
1357 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1358 if (len != ntohs (oh->length))
1359 zlog_err ("Could not send entire message");
1360}
1361
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001362static int
1363ospf6_packet_max(struct ospf6_interface *oi)
1364{
1365 return oi->ifmtu - sizeof(struct ip6_hdr);
1366}
1367
hasso508e53e2004-05-18 18:57:06 +00001368int
1369ospf6_hello_send (struct thread *thread)
1370{
1371 struct ospf6_interface *oi;
1372 struct ospf6_header *oh;
1373 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001374 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001375 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001376 struct ospf6_neighbor *on;
1377
1378 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1379 oi->thread_send_hello = (struct thread *) NULL;
1380
1381 if (oi->state <= OSPF6_INTERFACE_DOWN)
1382 {
1383 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001384 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001385 oi->interface->name);
1386 return 0;
1387 }
1388
1389 /* set next thread */
1390 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1391 oi, oi->hello_interval);
1392
hasso3b4cd3a2004-05-18 19:28:32 +00001393 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001394 oh = (struct ospf6_header *) sendbuf;
1395 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1396
1397 hello->interface_id = htonl (oi->interface->ifindex);
1398 hello->priority = oi->priority;
1399 hello->options[0] = oi->area->options[0];
1400 hello->options[1] = oi->area->options[1];
1401 hello->options[2] = oi->area->options[2];
1402 hello->hello_interval = htons (oi->hello_interval);
1403 hello->dead_interval = htons (oi->dead_interval);
1404 hello->drouter = oi->drouter;
1405 hello->bdrouter = oi->bdrouter;
1406
Paul Jakma6ac29a52008-08-15 13:45:30 +01001407 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001408
paul1eb8ef22005-04-07 07:30:20 +00001409 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001410 {
hasso508e53e2004-05-18 18:57:06 +00001411 if (on->state < OSPF6_NEIGHBOR_INIT)
1412 continue;
1413
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001414 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001415 {
1416 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001417 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001418 break;
1419 }
1420
1421 memcpy (p, &on->router_id, sizeof (u_int32_t));
1422 p += sizeof (u_int32_t);
1423 }
1424
1425 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1426 oh->length = htons (p - sendbuf);
1427
1428 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1429 return 0;
1430}
1431
1432int
1433ospf6_dbdesc_send (struct thread *thread)
1434{
1435 struct ospf6_neighbor *on;
1436 struct ospf6_header *oh;
1437 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001438 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001439 struct ospf6_lsa *lsa;
1440
1441 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1442 on->thread_send_dbdesc = (struct thread *) NULL;
1443
1444 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1445 {
1446 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001447 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1448 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001449 return 0;
1450 }
1451
1452 /* set next thread if master */
1453 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1454 on->thread_send_dbdesc =
1455 thread_add_timer (master, ospf6_dbdesc_send, on,
1456 on->ospf6_if->rxmt_interval);
1457
hasso3b4cd3a2004-05-18 19:28:32 +00001458 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001459 oh = (struct ospf6_header *) sendbuf;
1460 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1461 sizeof (struct ospf6_header));
1462
1463 /* if this is initial one, initialize sequence number for DbDesc */
1464 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1465 {
1466 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001467 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001468 tv.tv_sec = 1;
1469 on->dbdesc_seqnum = tv.tv_sec;
1470 }
1471
1472 dbdesc->options[0] = on->ospf6_if->area->options[0];
1473 dbdesc->options[1] = on->ospf6_if->area->options[1];
1474 dbdesc->options[2] = on->ospf6_if->area->options[2];
1475 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1476 dbdesc->bits = on->dbdesc_bits;
1477 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1478
1479 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001480 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001481 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1482 {
1483 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1484 lsa = ospf6_lsdb_next (lsa))
1485 {
1486 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1487
1488 /* MTU check */
1489 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001490 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001491 {
1492 ospf6_lsa_unlock (lsa);
1493 break;
1494 }
1495 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1496 p += sizeof (struct ospf6_lsa_header);
1497 }
1498 }
1499
1500 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1501 oh->length = htons (p - sendbuf);
1502
1503 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1504 on->ospf6_if, oh);
1505 return 0;
1506}
1507
1508int
1509ospf6_dbdesc_send_newone (struct thread *thread)
1510{
1511 struct ospf6_neighbor *on;
1512 struct ospf6_lsa *lsa;
1513 unsigned int size = 0;
1514
1515 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001516 ospf6_lsdb_remove_all (on->dbdesc_list);
1517
1518 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1519 so that ospf6_send_dbdesc () can send those LSAs */
1520 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1521 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1522 lsa = ospf6_lsdb_next (lsa))
1523 {
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001524 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001525 {
1526 ospf6_lsa_unlock (lsa);
1527 break;
1528 }
1529
hasso508e53e2004-05-18 18:57:06 +00001530 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1531 ospf6_lsdb_remove (lsa, on->summary_list);
1532 size += sizeof (struct ospf6_lsa_header);
1533 }
1534
1535 if (on->summary_list->count == 0)
1536 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1537
1538 /* If slave, More bit check must be done here */
1539 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1540 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1541 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1542 thread_add_event (master, exchange_done, on, 0);
1543
1544 thread_execute (master, ospf6_dbdesc_send, on, 0);
1545 return 0;
1546}
1547
1548int
1549ospf6_lsreq_send (struct thread *thread)
1550{
1551 struct ospf6_neighbor *on;
1552 struct ospf6_header *oh;
1553 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001554 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001555 struct ospf6_lsa *lsa;
1556
1557 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1558 on->thread_send_lsreq = (struct thread *) NULL;
1559
1560 /* LSReq will be sent only in ExStart or Loading */
1561 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1562 on->state != OSPF6_NEIGHBOR_LOADING)
1563 {
1564 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001565 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1566 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001567 return 0;
1568 }
1569
1570 /* schedule loading_done if request list is empty */
1571 if (on->request_list->count == 0)
1572 {
1573 thread_add_event (master, loading_done, on, 0);
1574 return 0;
1575 }
1576
1577 /* set next thread */
1578 on->thread_send_lsreq =
1579 thread_add_timer (master, ospf6_lsreq_send, on,
1580 on->ospf6_if->rxmt_interval);
1581
hasso3b4cd3a2004-05-18 19:28:32 +00001582 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001583 oh = (struct ospf6_header *) sendbuf;
1584
1585 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001586 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001587 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1588 lsa = ospf6_lsdb_next (lsa))
1589 {
1590 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001591 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001592 {
1593 ospf6_lsa_unlock (lsa);
1594 break;
1595 }
1596
1597 e = (struct ospf6_lsreq_entry *) p;
1598 e->type = lsa->header->type;
1599 e->id = lsa->header->id;
1600 e->adv_router = lsa->header->adv_router;
1601 p += sizeof (struct ospf6_lsreq_entry);
1602 }
1603
1604 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1605 oh->length = htons (p - sendbuf);
1606
1607 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1608 on->ospf6_if, oh);
1609 return 0;
1610}
1611
1612int
1613ospf6_lsupdate_send_neighbor (struct thread *thread)
1614{
1615 struct ospf6_neighbor *on;
1616 struct ospf6_header *oh;
1617 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001618 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001619 int num;
1620 struct ospf6_lsa *lsa;
1621
1622 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1623 on->thread_send_lsupdate = (struct thread *) NULL;
1624
hasso6452df02004-08-15 05:52:07 +00001625 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001626 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001627
hasso508e53e2004-05-18 18:57:06 +00001628 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1629 {
1630 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001631 zlog_debug ("Quit to send (neighbor state %s)",
1632 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001633 return 0;
1634 }
1635
1636 /* if we have nothing to send, return */
1637 if (on->lsupdate_list->count == 0 &&
1638 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001639 {
1640 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001641 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001642 return 0;
1643 }
hasso508e53e2004-05-18 18:57:06 +00001644
hasso3b4cd3a2004-05-18 19:28:32 +00001645 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001646 oh = (struct ospf6_header *) sendbuf;
1647 lsupdate = (struct ospf6_lsupdate *)
1648 ((caddr_t) oh + sizeof (struct ospf6_header));
1649
Paul Jakma6ac29a52008-08-15 13:45:30 +01001650 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001651 num = 0;
1652
1653 /* lsupdate_list lists those LSA which doesn't need to be
1654 retransmitted. remove those from the list */
1655 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1656 lsa = ospf6_lsdb_next (lsa))
1657 {
1658 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001659 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001660 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001661 {
1662 ospf6_lsa_unlock (lsa);
1663 break;
1664 }
1665
hasso508e53e2004-05-18 18:57:06 +00001666 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1667 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1668 p += OSPF6_LSA_SIZE (lsa->header);
1669 num++;
1670
1671 assert (lsa->lock == 2);
1672 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1673 }
1674
1675 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1676 lsa = ospf6_lsdb_next (lsa))
1677 {
1678 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001679 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001680 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001681 {
1682 ospf6_lsa_unlock (lsa);
1683 break;
1684 }
1685
hasso508e53e2004-05-18 18:57:06 +00001686 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1687 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1688 p += OSPF6_LSA_SIZE (lsa->header);
1689 num++;
1690 }
1691
1692 lsupdate->lsa_number = htonl (num);
1693
1694 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1695 oh->length = htons (p - sendbuf);
1696
1697 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1698 on->ospf6_if, oh);
1699
1700 if (on->lsupdate_list->count != 0 ||
1701 on->retrans_list->count != 0)
1702 {
1703 if (on->lsupdate_list->count != 0)
1704 on->thread_send_lsupdate =
1705 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1706 else
1707 on->thread_send_lsupdate =
1708 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1709 on->ospf6_if->rxmt_interval);
1710 }
1711
1712 return 0;
1713}
1714
1715int
1716ospf6_lsupdate_send_interface (struct thread *thread)
1717{
1718 struct ospf6_interface *oi;
1719 struct ospf6_header *oh;
1720 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001721 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001722 int num;
1723 struct ospf6_lsa *lsa;
1724
1725 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1726 oi->thread_send_lsupdate = (struct thread *) NULL;
1727
1728 if (oi->state <= OSPF6_INTERFACE_WAITING)
1729 {
1730 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001731 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
1732 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001733 return 0;
1734 }
1735
1736 /* if we have nothing to send, return */
1737 if (oi->lsupdate_list->count == 0)
1738 return 0;
1739
hasso3b4cd3a2004-05-18 19:28:32 +00001740 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001741 oh = (struct ospf6_header *) sendbuf;
1742 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1743 sizeof (struct ospf6_header));
1744
Paul Jakma6ac29a52008-08-15 13:45:30 +01001745 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001746 num = 0;
1747
1748 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1749 lsa = ospf6_lsdb_next (lsa))
1750 {
1751 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001752 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001753 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001754 {
1755 ospf6_lsa_unlock (lsa);
1756 break;
1757 }
1758
hasso508e53e2004-05-18 18:57:06 +00001759 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1760 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1761 p += OSPF6_LSA_SIZE (lsa->header);
1762 num++;
1763
1764 assert (lsa->lock == 2);
1765 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1766 }
1767
1768 lsupdate->lsa_number = htonl (num);
1769
1770 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1771 oh->length = htons (p - sendbuf);
1772
1773 if (oi->state == OSPF6_INTERFACE_DR ||
1774 oi->state == OSPF6_INTERFACE_BDR)
1775 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1776 else
1777 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1778
1779 if (oi->lsupdate_list->count > 0)
1780 {
1781 oi->thread_send_lsupdate =
1782 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1783 }
1784
1785 return 0;
1786}
1787
1788int
1789ospf6_lsack_send_neighbor (struct thread *thread)
1790{
1791 struct ospf6_neighbor *on;
1792 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001793 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001794 struct ospf6_lsa *lsa;
1795
1796 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1797 on->thread_send_lsack = (struct thread *) NULL;
1798
1799 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1800 {
1801 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001802 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
1803 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001804 return 0;
1805 }
1806
1807 /* if we have nothing to send, return */
1808 if (on->lsack_list->count == 0)
1809 return 0;
1810
hasso3b4cd3a2004-05-18 19:28:32 +00001811 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001812 oh = (struct ospf6_header *) sendbuf;
1813
Paul Jakma6ac29a52008-08-15 13:45:30 +01001814 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001815
1816 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1817 lsa = ospf6_lsdb_next (lsa))
1818 {
1819 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001820 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001821 {
1822 /* if we run out of packet size/space here,
1823 better to try again soon. */
1824 THREAD_OFF (on->thread_send_lsack);
1825 on->thread_send_lsack =
1826 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1827
1828 ospf6_lsa_unlock (lsa);
1829 break;
1830 }
1831
1832 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1833 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1834 p += sizeof (struct ospf6_lsa_header);
1835
1836 assert (lsa->lock == 2);
1837 ospf6_lsdb_remove (lsa, on->lsack_list);
1838 }
1839
1840 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1841 oh->length = htons (p - sendbuf);
1842
1843 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1844 on->ospf6_if, oh);
1845 return 0;
1846}
1847
1848int
1849ospf6_lsack_send_interface (struct thread *thread)
1850{
1851 struct ospf6_interface *oi;
1852 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001853 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001854 struct ospf6_lsa *lsa;
1855
1856 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1857 oi->thread_send_lsack = (struct thread *) NULL;
1858
1859 if (oi->state <= OSPF6_INTERFACE_WAITING)
1860 {
1861 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001862 zlog_debug ("Quit to send LSAck to interface %s state %s",
1863 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001864 return 0;
1865 }
1866
1867 /* if we have nothing to send, return */
1868 if (oi->lsack_list->count == 0)
1869 return 0;
1870
hasso3b4cd3a2004-05-18 19:28:32 +00001871 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001872 oh = (struct ospf6_header *) sendbuf;
1873
Paul Jakma6ac29a52008-08-15 13:45:30 +01001874 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001875
1876 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1877 lsa = ospf6_lsdb_next (lsa))
1878 {
1879 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001880 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001881 {
1882 /* if we run out of packet size/space here,
1883 better to try again soon. */
1884 THREAD_OFF (oi->thread_send_lsack);
1885 oi->thread_send_lsack =
1886 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1887
1888 ospf6_lsa_unlock (lsa);
1889 break;
1890 }
1891
1892 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1893 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1894 p += sizeof (struct ospf6_lsa_header);
1895
1896 assert (lsa->lock == 2);
1897 ospf6_lsdb_remove (lsa, oi->lsack_list);
1898 }
1899
1900 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1901 oh->length = htons (p - sendbuf);
1902
1903 if (oi->state == OSPF6_INTERFACE_DR ||
1904 oi->state == OSPF6_INTERFACE_BDR)
1905 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1906 else
1907 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1908
1909 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1910 {
1911 oi->thread_send_lsack =
1912 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1913 }
paul718e3742002-12-13 20:15:29 +00001914
1915 return 0;
1916}
1917
1918
hasso508e53e2004-05-18 18:57:06 +00001919/* Commands */
1920DEFUN (debug_ospf6_message,
1921 debug_ospf6_message_cmd,
1922 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1923 DEBUG_STR
1924 OSPF6_STR
1925 "Debug OSPFv3 message\n"
1926 "Debug Unknown message\n"
1927 "Debug Hello message\n"
1928 "Debug Database Description message\n"
1929 "Debug Link State Request message\n"
1930 "Debug Link State Update message\n"
1931 "Debug Link State Acknowledgement message\n"
1932 "Debug All message\n"
1933 )
paul718e3742002-12-13 20:15:29 +00001934{
hasso508e53e2004-05-18 18:57:06 +00001935 unsigned char level = 0;
1936 int type = 0;
paul718e3742002-12-13 20:15:29 +00001937 int i;
1938
hasso508e53e2004-05-18 18:57:06 +00001939 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001940
hasso508e53e2004-05-18 18:57:06 +00001941 /* check type */
1942 if (! strncmp (argv[0], "u", 1))
1943 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1944 else if (! strncmp (argv[0], "h", 1))
1945 type = OSPF6_MESSAGE_TYPE_HELLO;
1946 else if (! strncmp (argv[0], "d", 1))
1947 type = OSPF6_MESSAGE_TYPE_DBDESC;
1948 else if (! strncmp (argv[0], "lsr", 3))
1949 type = OSPF6_MESSAGE_TYPE_LSREQ;
1950 else if (! strncmp (argv[0], "lsu", 3))
1951 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1952 else if (! strncmp (argv[0], "lsa", 3))
1953 type = OSPF6_MESSAGE_TYPE_LSACK;
1954 else if (! strncmp (argv[0], "a", 1))
1955 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001956
hasso508e53e2004-05-18 18:57:06 +00001957 if (argc == 1)
1958 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1959 else if (! strncmp (argv[1], "s", 1))
1960 level = OSPF6_DEBUG_MESSAGE_SEND;
1961 else if (! strncmp (argv[1], "r", 1))
1962 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001963
hasso508e53e2004-05-18 18:57:06 +00001964 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001965 {
hasso508e53e2004-05-18 18:57:06 +00001966 for (i = 0; i < 6; i++)
1967 OSPF6_DEBUG_MESSAGE_ON (i, level);
1968 }
1969 else
1970 OSPF6_DEBUG_MESSAGE_ON (type, level);
1971
1972 return CMD_SUCCESS;
1973}
1974
1975ALIAS (debug_ospf6_message,
1976 debug_ospf6_message_sendrecv_cmd,
1977 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1978 DEBUG_STR
1979 OSPF6_STR
1980 "Debug OSPFv3 message\n"
1981 "Debug Unknown message\n"
1982 "Debug Hello message\n"
1983 "Debug Database Description message\n"
1984 "Debug Link State Request message\n"
1985 "Debug Link State Update message\n"
1986 "Debug Link State Acknowledgement message\n"
1987 "Debug All message\n"
1988 "Debug only sending message\n"
1989 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01001990 )
hasso508e53e2004-05-18 18:57:06 +00001991
1992
1993DEFUN (no_debug_ospf6_message,
1994 no_debug_ospf6_message_cmd,
1995 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1996 NO_STR
1997 DEBUG_STR
1998 OSPF6_STR
1999 "Debug OSPFv3 message\n"
2000 "Debug Unknown message\n"
2001 "Debug Hello message\n"
2002 "Debug Database Description message\n"
2003 "Debug Link State Request message\n"
2004 "Debug Link State Update message\n"
2005 "Debug Link State Acknowledgement message\n"
2006 "Debug All message\n"
2007 )
2008{
2009 unsigned char level = 0;
2010 int type = 0;
2011 int i;
2012
2013 assert (argc > 0);
2014
2015 /* check type */
2016 if (! strncmp (argv[0], "u", 1))
2017 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2018 else if (! strncmp (argv[0], "h", 1))
2019 type = OSPF6_MESSAGE_TYPE_HELLO;
2020 else if (! strncmp (argv[0], "d", 1))
2021 type = OSPF6_MESSAGE_TYPE_DBDESC;
2022 else if (! strncmp (argv[0], "lsr", 3))
2023 type = OSPF6_MESSAGE_TYPE_LSREQ;
2024 else if (! strncmp (argv[0], "lsu", 3))
2025 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2026 else if (! strncmp (argv[0], "lsa", 3))
2027 type = OSPF6_MESSAGE_TYPE_LSACK;
2028 else if (! strncmp (argv[0], "a", 1))
2029 type = OSPF6_MESSAGE_TYPE_ALL;
2030
2031 if (argc == 1)
2032 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2033 else if (! strncmp (argv[1], "s", 1))
2034 level = OSPF6_DEBUG_MESSAGE_SEND;
2035 else if (! strncmp (argv[1], "r", 1))
2036 level = OSPF6_DEBUG_MESSAGE_RECV;
2037
2038 if (type == OSPF6_MESSAGE_TYPE_ALL)
2039 {
2040 for (i = 0; i < 6; i++)
2041 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2042 }
2043 else
2044 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2045
2046 return CMD_SUCCESS;
2047}
2048
2049ALIAS (no_debug_ospf6_message,
2050 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002051 "no debug ospf6 message "
2052 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002053 NO_STR
2054 DEBUG_STR
2055 OSPF6_STR
2056 "Debug OSPFv3 message\n"
2057 "Debug Unknown message\n"
2058 "Debug Hello message\n"
2059 "Debug Database Description message\n"
2060 "Debug Link State Request message\n"
2061 "Debug Link State Update message\n"
2062 "Debug Link State Acknowledgement message\n"
2063 "Debug All message\n"
2064 "Debug only sending message\n"
2065 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002066 )
hasso508e53e2004-05-18 18:57:06 +00002067
2068int
2069config_write_ospf6_debug_message (struct vty *vty)
2070{
paul0c083ee2004-10-10 12:54:58 +00002071 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002072 "lsreq", "lsupdate", "lsack"};
2073 unsigned char s = 0, r = 0;
2074 int i;
2075
2076 for (i = 0; i < 6; i++)
2077 {
2078 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2079 s |= 1 << i;
2080 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2081 r |= 1 << i;
2082 }
2083
2084 if (s == 0x3f && r == 0x3f)
2085 {
hasso049207c2004-08-04 20:02:13 +00002086 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002087 return 0;
2088 }
2089
hasso508e53e2004-05-18 18:57:06 +00002090 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002091 {
hasso049207c2004-08-04 20:02:13 +00002092 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002093 return 0;
2094 }
2095 else if (s == 0 && r == 0x3f)
2096 {
hasso049207c2004-08-04 20:02:13 +00002097 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002098 return 0;
paul718e3742002-12-13 20:15:29 +00002099 }
2100
hasso508e53e2004-05-18 18:57:06 +00002101 /* Unknown message is logged by default */
2102 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2103 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002104 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002105 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002106 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002107 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002108 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002109
hasso508e53e2004-05-18 18:57:06 +00002110 for (i = 1; i < 6; i++)
2111 {
2112 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2113 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002114 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002115 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2116 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002117 VNL);
hasso508e53e2004-05-18 18:57:06 +00002118 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2119 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002120 VNL);
hasso508e53e2004-05-18 18:57:06 +00002121 }
paul718e3742002-12-13 20:15:29 +00002122
2123 return 0;
2124}
2125
paul718e3742002-12-13 20:15:29 +00002126void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002127install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002128{
hasso508e53e2004-05-18 18:57:06 +00002129 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2130 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2131 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2132 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2133 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2134 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2135 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2136 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002137}
2138
paul718e3742002-12-13 20:15:29 +00002139