blob: d06eba26b193e375052fc44bee9ea31645dbde49 [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
45unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
paul0c083ee2004-10-10 12:54:58 +000046const char *ospf6_message_type_str[] =
hasso508e53e2004-05-18 18:57:06 +000047 { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
48
49/* print functions */
50
51static void
52ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000053{
hasso508e53e2004-05-18 18:57:06 +000054 char router_id[16], area_id[16];
55 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
56 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000057
hassoc6487d62004-12-24 06:00:11 +000058 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +000059 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +000060 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +000061 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +000062}
paul718e3742002-12-13 20:15:29 +000063
64void
hasso508e53e2004-05-18 18:57:06 +000065ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000066{
paul718e3742002-12-13 20:15:29 +000067 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +000068 char options[16];
69 char drouter[16], bdrouter[16], neighbor[16];
70 char *p;
paul718e3742002-12-13 20:15:29 +000071
hasso508e53e2004-05-18 18:57:06 +000072 ospf6_header_print (oh);
73 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +000074
hasso508e53e2004-05-18 18:57:06 +000075 hello = (struct ospf6_hello *)
76 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +000077
hasso508e53e2004-05-18 18:57:06 +000078 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
79 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
80 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +000081
hassoc6487d62004-12-24 06:00:11 +000082 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +000083 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +000084 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +000085 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +000086 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +000087
hasso508e53e2004-05-18 18:57:06 +000088 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
89 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
90 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +000091 {
hasso508e53e2004-05-18 18:57:06 +000092 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +000093 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +000094 }
hasso508e53e2004-05-18 18:57:06 +000095
96 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +000097 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +000098}
99
hasso508e53e2004-05-18 18:57:06 +0000100void
101ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000102{
paul718e3742002-12-13 20:15:29 +0000103 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000104 char options[16];
105 char *p;
paul718e3742002-12-13 20:15:29 +0000106
hasso508e53e2004-05-18 18:57:06 +0000107 ospf6_header_print (oh);
108 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000109
hasso508e53e2004-05-18 18:57:06 +0000110 dbdesc = (struct ospf6_dbdesc *)
111 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000112
hasso508e53e2004-05-18 18:57:06 +0000113 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000114
hassoc6487d62004-12-24 06:00:11 +0000115 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000116 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000117 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000118 dbdesc->reserved2,
119 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
120 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
121 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
122 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000123
hasso508e53e2004-05-18 18:57:06 +0000124 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
125 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
126 p += sizeof (struct ospf6_lsa_header))
127 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
128
129 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000130 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000131}
132
hasso508e53e2004-05-18 18:57:06 +0000133void
134ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000135{
hasso508e53e2004-05-18 18:57:06 +0000136 char id[16], adv_router[16];
137 char *p;
paul718e3742002-12-13 20:15:29 +0000138
hasso508e53e2004-05-18 18:57:06 +0000139 ospf6_header_print (oh);
140 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000141
hasso508e53e2004-05-18 18:57:06 +0000142 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
143 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
144 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000145 {
hasso508e53e2004-05-18 18:57:06 +0000146 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
147 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
148 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000149 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000150 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000151 }
hasso508e53e2004-05-18 18:57:06 +0000152
153 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000154 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000155}
156
hasso508e53e2004-05-18 18:57:06 +0000157void
158ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000159{
paul718e3742002-12-13 20:15:29 +0000160 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000161 u_long num;
162 char *p;
paul718e3742002-12-13 20:15:29 +0000163
hasso508e53e2004-05-18 18:57:06 +0000164 ospf6_header_print (oh);
165 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000166
hasso508e53e2004-05-18 18:57:06 +0000167 lsupdate = (struct ospf6_lsupdate *)
168 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000169
hasso508e53e2004-05-18 18:57:06 +0000170 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000171 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000172
hasso508e53e2004-05-18 18:57:06 +0000173 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
174 p < OSPF6_MESSAGE_END (oh) &&
175 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
176 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000177 {
hasso508e53e2004-05-18 18:57:06 +0000178 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
179 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
180 {
hassoc6487d62004-12-24 06:00:11 +0000181 zlog_debug (" Malformed LSA length, quit printing");
hasso508e53e2004-05-18 18:57:06 +0000182 break;
183 }
184 }
paul718e3742002-12-13 20:15:29 +0000185
hasso508e53e2004-05-18 18:57:06 +0000186 if (p != OSPF6_MESSAGE_END (oh))
187 {
188 char buf[32];
189
190 int num = 0;
191 memset (buf, 0, sizeof (buf));
192
hassoc6487d62004-12-24 06:00:11 +0000193 zlog_debug (" Trailing garbage exists");
hasso508e53e2004-05-18 18:57:06 +0000194 while (p < OSPF6_MESSAGE_END (oh))
195 {
196 snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
197 num++;
198 if (num == 8)
199 {
hassoc6487d62004-12-24 06:00:11 +0000200 zlog_debug (" %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000201 memset (buf, 0, sizeof (buf));
202 num = 0;
203 }
204 }
205 if (num)
hassoc6487d62004-12-24 06:00:11 +0000206 zlog_debug (" %s", buf);
paul718e3742002-12-13 20:15:29 +0000207 }
208}
209
hasso508e53e2004-05-18 18:57:06 +0000210void
211ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000212{
hasso508e53e2004-05-18 18:57:06 +0000213 char *p;
paul718e3742002-12-13 20:15:29 +0000214
hasso508e53e2004-05-18 18:57:06 +0000215 ospf6_header_print (oh);
216 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000217
hasso508e53e2004-05-18 18:57:06 +0000218 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
219 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
220 p += sizeof (struct ospf6_lsa_header))
221 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
222
223 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000224 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000225}
226
hasso508e53e2004-05-18 18:57:06 +0000227/* Receive function */
228#define MSG_OK 0
229#define MSG_NG 1
230static 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 */
835 if (ntohs (dbdesc->ifmtu) != oi->ifmtu)
836 {
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
Tom Goffae2254a2010-11-10 13:01:41 -08001171void
1172ospf6_message_terminate (void)
1173{
1174 if (recvbuf)
1175 {
1176 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1177 recvbuf = NULL;
1178 }
1179
1180 if (sendbuf)
1181 {
1182 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1183 sendbuf = NULL;
1184 }
1185
1186 iobuflen = 0;
1187}
1188
paul718e3742002-12-13 20:15:29 +00001189int
1190ospf6_receive (struct thread *thread)
1191{
paul0c083ee2004-10-10 12:54:58 +00001192 int sockfd;
1193 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001194 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001195 struct in6_addr src, dst;
1196 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001197 struct iovec iovector[2];
1198 struct ospf6_interface *oi;
1199 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001200
1201 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001202 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001203 thread_add_read (master, ospf6_receive, NULL, sockfd);
1204
1205 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001206 memset (&src, 0, sizeof (src));
1207 memset (&dst, 0, sizeof (dst));
1208 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001209 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001210 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001211 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001212 iovector[1].iov_base = NULL;
1213 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001214
1215 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001216 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001217 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001218 {
hasso508e53e2004-05-18 18:57:06 +00001219 zlog_err ("Excess message read");
1220 return 0;
1221 }
1222 else if (len < sizeof (struct ospf6_header))
1223 {
1224 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001225 return 0;
1226 }
1227
hasso508e53e2004-05-18 18:57:06 +00001228 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1229 if (oi == NULL || oi->area == NULL)
1230 {
hassoc6487d62004-12-24 06:00:11 +00001231 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001232 return 0;
1233 }
1234
1235 oh = (struct ospf6_header *) recvbuf;
1236
1237 /* Log */
1238 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1239 {
1240 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1241 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001242 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001243 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001244 zlog_debug (" src: %s", srcname);
1245 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001246 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001247 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001248
1249 switch (oh->type)
1250 {
1251 case OSPF6_MESSAGE_TYPE_HELLO:
1252 ospf6_hello_print (oh);
1253 break;
1254 case OSPF6_MESSAGE_TYPE_DBDESC:
1255 ospf6_dbdesc_print (oh);
1256 break;
1257 case OSPF6_MESSAGE_TYPE_LSREQ:
1258 ospf6_lsreq_print (oh);
1259 break;
1260 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1261 ospf6_lsupdate_print (oh);
1262 break;
1263 case OSPF6_MESSAGE_TYPE_LSACK:
1264 ospf6_lsack_print (oh);
1265 break;
1266 default:
hassoc6487d62004-12-24 06:00:11 +00001267 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001268 break;
1269 }
1270 }
1271
1272 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1273 {
1274 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001275 zlog_debug ("Ignore message on passive interface %s",
hasso508e53e2004-05-18 18:57:06 +00001276 oi->interface->name);
1277 return 0;
1278 }
1279
1280 switch (oh->type)
1281 {
1282 case OSPF6_MESSAGE_TYPE_HELLO:
1283 ospf6_hello_recv (&src, &dst, oi, oh);
1284 break;
1285
1286 case OSPF6_MESSAGE_TYPE_DBDESC:
1287 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1288 break;
1289
1290 case OSPF6_MESSAGE_TYPE_LSREQ:
1291 ospf6_lsreq_recv (&src, &dst, oi, oh);
1292 break;
1293
1294 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1295 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1296 break;
1297
1298 case OSPF6_MESSAGE_TYPE_LSACK:
1299 ospf6_lsack_recv (&src, &dst, oi, oh);
1300 break;
1301
1302 default:
1303 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001304 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001305 break;
1306 }
1307
1308 return 0;
1309}
1310
Paul Jakma6ac29a52008-08-15 13:45:30 +01001311static void
hasso508e53e2004-05-18 18:57:06 +00001312ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1313 struct ospf6_interface *oi, struct ospf6_header *oh)
1314{
1315 int len;
1316 char srcname[64], dstname[64];
1317 struct iovec iovector[2];
1318
1319 /* initialize */
1320 iovector[0].iov_base = (caddr_t) oh;
1321 iovector[0].iov_len = ntohs (oh->length);
1322 iovector[1].iov_base = NULL;
1323 iovector[1].iov_len = 0;
1324
1325 /* fill OSPF header */
1326 oh->version = OSPFV3_VERSION;
1327 /* message type must be set before */
1328 /* message length must be set before */
1329 oh->router_id = oi->area->ospf6->router_id;
1330 oh->area_id = oi->area->area_id;
1331 /* checksum is calculated by kernel */
1332 oh->instance_id = oi->instance_id;
1333 oh->reserved = 0;
1334
1335 /* Log */
1336 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1337 {
1338 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1339 if (src)
1340 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1341 else
1342 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001343 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001344 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001345 zlog_debug (" src: %s", srcname);
1346 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001347
1348 switch (oh->type)
1349 {
1350 case OSPF6_MESSAGE_TYPE_HELLO:
1351 ospf6_hello_print (oh);
1352 break;
1353 case OSPF6_MESSAGE_TYPE_DBDESC:
1354 ospf6_dbdesc_print (oh);
1355 break;
1356 case OSPF6_MESSAGE_TYPE_LSREQ:
1357 ospf6_lsreq_print (oh);
1358 break;
1359 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1360 ospf6_lsupdate_print (oh);
1361 break;
1362 case OSPF6_MESSAGE_TYPE_LSACK:
1363 ospf6_lsack_print (oh);
1364 break;
1365 default:
hassoc6487d62004-12-24 06:00:11 +00001366 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001367 assert (0);
1368 break;
1369 }
1370 }
1371
1372 /* send message */
1373 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1374 if (len != ntohs (oh->length))
1375 zlog_err ("Could not send entire message");
1376}
1377
1378int
1379ospf6_hello_send (struct thread *thread)
1380{
1381 struct ospf6_interface *oi;
1382 struct ospf6_header *oh;
1383 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001384 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001385 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001386 struct ospf6_neighbor *on;
1387
1388 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1389 oi->thread_send_hello = (struct thread *) NULL;
1390
1391 if (oi->state <= OSPF6_INTERFACE_DOWN)
1392 {
1393 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001394 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001395 oi->interface->name);
1396 return 0;
1397 }
1398
1399 /* set next thread */
1400 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1401 oi, oi->hello_interval);
1402
hasso3b4cd3a2004-05-18 19:28:32 +00001403 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001404 oh = (struct ospf6_header *) sendbuf;
1405 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1406
1407 hello->interface_id = htonl (oi->interface->ifindex);
1408 hello->priority = oi->priority;
1409 hello->options[0] = oi->area->options[0];
1410 hello->options[1] = oi->area->options[1];
1411 hello->options[2] = oi->area->options[2];
1412 hello->hello_interval = htons (oi->hello_interval);
1413 hello->dead_interval = htons (oi->dead_interval);
1414 hello->drouter = oi->drouter;
1415 hello->bdrouter = oi->bdrouter;
1416
Paul Jakma6ac29a52008-08-15 13:45:30 +01001417 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001418
paul1eb8ef22005-04-07 07:30:20 +00001419 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001420 {
hasso508e53e2004-05-18 18:57:06 +00001421 if (on->state < OSPF6_NEIGHBOR_INIT)
1422 continue;
1423
1424 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1425 {
1426 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001427 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001428 break;
1429 }
1430
1431 memcpy (p, &on->router_id, sizeof (u_int32_t));
1432 p += sizeof (u_int32_t);
1433 }
1434
1435 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1436 oh->length = htons (p - sendbuf);
1437
1438 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1439 return 0;
1440}
1441
1442int
1443ospf6_dbdesc_send (struct thread *thread)
1444{
1445 struct ospf6_neighbor *on;
1446 struct ospf6_header *oh;
1447 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001448 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001449 struct ospf6_lsa *lsa;
1450
1451 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1452 on->thread_send_dbdesc = (struct thread *) NULL;
1453
1454 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1455 {
1456 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001457 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1458 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001459 return 0;
1460 }
1461
1462 /* set next thread if master */
1463 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1464 on->thread_send_dbdesc =
1465 thread_add_timer (master, ospf6_dbdesc_send, on,
1466 on->ospf6_if->rxmt_interval);
1467
hasso3b4cd3a2004-05-18 19:28:32 +00001468 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001469 oh = (struct ospf6_header *) sendbuf;
1470 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1471 sizeof (struct ospf6_header));
1472
1473 /* if this is initial one, initialize sequence number for DbDesc */
1474 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1475 {
1476 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001477 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001478 tv.tv_sec = 1;
1479 on->dbdesc_seqnum = tv.tv_sec;
1480 }
1481
1482 dbdesc->options[0] = on->ospf6_if->area->options[0];
1483 dbdesc->options[1] = on->ospf6_if->area->options[1];
1484 dbdesc->options[2] = on->ospf6_if->area->options[2];
1485 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1486 dbdesc->bits = on->dbdesc_bits;
1487 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1488
1489 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001490 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001491 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1492 {
1493 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1494 lsa = ospf6_lsdb_next (lsa))
1495 {
1496 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1497
1498 /* MTU check */
1499 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1500 on->ospf6_if->ifmtu)
1501 {
1502 ospf6_lsa_unlock (lsa);
1503 break;
1504 }
1505 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1506 p += sizeof (struct ospf6_lsa_header);
1507 }
1508 }
1509
1510 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1511 oh->length = htons (p - sendbuf);
1512
1513 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1514 on->ospf6_if, oh);
1515 return 0;
1516}
1517
1518int
1519ospf6_dbdesc_send_newone (struct thread *thread)
1520{
1521 struct ospf6_neighbor *on;
1522 struct ospf6_lsa *lsa;
1523 unsigned int size = 0;
1524
1525 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001526 ospf6_lsdb_remove_all (on->dbdesc_list);
1527
1528 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1529 so that ospf6_send_dbdesc () can send those LSAs */
1530 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1531 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1532 lsa = ospf6_lsdb_next (lsa))
1533 {
1534 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1535 {
1536 ospf6_lsa_unlock (lsa);
1537 break;
1538 }
1539
hasso508e53e2004-05-18 18:57:06 +00001540 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1541 ospf6_lsdb_remove (lsa, on->summary_list);
1542 size += sizeof (struct ospf6_lsa_header);
1543 }
1544
1545 if (on->summary_list->count == 0)
1546 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1547
1548 /* If slave, More bit check must be done here */
1549 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1550 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1551 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1552 thread_add_event (master, exchange_done, on, 0);
1553
1554 thread_execute (master, ospf6_dbdesc_send, on, 0);
1555 return 0;
1556}
1557
1558int
1559ospf6_lsreq_send (struct thread *thread)
1560{
1561 struct ospf6_neighbor *on;
1562 struct ospf6_header *oh;
1563 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001564 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001565 struct ospf6_lsa *lsa;
1566
1567 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1568 on->thread_send_lsreq = (struct thread *) NULL;
1569
1570 /* LSReq will be sent only in ExStart or Loading */
1571 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1572 on->state != OSPF6_NEIGHBOR_LOADING)
1573 {
1574 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001575 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1576 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001577 return 0;
1578 }
1579
1580 /* schedule loading_done if request list is empty */
1581 if (on->request_list->count == 0)
1582 {
1583 thread_add_event (master, loading_done, on, 0);
1584 return 0;
1585 }
1586
1587 /* set next thread */
1588 on->thread_send_lsreq =
1589 thread_add_timer (master, ospf6_lsreq_send, on,
1590 on->ospf6_if->rxmt_interval);
1591
hasso3b4cd3a2004-05-18 19:28:32 +00001592 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001593 oh = (struct ospf6_header *) sendbuf;
1594
1595 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001596 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001597 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1598 lsa = ospf6_lsdb_next (lsa))
1599 {
1600 /* MTU check */
1601 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
1602 {
1603 ospf6_lsa_unlock (lsa);
1604 break;
1605 }
1606
1607 e = (struct ospf6_lsreq_entry *) p;
1608 e->type = lsa->header->type;
1609 e->id = lsa->header->id;
1610 e->adv_router = lsa->header->adv_router;
1611 p += sizeof (struct ospf6_lsreq_entry);
1612 }
1613
1614 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1615 oh->length = htons (p - sendbuf);
1616
1617 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1618 on->ospf6_if, oh);
1619 return 0;
1620}
1621
1622int
1623ospf6_lsupdate_send_neighbor (struct thread *thread)
1624{
1625 struct ospf6_neighbor *on;
1626 struct ospf6_header *oh;
1627 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001628 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001629 int num;
1630 struct ospf6_lsa *lsa;
1631
1632 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1633 on->thread_send_lsupdate = (struct thread *) NULL;
1634
hasso6452df02004-08-15 05:52:07 +00001635 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001636 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001637
hasso508e53e2004-05-18 18:57:06 +00001638 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1639 {
1640 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001641 zlog_debug ("Quit to send (neighbor state %s)",
1642 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001643 return 0;
1644 }
1645
1646 /* if we have nothing to send, return */
1647 if (on->lsupdate_list->count == 0 &&
1648 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001649 {
1650 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001651 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001652 return 0;
1653 }
hasso508e53e2004-05-18 18:57:06 +00001654
hasso3b4cd3a2004-05-18 19:28:32 +00001655 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001656 oh = (struct ospf6_header *) sendbuf;
1657 lsupdate = (struct ospf6_lsupdate *)
1658 ((caddr_t) oh + sizeof (struct ospf6_header));
1659
Paul Jakma6ac29a52008-08-15 13:45:30 +01001660 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001661 num = 0;
1662
1663 /* lsupdate_list lists those LSA which doesn't need to be
1664 retransmitted. remove those from the list */
1665 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1666 lsa = ospf6_lsdb_next (lsa))
1667 {
1668 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001669 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
1670 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001671 {
1672 ospf6_lsa_unlock (lsa);
1673 break;
1674 }
1675
hasso508e53e2004-05-18 18:57:06 +00001676 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1677 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1678 p += OSPF6_LSA_SIZE (lsa->header);
1679 num++;
1680
1681 assert (lsa->lock == 2);
1682 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1683 }
1684
1685 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1686 lsa = ospf6_lsdb_next (lsa))
1687 {
1688 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001689 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
1690 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001691 {
1692 ospf6_lsa_unlock (lsa);
1693 break;
1694 }
1695
hasso508e53e2004-05-18 18:57:06 +00001696 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1697 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1698 p += OSPF6_LSA_SIZE (lsa->header);
1699 num++;
1700 }
1701
1702 lsupdate->lsa_number = htonl (num);
1703
1704 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1705 oh->length = htons (p - sendbuf);
1706
1707 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1708 on->ospf6_if, oh);
1709
1710 if (on->lsupdate_list->count != 0 ||
1711 on->retrans_list->count != 0)
1712 {
1713 if (on->lsupdate_list->count != 0)
1714 on->thread_send_lsupdate =
1715 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1716 else
1717 on->thread_send_lsupdate =
1718 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1719 on->ospf6_if->rxmt_interval);
1720 }
1721
1722 return 0;
1723}
1724
1725int
1726ospf6_lsupdate_send_interface (struct thread *thread)
1727{
1728 struct ospf6_interface *oi;
1729 struct ospf6_header *oh;
1730 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001731 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001732 int num;
1733 struct ospf6_lsa *lsa;
1734
1735 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1736 oi->thread_send_lsupdate = (struct thread *) NULL;
1737
1738 if (oi->state <= OSPF6_INTERFACE_WAITING)
1739 {
1740 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001741 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
1742 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001743 return 0;
1744 }
1745
1746 /* if we have nothing to send, return */
1747 if (oi->lsupdate_list->count == 0)
1748 return 0;
1749
hasso3b4cd3a2004-05-18 19:28:32 +00001750 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001751 oh = (struct ospf6_header *) sendbuf;
1752 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1753 sizeof (struct ospf6_header));
1754
Paul Jakma6ac29a52008-08-15 13:45:30 +01001755 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001756 num = 0;
1757
1758 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1759 lsa = ospf6_lsdb_next (lsa))
1760 {
1761 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001762 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
1763 > oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001764 {
1765 ospf6_lsa_unlock (lsa);
1766 break;
1767 }
1768
hasso508e53e2004-05-18 18:57:06 +00001769 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1770 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1771 p += OSPF6_LSA_SIZE (lsa->header);
1772 num++;
1773
1774 assert (lsa->lock == 2);
1775 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1776 }
1777
1778 lsupdate->lsa_number = htonl (num);
1779
1780 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1781 oh->length = htons (p - sendbuf);
1782
1783 if (oi->state == OSPF6_INTERFACE_DR ||
1784 oi->state == OSPF6_INTERFACE_BDR)
1785 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1786 else
1787 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1788
1789 if (oi->lsupdate_list->count > 0)
1790 {
1791 oi->thread_send_lsupdate =
1792 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1793 }
1794
1795 return 0;
1796}
1797
1798int
1799ospf6_lsack_send_neighbor (struct thread *thread)
1800{
1801 struct ospf6_neighbor *on;
1802 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001803 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001804 struct ospf6_lsa *lsa;
1805
1806 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1807 on->thread_send_lsack = (struct thread *) NULL;
1808
1809 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1810 {
1811 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001812 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
1813 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001814 return 0;
1815 }
1816
1817 /* if we have nothing to send, return */
1818 if (on->lsack_list->count == 0)
1819 return 0;
1820
hasso3b4cd3a2004-05-18 19:28:32 +00001821 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001822 oh = (struct ospf6_header *) sendbuf;
1823
Paul Jakma6ac29a52008-08-15 13:45:30 +01001824 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001825
1826 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1827 lsa = ospf6_lsdb_next (lsa))
1828 {
1829 /* MTU check */
1830 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1831 {
1832 /* if we run out of packet size/space here,
1833 better to try again soon. */
1834 THREAD_OFF (on->thread_send_lsack);
1835 on->thread_send_lsack =
1836 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1837
1838 ospf6_lsa_unlock (lsa);
1839 break;
1840 }
1841
1842 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1843 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1844 p += sizeof (struct ospf6_lsa_header);
1845
1846 assert (lsa->lock == 2);
1847 ospf6_lsdb_remove (lsa, on->lsack_list);
1848 }
1849
1850 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1851 oh->length = htons (p - sendbuf);
1852
1853 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1854 on->ospf6_if, oh);
1855 return 0;
1856}
1857
1858int
1859ospf6_lsack_send_interface (struct thread *thread)
1860{
1861 struct ospf6_interface *oi;
1862 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001863 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001864 struct ospf6_lsa *lsa;
1865
1866 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1867 oi->thread_send_lsack = (struct thread *) NULL;
1868
1869 if (oi->state <= OSPF6_INTERFACE_WAITING)
1870 {
1871 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001872 zlog_debug ("Quit to send LSAck to interface %s state %s",
1873 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001874 return 0;
1875 }
1876
1877 /* if we have nothing to send, return */
1878 if (oi->lsack_list->count == 0)
1879 return 0;
1880
hasso3b4cd3a2004-05-18 19:28:32 +00001881 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001882 oh = (struct ospf6_header *) sendbuf;
1883
Paul Jakma6ac29a52008-08-15 13:45:30 +01001884 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001885
1886 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1887 lsa = ospf6_lsdb_next (lsa))
1888 {
1889 /* MTU check */
1890 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
1891 {
1892 /* if we run out of packet size/space here,
1893 better to try again soon. */
1894 THREAD_OFF (oi->thread_send_lsack);
1895 oi->thread_send_lsack =
1896 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1897
1898 ospf6_lsa_unlock (lsa);
1899 break;
1900 }
1901
1902 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1903 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1904 p += sizeof (struct ospf6_lsa_header);
1905
1906 assert (lsa->lock == 2);
1907 ospf6_lsdb_remove (lsa, oi->lsack_list);
1908 }
1909
1910 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1911 oh->length = htons (p - sendbuf);
1912
1913 if (oi->state == OSPF6_INTERFACE_DR ||
1914 oi->state == OSPF6_INTERFACE_BDR)
1915 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1916 else
1917 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1918
1919 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1920 {
1921 oi->thread_send_lsack =
1922 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1923 }
paul718e3742002-12-13 20:15:29 +00001924
1925 return 0;
1926}
1927
1928
hasso508e53e2004-05-18 18:57:06 +00001929/* Commands */
1930DEFUN (debug_ospf6_message,
1931 debug_ospf6_message_cmd,
1932 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1933 DEBUG_STR
1934 OSPF6_STR
1935 "Debug OSPFv3 message\n"
1936 "Debug Unknown message\n"
1937 "Debug Hello message\n"
1938 "Debug Database Description message\n"
1939 "Debug Link State Request message\n"
1940 "Debug Link State Update message\n"
1941 "Debug Link State Acknowledgement message\n"
1942 "Debug All message\n"
1943 )
paul718e3742002-12-13 20:15:29 +00001944{
hasso508e53e2004-05-18 18:57:06 +00001945 unsigned char level = 0;
1946 int type = 0;
paul718e3742002-12-13 20:15:29 +00001947 int i;
1948
hasso508e53e2004-05-18 18:57:06 +00001949 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001950
hasso508e53e2004-05-18 18:57:06 +00001951 /* check type */
1952 if (! strncmp (argv[0], "u", 1))
1953 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1954 else if (! strncmp (argv[0], "h", 1))
1955 type = OSPF6_MESSAGE_TYPE_HELLO;
1956 else if (! strncmp (argv[0], "d", 1))
1957 type = OSPF6_MESSAGE_TYPE_DBDESC;
1958 else if (! strncmp (argv[0], "lsr", 3))
1959 type = OSPF6_MESSAGE_TYPE_LSREQ;
1960 else if (! strncmp (argv[0], "lsu", 3))
1961 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1962 else if (! strncmp (argv[0], "lsa", 3))
1963 type = OSPF6_MESSAGE_TYPE_LSACK;
1964 else if (! strncmp (argv[0], "a", 1))
1965 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001966
hasso508e53e2004-05-18 18:57:06 +00001967 if (argc == 1)
1968 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1969 else if (! strncmp (argv[1], "s", 1))
1970 level = OSPF6_DEBUG_MESSAGE_SEND;
1971 else if (! strncmp (argv[1], "r", 1))
1972 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001973
hasso508e53e2004-05-18 18:57:06 +00001974 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001975 {
hasso508e53e2004-05-18 18:57:06 +00001976 for (i = 0; i < 6; i++)
1977 OSPF6_DEBUG_MESSAGE_ON (i, level);
1978 }
1979 else
1980 OSPF6_DEBUG_MESSAGE_ON (type, level);
1981
1982 return CMD_SUCCESS;
1983}
1984
1985ALIAS (debug_ospf6_message,
1986 debug_ospf6_message_sendrecv_cmd,
1987 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1988 DEBUG_STR
1989 OSPF6_STR
1990 "Debug OSPFv3 message\n"
1991 "Debug Unknown message\n"
1992 "Debug Hello message\n"
1993 "Debug Database Description message\n"
1994 "Debug Link State Request message\n"
1995 "Debug Link State Update message\n"
1996 "Debug Link State Acknowledgement message\n"
1997 "Debug All message\n"
1998 "Debug only sending message\n"
1999 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002000 )
hasso508e53e2004-05-18 18:57:06 +00002001
2002
2003DEFUN (no_debug_ospf6_message,
2004 no_debug_ospf6_message_cmd,
2005 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2006 NO_STR
2007 DEBUG_STR
2008 OSPF6_STR
2009 "Debug OSPFv3 message\n"
2010 "Debug Unknown message\n"
2011 "Debug Hello message\n"
2012 "Debug Database Description message\n"
2013 "Debug Link State Request message\n"
2014 "Debug Link State Update message\n"
2015 "Debug Link State Acknowledgement message\n"
2016 "Debug All message\n"
2017 )
2018{
2019 unsigned char level = 0;
2020 int type = 0;
2021 int i;
2022
2023 assert (argc > 0);
2024
2025 /* check type */
2026 if (! strncmp (argv[0], "u", 1))
2027 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2028 else if (! strncmp (argv[0], "h", 1))
2029 type = OSPF6_MESSAGE_TYPE_HELLO;
2030 else if (! strncmp (argv[0], "d", 1))
2031 type = OSPF6_MESSAGE_TYPE_DBDESC;
2032 else if (! strncmp (argv[0], "lsr", 3))
2033 type = OSPF6_MESSAGE_TYPE_LSREQ;
2034 else if (! strncmp (argv[0], "lsu", 3))
2035 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2036 else if (! strncmp (argv[0], "lsa", 3))
2037 type = OSPF6_MESSAGE_TYPE_LSACK;
2038 else if (! strncmp (argv[0], "a", 1))
2039 type = OSPF6_MESSAGE_TYPE_ALL;
2040
2041 if (argc == 1)
2042 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2043 else if (! strncmp (argv[1], "s", 1))
2044 level = OSPF6_DEBUG_MESSAGE_SEND;
2045 else if (! strncmp (argv[1], "r", 1))
2046 level = OSPF6_DEBUG_MESSAGE_RECV;
2047
2048 if (type == OSPF6_MESSAGE_TYPE_ALL)
2049 {
2050 for (i = 0; i < 6; i++)
2051 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2052 }
2053 else
2054 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2055
2056 return CMD_SUCCESS;
2057}
2058
2059ALIAS (no_debug_ospf6_message,
2060 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002061 "no debug ospf6 message "
2062 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002063 NO_STR
2064 DEBUG_STR
2065 OSPF6_STR
2066 "Debug OSPFv3 message\n"
2067 "Debug Unknown message\n"
2068 "Debug Hello message\n"
2069 "Debug Database Description message\n"
2070 "Debug Link State Request message\n"
2071 "Debug Link State Update message\n"
2072 "Debug Link State Acknowledgement message\n"
2073 "Debug All message\n"
2074 "Debug only sending message\n"
2075 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002076 )
hasso508e53e2004-05-18 18:57:06 +00002077
2078int
2079config_write_ospf6_debug_message (struct vty *vty)
2080{
paul0c083ee2004-10-10 12:54:58 +00002081 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002082 "lsreq", "lsupdate", "lsack"};
2083 unsigned char s = 0, r = 0;
2084 int i;
2085
2086 for (i = 0; i < 6; i++)
2087 {
2088 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2089 s |= 1 << i;
2090 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2091 r |= 1 << i;
2092 }
2093
2094 if (s == 0x3f && r == 0x3f)
2095 {
hasso049207c2004-08-04 20:02:13 +00002096 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002097 return 0;
2098 }
2099
hasso508e53e2004-05-18 18:57:06 +00002100 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002101 {
hasso049207c2004-08-04 20:02:13 +00002102 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002103 return 0;
2104 }
2105 else if (s == 0 && r == 0x3f)
2106 {
hasso049207c2004-08-04 20:02:13 +00002107 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002108 return 0;
paul718e3742002-12-13 20:15:29 +00002109 }
2110
hasso508e53e2004-05-18 18:57:06 +00002111 /* Unknown message is logged by default */
2112 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2113 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002114 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002115 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002116 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002117 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002118 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002119
hasso508e53e2004-05-18 18:57:06 +00002120 for (i = 1; i < 6; i++)
2121 {
2122 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2123 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002124 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002125 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2126 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002127 VNL);
hasso508e53e2004-05-18 18:57:06 +00002128 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2129 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002130 VNL);
hasso508e53e2004-05-18 18:57:06 +00002131 }
paul718e3742002-12-13 20:15:29 +00002132
2133 return 0;
2134}
2135
paul718e3742002-12-13 20:15:29 +00002136void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002137install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002138{
hasso508e53e2004-05-18 18:57:06 +00002139 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2140 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2141 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2142 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2143 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2144 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2145 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2146 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002147}
2148
paul718e3742002-12-13 20:15:29 +00002149