blob: f4df318bdf289fdb1685a8b1b33c293313c59578 [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 */
hasso508e53e2004-05-18 18:57:06 +0000228static int
229ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst,
230 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000231{
paul718e3742002-12-13 20:15:29 +0000232 u_char type;
hasso508e53e2004-05-18 18:57:06 +0000233 type = OSPF6_MESSAGE_TYPE_CANONICAL (oh->type);
paul718e3742002-12-13 20:15:29 +0000234
hasso508e53e2004-05-18 18:57:06 +0000235 /* version check */
236 if (oh->version != OSPFV3_VERSION)
paul718e3742002-12-13 20:15:29 +0000237 {
hasso508e53e2004-05-18 18:57:06 +0000238 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000239 zlog_debug ("Message with unknown version");
hasso508e53e2004-05-18 18:57:06 +0000240 return MSG_NG;
paul718e3742002-12-13 20:15:29 +0000241 }
242
hasso508e53e2004-05-18 18:57:06 +0000243 /* Area-ID check */
244 if (oh->area_id != oi->area->area_id)
245 {
hasso6452df02004-08-15 05:52:07 +0000246 if (oh->area_id == BACKBONE_AREA_ID)
hasso508e53e2004-05-18 18:57:06 +0000247 {
248 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000249 zlog_debug ("Message may be via Virtual Link: not supported");
hasso508e53e2004-05-18 18:57:06 +0000250 return MSG_NG;
251 }
252
253 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000254 zlog_debug ("Area-ID mismatch");
hasso508e53e2004-05-18 18:57:06 +0000255 return MSG_NG;
256 }
257
258 /* Instance-ID check */
259 if (oh->instance_id != oi->instance_id)
260 {
261 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000262 zlog_debug ("Instance-ID mismatch");
hasso508e53e2004-05-18 18:57:06 +0000263 return MSG_NG;
264 }
265
266 /* Router-ID check */
267 if (oh->router_id == oi->area->ospf6->router_id)
268 zlog_warn ("Detect duplicate Router-ID");
269
270 return MSG_OK;
271}
272
Paul Jakma6ac29a52008-08-15 13:45:30 +0100273static void
hasso508e53e2004-05-18 18:57:06 +0000274ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
275 struct ospf6_interface *oi, struct ospf6_header *oh)
276{
277 struct ospf6_hello *hello;
278 struct ospf6_neighbor *on;
279 char *p;
280 int twoway = 0;
281 int neighborchange = 0;
282 int backupseen = 0;
283
284 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
285 return;
286
287 hello = (struct ospf6_hello *)
288 ((caddr_t) oh + sizeof (struct ospf6_header));
289
paul718e3742002-12-13 20:15:29 +0000290 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000291 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000292 {
hasso508e53e2004-05-18 18:57:06 +0000293 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000294 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000295 return;
296 }
297
298 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000299 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000300 {
hasso508e53e2004-05-18 18:57:06 +0000301 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000302 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000303 return;
304 }
305
hasso508e53e2004-05-18 18:57:06 +0000306 /* E-bit check */
307 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
308 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000309 {
hasso508e53e2004-05-18 18:57:06 +0000310 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000311 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000312 return;
313 }
314
hasso508e53e2004-05-18 18:57:06 +0000315 /* Find neighbor, create if not exist */
316 on = ospf6_neighbor_lookup (oh->router_id, oi);
317 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000318 {
hasso508e53e2004-05-18 18:57:06 +0000319 on = ospf6_neighbor_create (oh->router_id, oi);
320 on->prev_drouter = on->drouter = hello->drouter;
321 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
322 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000323 }
324
hasso7b6ae022005-06-24 08:17:51 +0000325 /* always override neighbor's source address and ifindex */
326 on->ifindex = ntohl (hello->interface_id);
327 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
328
paul718e3742002-12-13 20:15:29 +0000329 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000330 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
331 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
332 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000333 {
hasso508e53e2004-05-18 18:57:06 +0000334 u_int32_t *router_id = (u_int32_t *) p;
335
336 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000337 twoway++;
paul718e3742002-12-13 20:15:29 +0000338 }
339
hasso508e53e2004-05-18 18:57:06 +0000340 if (p != OSPF6_MESSAGE_END (oh))
341 {
342 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000343 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000344 }
345
346 /* RouterPriority check */
347 if (on->priority != hello->priority)
348 {
349 on->priority = hello->priority;
350 neighborchange++;
351 }
352
353 /* DR check */
354 if (on->drouter != hello->drouter)
355 {
356 on->prev_drouter = on->drouter;
357 on->drouter = hello->drouter;
358 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
359 neighborchange++;
360 }
361
362 /* BDR check */
363 if (on->bdrouter != hello->bdrouter)
364 {
365 on->prev_bdrouter = on->bdrouter;
366 on->bdrouter = hello->bdrouter;
367 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
368 neighborchange++;
369 }
paul718e3742002-12-13 20:15:29 +0000370
371 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000372 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000373 {
hasso508e53e2004-05-18 18:57:06 +0000374 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000375 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000376 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000377 backupseen++;
378 }
379
hasso508e53e2004-05-18 18:57:06 +0000380 /* Execute neighbor events */
381 thread_execute (master, hello_received, on, 0);
382 if (twoway)
383 thread_execute (master, twoway_received, on, 0);
384 else
385 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000386
hasso508e53e2004-05-18 18:57:06 +0000387 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000388 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000389 thread_add_event (master, backup_seen, oi, 0);
390 if (neighborchange)
391 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000392}
393
hasso508e53e2004-05-18 18:57:06 +0000394static void
395ospf6_dbdesc_recv_master (struct ospf6_header *oh,
396 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000397{
paul718e3742002-12-13 20:15:29 +0000398 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000399 char *p;
paul718e3742002-12-13 20:15:29 +0000400
hasso508e53e2004-05-18 18:57:06 +0000401 dbdesc = (struct ospf6_dbdesc *)
402 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000403
hasso508e53e2004-05-18 18:57:06 +0000404 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000405 {
hasso508e53e2004-05-18 18:57:06 +0000406 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000407 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000408 return;
409 }
410
hasso508e53e2004-05-18 18:57:06 +0000411 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000412 {
hasso508e53e2004-05-18 18:57:06 +0000413 case OSPF6_NEIGHBOR_TWOWAY:
414 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000415 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000416 return;
417
418 case OSPF6_NEIGHBOR_INIT:
419 thread_execute (master, twoway_received, on, 0);
420 if (on->state != OSPF6_NEIGHBOR_EXSTART)
421 {
422 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000423 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000424 return;
425 }
426 /* else fall through to ExStart */
427
428 case OSPF6_NEIGHBOR_EXSTART:
429 /* if neighbor obeys us as our slave, schedule negotiation_done
430 and process LSA Headers. Otherwise, ignore this message */
431 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
432 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
433 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
434 {
435 /* execute NegotiationDone */
436 thread_execute (master, negotiation_done, on, 0);
437
438 /* Record neighbor options */
439 memcpy (on->options, dbdesc->options, sizeof (on->options));
440 }
441 else
442 {
443 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000444 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000445 return;
446 }
447 /* fall through to exchange */
448
449 case OSPF6_NEIGHBOR_EXCHANGE:
450 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
451 {
452 /* Duplicated DatabaseDescription is dropped by master */
453 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000454 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000455 return;
456 }
457
458 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
459 {
460 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000461 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000462 thread_add_event (master, seqnumber_mismatch, on, 0);
463 return;
464 }
465
466 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
467 {
468 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000469 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000470 thread_add_event (master, seqnumber_mismatch, on, 0);
471 return;
472 }
473
474 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
475 {
476 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000477 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000478 thread_add_event (master, seqnumber_mismatch, on, 0);
479 return;
480 }
481
482 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
483 {
484 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000485 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000486 (u_long) on->dbdesc_seqnum);
487 thread_add_event (master, seqnumber_mismatch, on, 0);
488 return;
489 }
490 break;
491
492 case OSPF6_NEIGHBOR_LOADING:
493 case OSPF6_NEIGHBOR_FULL:
494 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
495 {
496 /* Duplicated DatabaseDescription is dropped by master */
497 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000498 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000499 return;
500 }
501
502 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000503 zlog_debug ("Not duplicate dbdesc in state %s",
504 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000505 thread_add_event (master, seqnumber_mismatch, on, 0);
506 return;
507
508 default:
509 assert (0);
510 break;
511 }
512
513 /* Process LSA headers */
514 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
515 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
516 p += sizeof (struct ospf6_lsa_header))
517 {
518 struct ospf6_lsa *his, *mine;
519 struct ospf6_lsdb *lsdb = NULL;
520
521 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000522
523 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000524 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000525
526 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000527 {
hasso6452df02004-08-15 05:52:07 +0000528 case OSPF6_SCOPE_LINKLOCAL:
529 lsdb = on->ospf6_if->lsdb;
530 break;
531 case OSPF6_SCOPE_AREA:
532 lsdb = on->ospf6_if->area->lsdb;
533 break;
534 case OSPF6_SCOPE_AS:
535 lsdb = on->ospf6_if->area->ospf6->lsdb;
536 break;
537 case OSPF6_SCOPE_RESERVED:
538 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000539 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000540 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000541 continue;
542 break;
hasso508e53e2004-05-18 18:57:06 +0000543 }
544
545 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000546 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000547 {
548 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000549 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000550 ospf6_lsa_delete (his);
551 thread_add_event (master, seqnumber_mismatch, on, 0);
552 return;
553 }
554
555 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
556 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000557 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000558 {
hasso6452df02004-08-15 05:52:07 +0000559 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000560 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000561 ospf6_lsdb_add (his, on->request_list);
562 }
563 else if (ospf6_lsa_compare (his, mine) < 0)
564 {
565 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000566 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000567 ospf6_lsdb_add (his, on->request_list);
568 }
569 else
hasso6452df02004-08-15 05:52:07 +0000570 {
571 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000572 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000573 ospf6_lsa_delete (his);
574 }
hasso508e53e2004-05-18 18:57:06 +0000575 }
576
577 if (p != OSPF6_MESSAGE_END (oh))
578 {
579 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000580 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000581 }
582
583 /* Increment sequence number */
584 on->dbdesc_seqnum ++;
585
586 /* schedule send lsreq */
587 if (on->thread_send_lsreq == NULL)
588 on->thread_send_lsreq =
589 thread_add_event (master, ospf6_lsreq_send, on, 0);
590
591 THREAD_OFF (on->thread_send_dbdesc);
592
593 /* More bit check */
594 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
595 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
596 thread_add_event (master, exchange_done, on, 0);
597 else
598 on->thread_send_dbdesc =
599 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
600
601 /* save last received dbdesc */
602 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
603}
604
605static void
606ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
607 struct ospf6_neighbor *on)
608{
609 struct ospf6_dbdesc *dbdesc;
610 char *p;
611
612 dbdesc = (struct ospf6_dbdesc *)
613 ((caddr_t) oh + sizeof (struct ospf6_header));
614
615 if (on->state < OSPF6_NEIGHBOR_INIT)
616 {
617 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000618 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000619 return;
620 }
621
hasso508e53e2004-05-18 18:57:06 +0000622 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000623 {
hasso508e53e2004-05-18 18:57:06 +0000624 case OSPF6_NEIGHBOR_TWOWAY:
625 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000626 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000627 return;
628
629 case OSPF6_NEIGHBOR_INIT:
630 thread_execute (master, twoway_received, on, 0);
631 if (on->state != OSPF6_NEIGHBOR_EXSTART)
632 {
633 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000634 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000635 return;
636 }
637 /* else fall through to ExStart */
638
639 case OSPF6_NEIGHBOR_EXSTART:
640 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
641 and process LSA Headers. Otherwise, ignore this message */
642 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
643 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
644 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
645 ntohs (oh->length) == sizeof (struct ospf6_header) +
646 sizeof (struct ospf6_dbdesc))
647 {
648 /* set the master/slave bit to slave */
649 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
650
651 /* set the DD sequence number to one specified by master */
652 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
653
654 /* schedule NegotiationDone */
655 thread_execute (master, negotiation_done, on, 0);
656
657 /* Record neighbor options */
658 memcpy (on->options, dbdesc->options, sizeof (on->options));
659 }
660 else
661 {
662 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000663 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000664 return;
665 }
666 break;
667
668 case OSPF6_NEIGHBOR_EXCHANGE:
669 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
670 {
671 /* Duplicated DatabaseDescription causes slave to retransmit */
672 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000673 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000674 THREAD_OFF (on->thread_send_dbdesc);
675 on->thread_send_dbdesc =
676 thread_add_event (master, ospf6_dbdesc_send, on, 0);
677 return;
678 }
679
680 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
681 {
682 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000683 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000684 thread_add_event (master, seqnumber_mismatch, on, 0);
685 return;
686 }
687
688 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
689 {
690 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000691 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000692 thread_add_event (master, seqnumber_mismatch, on, 0);
693 return;
694 }
695
696 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
697 {
698 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000699 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000700 thread_add_event (master, seqnumber_mismatch, on, 0);
701 return;
702 }
703
704 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
705 {
706 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000707 zlog_debug ("Sequence number mismatch (%#lx expected)",
708 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000709 thread_add_event (master, seqnumber_mismatch, on, 0);
710 return;
711 }
712 break;
713
714 case OSPF6_NEIGHBOR_LOADING:
715 case OSPF6_NEIGHBOR_FULL:
716 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
717 {
718 /* Duplicated DatabaseDescription causes slave to retransmit */
719 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000720 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000721 THREAD_OFF (on->thread_send_dbdesc);
722 on->thread_send_dbdesc =
723 thread_add_event (master, ospf6_dbdesc_send, on, 0);
724 return;
725 }
726
727 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000728 zlog_debug ("Not duplicate dbdesc in state %s",
729 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000730 thread_add_event (master, seqnumber_mismatch, on, 0);
731 return;
732
733 default:
734 assert (0);
735 break;
paul718e3742002-12-13 20:15:29 +0000736 }
737
hasso508e53e2004-05-18 18:57:06 +0000738 /* Process LSA headers */
739 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
740 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
741 p += sizeof (struct ospf6_lsa_header))
742 {
743 struct ospf6_lsa *his, *mine;
744 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000745
hasso508e53e2004-05-18 18:57:06 +0000746 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000747
748 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000749 {
hasso6452df02004-08-15 05:52:07 +0000750 case OSPF6_SCOPE_LINKLOCAL:
751 lsdb = on->ospf6_if->lsdb;
752 break;
753 case OSPF6_SCOPE_AREA:
754 lsdb = on->ospf6_if->area->lsdb;
755 break;
756 case OSPF6_SCOPE_AS:
757 lsdb = on->ospf6_if->area->ospf6->lsdb;
758 break;
759 case OSPF6_SCOPE_RESERVED:
760 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000761 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000762 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000763 continue;
764 break;
hasso508e53e2004-05-18 18:57:06 +0000765 }
766
hasso6452df02004-08-15 05:52:07 +0000767 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
768 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000769 {
770 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000771 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000772 ospf6_lsa_delete (his);
773 thread_add_event (master, seqnumber_mismatch, on, 0);
774 return;
775 }
776
777 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
778 his->header->adv_router, lsdb);
779 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
780 {
hasso6452df02004-08-15 05:52:07 +0000781 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000782 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000783 ospf6_lsdb_add (his, on->request_list);
784 }
785 else
786 ospf6_lsa_delete (his);
787 }
788
789 if (p != OSPF6_MESSAGE_END (oh))
790 {
791 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000792 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000793 }
794
795 /* Set sequence number to Master's */
796 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
797
798 /* schedule send lsreq */
799 if (on->thread_send_lsreq == NULL)
800 on->thread_send_lsreq =
801 thread_add_event (master, ospf6_lsreq_send, on, 0);
802
803 THREAD_OFF (on->thread_send_dbdesc);
804 on->thread_send_dbdesc =
805 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
806
807 /* save last received dbdesc */
808 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000809}
810
Paul Jakma6ac29a52008-08-15 13:45:30 +0100811static void
hasso508e53e2004-05-18 18:57:06 +0000812ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
813 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000814{
hasso508e53e2004-05-18 18:57:06 +0000815 struct ospf6_neighbor *on;
816 struct ospf6_dbdesc *dbdesc;
817
818 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
819 return;
820
821 on = ospf6_neighbor_lookup (oh->router_id, oi);
822 if (on == NULL)
823 {
824 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000825 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000826 return;
827 }
828
hasso508e53e2004-05-18 18:57:06 +0000829 dbdesc = (struct ospf6_dbdesc *)
830 ((caddr_t) oh + sizeof (struct ospf6_header));
831
832 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400833 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000834 {
835 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000836 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000837 return;
838 }
839
840 if (dbdesc->reserved1 || dbdesc->reserved2)
841 {
842 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000843 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
844 on->name);
hasso508e53e2004-05-18 18:57:06 +0000845 dbdesc->reserved1 = 0;
846 dbdesc->reserved2 = 0;
847 }
848
849 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
850 ospf6_dbdesc_recv_master (oh, on);
851 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
852 ospf6_dbdesc_recv_slave (oh, on);
853 else
854 {
855 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000856 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000857 }
858}
859
Paul Jakma6ac29a52008-08-15 13:45:30 +0100860static void
hasso508e53e2004-05-18 18:57:06 +0000861ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
862 struct ospf6_interface *oi, struct ospf6_header *oh)
863{
864 struct ospf6_neighbor *on;
865 char *p;
866 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000867 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000868 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000869
hasso508e53e2004-05-18 18:57:06 +0000870 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
871 return;
paul718e3742002-12-13 20:15:29 +0000872
hasso508e53e2004-05-18 18:57:06 +0000873 on = ospf6_neighbor_lookup (oh->router_id, oi);
874 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000875 {
hasso508e53e2004-05-18 18:57:06 +0000876 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000877 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000878 return;
879 }
880
hasso508e53e2004-05-18 18:57:06 +0000881 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
882 on->state != OSPF6_NEIGHBOR_LOADING &&
883 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000884 {
hasso508e53e2004-05-18 18:57:06 +0000885 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000886 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000887 return;
888 }
889
hasso508e53e2004-05-18 18:57:06 +0000890 /* Process each request */
891 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
892 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
893 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000894 {
hasso508e53e2004-05-18 18:57:06 +0000895 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000896
897 switch (OSPF6_LSA_SCOPE (e->type))
898 {
899 case OSPF6_SCOPE_LINKLOCAL:
900 lsdb = on->ospf6_if->lsdb;
901 break;
902 case OSPF6_SCOPE_AREA:
903 lsdb = on->ospf6_if->area->lsdb;
904 break;
905 case OSPF6_SCOPE_AS:
906 lsdb = on->ospf6_if->area->ospf6->lsdb;
907 break;
908 default:
909 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000910 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000911 continue;
912 break;
913 }
paul718e3742002-12-13 20:15:29 +0000914
hasso508e53e2004-05-18 18:57:06 +0000915 /* Find database copy */
916 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
917 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000918 {
hasso508e53e2004-05-18 18:57:06 +0000919 char id[16], adv_router[16];
920 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
921 {
922 inet_ntop (AF_INET, &e->id, id, sizeof (id));
923 inet_ntop (AF_INET, &e->adv_router, adv_router,
924 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000925 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
926 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000927 }
928 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000929 return;
930 }
931
hasso508e53e2004-05-18 18:57:06 +0000932 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000933 }
934
hasso508e53e2004-05-18 18:57:06 +0000935 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000936 {
hasso508e53e2004-05-18 18:57:06 +0000937 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000938 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000939 }
940
hasso508e53e2004-05-18 18:57:06 +0000941 /* schedule send lsupdate */
942 THREAD_OFF (on->thread_send_lsupdate);
943 on->thread_send_lsupdate =
944 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000945}
946
Paul Jakma6ac29a52008-08-15 13:45:30 +0100947static void
hasso508e53e2004-05-18 18:57:06 +0000948ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
949 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000950{
hasso508e53e2004-05-18 18:57:06 +0000951 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +0000952 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000953 unsigned long num;
954 char *p;
paul718e3742002-12-13 20:15:29 +0000955
hasso508e53e2004-05-18 18:57:06 +0000956 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
957 return;
paul718e3742002-12-13 20:15:29 +0000958
hasso508e53e2004-05-18 18:57:06 +0000959 on = ospf6_neighbor_lookup (oh->router_id, oi);
960 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000961 {
hasso508e53e2004-05-18 18:57:06 +0000962 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000963 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000964 return;
965 }
966
hasso508e53e2004-05-18 18:57:06 +0000967 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
968 on->state != OSPF6_NEIGHBOR_LOADING &&
969 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000970 {
hasso508e53e2004-05-18 18:57:06 +0000971 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000972 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000973 return;
974 }
975
hasso508e53e2004-05-18 18:57:06 +0000976 lsupdate = (struct ospf6_lsupdate *)
977 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000978
hasso508e53e2004-05-18 18:57:06 +0000979 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +0000980
hasso508e53e2004-05-18 18:57:06 +0000981 /* Process LSAs */
982 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
983 p < OSPF6_MESSAGE_END (oh) &&
984 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
985 p += OSPF6_LSA_SIZE (p))
986 {
987 if (num == 0)
988 break;
989 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
990 {
991 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000992 zlog_debug ("Malformed LSA length, quit processing");
hasso508e53e2004-05-18 18:57:06 +0000993 break;
994 }
995
hasso6452df02004-08-15 05:52:07 +0000996 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000997 num--;
998 }
999
1000 if (num != 0)
1001 {
1002 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001003 zlog_debug ("Malformed LSA number or LSA length");
hasso508e53e2004-05-18 18:57:06 +00001004 }
1005 if (p != OSPF6_MESSAGE_END (oh))
1006 {
1007 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001008 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001009 }
paul718e3742002-12-13 20:15:29 +00001010
1011 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1012 with the proper Link State Update packet(s), the Link state request
1013 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001014 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001015 can be recognized as a response to our previous LS Request */
1016 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1017 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1018 on->state == OSPF6_NEIGHBOR_LOADING))
1019 {
1020 THREAD_OFF (on->thread_send_lsreq);
1021 on->thread_send_lsreq =
1022 thread_add_event (master, ospf6_lsreq_send, on, 0);
1023 }
paul718e3742002-12-13 20:15:29 +00001024}
1025
Paul Jakma6ac29a52008-08-15 13:45:30 +01001026static void
hasso508e53e2004-05-18 18:57:06 +00001027ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1028 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001029{
hasso508e53e2004-05-18 18:57:06 +00001030 struct ospf6_neighbor *on;
1031 char *p;
1032 struct ospf6_lsa *his, *mine;
1033 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001034
hasso508e53e2004-05-18 18:57:06 +00001035 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1036 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
1037 return;
paul718e3742002-12-13 20:15:29 +00001038
hasso508e53e2004-05-18 18:57:06 +00001039 on = ospf6_neighbor_lookup (oh->router_id, oi);
1040 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001041 {
hasso508e53e2004-05-18 18:57:06 +00001042 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001043 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001044 return;
1045 }
1046
hasso508e53e2004-05-18 18:57:06 +00001047 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1048 on->state != OSPF6_NEIGHBOR_LOADING &&
1049 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001050 {
hasso508e53e2004-05-18 18:57:06 +00001051 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001052 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001053 return;
1054 }
1055
hasso508e53e2004-05-18 18:57:06 +00001056 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1057 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1058 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001059 {
hasso508e53e2004-05-18 18:57:06 +00001060 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001061
hasso6452df02004-08-15 05:52:07 +00001062 switch (OSPF6_LSA_SCOPE (his->header->type))
1063 {
1064 case OSPF6_SCOPE_LINKLOCAL:
1065 lsdb = on->ospf6_if->lsdb;
1066 break;
1067 case OSPF6_SCOPE_AREA:
1068 lsdb = on->ospf6_if->area->lsdb;
1069 break;
1070 case OSPF6_SCOPE_AS:
1071 lsdb = on->ospf6_if->area->ospf6->lsdb;
1072 break;
1073 case OSPF6_SCOPE_RESERVED:
1074 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001075 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001076 ospf6_lsa_delete (his);
1077 continue;
1078 break;
1079 }
1080
1081 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001082 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001083
1084 /* Find database copy */
1085 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1086 his->header->adv_router, lsdb);
1087 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001088 {
hasso508e53e2004-05-18 18:57:06 +00001089 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001090 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001091 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001092 continue;
1093 }
1094
hasso508e53e2004-05-18 18:57:06 +00001095 /* Check if the LSA is on his retrans-list */
1096 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1097 his->header->adv_router, on->retrans_list);
1098 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001099 {
hasso508e53e2004-05-18 18:57:06 +00001100 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001101 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001102 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001103 continue;
1104 }
1105
hasso508e53e2004-05-18 18:57:06 +00001106 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001107 {
hasso508e53e2004-05-18 18:57:06 +00001108 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001109 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001110 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001111 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001112 ospf6_lsa_delete (his);
1113 continue;
paul718e3742002-12-13 20:15:29 +00001114 }
1115
hasso6452df02004-08-15 05:52:07 +00001116 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001117 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1118 on->name);
hasso508e53e2004-05-18 18:57:06 +00001119
Paul Jakma932bf192006-05-15 10:42:24 +00001120 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001121 if (OSPF6_LSA_IS_MAXAGE (mine))
1122 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001123 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001124 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001125 }
1126
hasso508e53e2004-05-18 18:57:06 +00001127 if (p != OSPF6_MESSAGE_END (oh))
1128 {
1129 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001130 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001131 }
paul718e3742002-12-13 20:15:29 +00001132}
1133
Paul Jakma6ac29a52008-08-15 13:45:30 +01001134static u_char *recvbuf = NULL;
1135static u_char *sendbuf = NULL;
1136static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001137
1138int
paul0c083ee2004-10-10 12:54:58 +00001139ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001140{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001141 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001142
1143 if (size <= iobuflen)
1144 return iobuflen;
1145
1146 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1147 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1148 if (recvnew == NULL || sendnew == NULL)
1149 {
hassob596c712004-07-09 18:33:43 +00001150 if (recvnew)
1151 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1152 if (sendnew)
1153 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001154 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001155 return iobuflen;
1156 }
1157
1158 if (recvbuf)
1159 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1160 if (sendbuf)
1161 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1162 recvbuf = recvnew;
1163 sendbuf = sendnew;
1164 iobuflen = size;
1165
1166 return iobuflen;
1167}
paul718e3742002-12-13 20:15:29 +00001168
Tom Goffae2254a2010-11-10 13:01:41 -08001169void
1170ospf6_message_terminate (void)
1171{
1172 if (recvbuf)
1173 {
1174 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1175 recvbuf = NULL;
1176 }
1177
1178 if (sendbuf)
1179 {
1180 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1181 sendbuf = NULL;
1182 }
1183
1184 iobuflen = 0;
1185}
1186
paul718e3742002-12-13 20:15:29 +00001187int
1188ospf6_receive (struct thread *thread)
1189{
paul0c083ee2004-10-10 12:54:58 +00001190 int sockfd;
1191 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001192 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001193 struct in6_addr src, dst;
1194 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001195 struct iovec iovector[2];
1196 struct ospf6_interface *oi;
1197 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001198
1199 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001200 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001201 thread_add_read (master, ospf6_receive, NULL, sockfd);
1202
1203 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001204 memset (&src, 0, sizeof (src));
1205 memset (&dst, 0, sizeof (dst));
1206 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001207 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001208 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001209 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001210 iovector[1].iov_base = NULL;
1211 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001212
1213 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001214 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001215 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001216 {
hasso508e53e2004-05-18 18:57:06 +00001217 zlog_err ("Excess message read");
1218 return 0;
1219 }
1220 else if (len < sizeof (struct ospf6_header))
1221 {
1222 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001223 return 0;
1224 }
1225
hasso508e53e2004-05-18 18:57:06 +00001226 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1227 if (oi == NULL || oi->area == NULL)
1228 {
hassoc6487d62004-12-24 06:00:11 +00001229 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001230 return 0;
1231 }
1232
1233 oh = (struct ospf6_header *) recvbuf;
1234
1235 /* Log */
1236 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1237 {
1238 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1239 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001240 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001241 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001242 zlog_debug (" src: %s", srcname);
1243 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001244 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001245 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001246
1247 switch (oh->type)
1248 {
1249 case OSPF6_MESSAGE_TYPE_HELLO:
1250 ospf6_hello_print (oh);
1251 break;
1252 case OSPF6_MESSAGE_TYPE_DBDESC:
1253 ospf6_dbdesc_print (oh);
1254 break;
1255 case OSPF6_MESSAGE_TYPE_LSREQ:
1256 ospf6_lsreq_print (oh);
1257 break;
1258 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1259 ospf6_lsupdate_print (oh);
1260 break;
1261 case OSPF6_MESSAGE_TYPE_LSACK:
1262 ospf6_lsack_print (oh);
1263 break;
1264 default:
hassoc6487d62004-12-24 06:00:11 +00001265 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001266 break;
1267 }
1268 }
1269
1270 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1271 {
1272 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001273 zlog_debug ("Ignore message on passive interface %s",
hasso508e53e2004-05-18 18:57:06 +00001274 oi->interface->name);
1275 return 0;
1276 }
1277
1278 switch (oh->type)
1279 {
1280 case OSPF6_MESSAGE_TYPE_HELLO:
1281 ospf6_hello_recv (&src, &dst, oi, oh);
1282 break;
1283
1284 case OSPF6_MESSAGE_TYPE_DBDESC:
1285 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1286 break;
1287
1288 case OSPF6_MESSAGE_TYPE_LSREQ:
1289 ospf6_lsreq_recv (&src, &dst, oi, oh);
1290 break;
1291
1292 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1293 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1294 break;
1295
1296 case OSPF6_MESSAGE_TYPE_LSACK:
1297 ospf6_lsack_recv (&src, &dst, oi, oh);
1298 break;
1299
1300 default:
1301 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001302 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001303 break;
1304 }
1305
1306 return 0;
1307}
1308
Paul Jakma6ac29a52008-08-15 13:45:30 +01001309static void
hasso508e53e2004-05-18 18:57:06 +00001310ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1311 struct ospf6_interface *oi, struct ospf6_header *oh)
1312{
1313 int len;
1314 char srcname[64], dstname[64];
1315 struct iovec iovector[2];
1316
1317 /* initialize */
1318 iovector[0].iov_base = (caddr_t) oh;
1319 iovector[0].iov_len = ntohs (oh->length);
1320 iovector[1].iov_base = NULL;
1321 iovector[1].iov_len = 0;
1322
1323 /* fill OSPF header */
1324 oh->version = OSPFV3_VERSION;
1325 /* message type must be set before */
1326 /* message length must be set before */
1327 oh->router_id = oi->area->ospf6->router_id;
1328 oh->area_id = oi->area->area_id;
1329 /* checksum is calculated by kernel */
1330 oh->instance_id = oi->instance_id;
1331 oh->reserved = 0;
1332
1333 /* Log */
1334 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1335 {
1336 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1337 if (src)
1338 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1339 else
1340 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001341 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001342 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001343 zlog_debug (" src: %s", srcname);
1344 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001345
1346 switch (oh->type)
1347 {
1348 case OSPF6_MESSAGE_TYPE_HELLO:
1349 ospf6_hello_print (oh);
1350 break;
1351 case OSPF6_MESSAGE_TYPE_DBDESC:
1352 ospf6_dbdesc_print (oh);
1353 break;
1354 case OSPF6_MESSAGE_TYPE_LSREQ:
1355 ospf6_lsreq_print (oh);
1356 break;
1357 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1358 ospf6_lsupdate_print (oh);
1359 break;
1360 case OSPF6_MESSAGE_TYPE_LSACK:
1361 ospf6_lsack_print (oh);
1362 break;
1363 default:
hassoc6487d62004-12-24 06:00:11 +00001364 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001365 assert (0);
1366 break;
1367 }
1368 }
1369
1370 /* send message */
1371 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1372 if (len != ntohs (oh->length))
1373 zlog_err ("Could not send entire message");
1374}
1375
1376int
1377ospf6_hello_send (struct thread *thread)
1378{
1379 struct ospf6_interface *oi;
1380 struct ospf6_header *oh;
1381 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001382 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001383 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001384 struct ospf6_neighbor *on;
1385
1386 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1387 oi->thread_send_hello = (struct thread *) NULL;
1388
1389 if (oi->state <= OSPF6_INTERFACE_DOWN)
1390 {
1391 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001392 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001393 oi->interface->name);
1394 return 0;
1395 }
1396
1397 /* set next thread */
1398 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1399 oi, oi->hello_interval);
1400
hasso3b4cd3a2004-05-18 19:28:32 +00001401 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001402 oh = (struct ospf6_header *) sendbuf;
1403 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1404
1405 hello->interface_id = htonl (oi->interface->ifindex);
1406 hello->priority = oi->priority;
1407 hello->options[0] = oi->area->options[0];
1408 hello->options[1] = oi->area->options[1];
1409 hello->options[2] = oi->area->options[2];
1410 hello->hello_interval = htons (oi->hello_interval);
1411 hello->dead_interval = htons (oi->dead_interval);
1412 hello->drouter = oi->drouter;
1413 hello->bdrouter = oi->bdrouter;
1414
Paul Jakma6ac29a52008-08-15 13:45:30 +01001415 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001416
paul1eb8ef22005-04-07 07:30:20 +00001417 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001418 {
hasso508e53e2004-05-18 18:57:06 +00001419 if (on->state < OSPF6_NEIGHBOR_INIT)
1420 continue;
1421
1422 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1423 {
1424 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001425 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001426 break;
1427 }
1428
1429 memcpy (p, &on->router_id, sizeof (u_int32_t));
1430 p += sizeof (u_int32_t);
1431 }
1432
1433 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1434 oh->length = htons (p - sendbuf);
1435
1436 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1437 return 0;
1438}
1439
1440int
1441ospf6_dbdesc_send (struct thread *thread)
1442{
1443 struct ospf6_neighbor *on;
1444 struct ospf6_header *oh;
1445 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001446 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001447 struct ospf6_lsa *lsa;
1448
1449 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1450 on->thread_send_dbdesc = (struct thread *) NULL;
1451
1452 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1453 {
1454 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001455 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1456 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001457 return 0;
1458 }
1459
1460 /* set next thread if master */
1461 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1462 on->thread_send_dbdesc =
1463 thread_add_timer (master, ospf6_dbdesc_send, on,
1464 on->ospf6_if->rxmt_interval);
1465
hasso3b4cd3a2004-05-18 19:28:32 +00001466 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001467 oh = (struct ospf6_header *) sendbuf;
1468 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1469 sizeof (struct ospf6_header));
1470
1471 /* if this is initial one, initialize sequence number for DbDesc */
1472 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1473 {
1474 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001475 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001476 tv.tv_sec = 1;
1477 on->dbdesc_seqnum = tv.tv_sec;
1478 }
1479
1480 dbdesc->options[0] = on->ospf6_if->area->options[0];
1481 dbdesc->options[1] = on->ospf6_if->area->options[1];
1482 dbdesc->options[2] = on->ospf6_if->area->options[2];
1483 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1484 dbdesc->bits = on->dbdesc_bits;
1485 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1486
1487 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001488 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001489 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1490 {
1491 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1492 lsa = ospf6_lsdb_next (lsa))
1493 {
1494 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1495
1496 /* MTU check */
1497 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1498 on->ospf6_if->ifmtu)
1499 {
1500 ospf6_lsa_unlock (lsa);
1501 break;
1502 }
1503 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1504 p += sizeof (struct ospf6_lsa_header);
1505 }
1506 }
1507
1508 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1509 oh->length = htons (p - sendbuf);
1510
1511 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1512 on->ospf6_if, oh);
1513 return 0;
1514}
1515
1516int
1517ospf6_dbdesc_send_newone (struct thread *thread)
1518{
1519 struct ospf6_neighbor *on;
1520 struct ospf6_lsa *lsa;
1521 unsigned int size = 0;
1522
1523 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001524 ospf6_lsdb_remove_all (on->dbdesc_list);
1525
1526 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1527 so that ospf6_send_dbdesc () can send those LSAs */
1528 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1529 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1530 lsa = ospf6_lsdb_next (lsa))
1531 {
1532 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1533 {
1534 ospf6_lsa_unlock (lsa);
1535 break;
1536 }
1537
hasso508e53e2004-05-18 18:57:06 +00001538 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1539 ospf6_lsdb_remove (lsa, on->summary_list);
1540 size += sizeof (struct ospf6_lsa_header);
1541 }
1542
1543 if (on->summary_list->count == 0)
1544 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1545
1546 /* If slave, More bit check must be done here */
1547 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1548 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1549 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1550 thread_add_event (master, exchange_done, on, 0);
1551
1552 thread_execute (master, ospf6_dbdesc_send, on, 0);
1553 return 0;
1554}
1555
1556int
1557ospf6_lsreq_send (struct thread *thread)
1558{
1559 struct ospf6_neighbor *on;
1560 struct ospf6_header *oh;
1561 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001562 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001563 struct ospf6_lsa *lsa;
1564
1565 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1566 on->thread_send_lsreq = (struct thread *) NULL;
1567
1568 /* LSReq will be sent only in ExStart or Loading */
1569 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1570 on->state != OSPF6_NEIGHBOR_LOADING)
1571 {
1572 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001573 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1574 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001575 return 0;
1576 }
1577
1578 /* schedule loading_done if request list is empty */
1579 if (on->request_list->count == 0)
1580 {
1581 thread_add_event (master, loading_done, on, 0);
1582 return 0;
1583 }
1584
1585 /* set next thread */
1586 on->thread_send_lsreq =
1587 thread_add_timer (master, ospf6_lsreq_send, on,
1588 on->ospf6_if->rxmt_interval);
1589
hasso3b4cd3a2004-05-18 19:28:32 +00001590 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001591 oh = (struct ospf6_header *) sendbuf;
1592
1593 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001594 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001595 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1596 lsa = ospf6_lsdb_next (lsa))
1597 {
1598 /* MTU check */
1599 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
1600 {
1601 ospf6_lsa_unlock (lsa);
1602 break;
1603 }
1604
1605 e = (struct ospf6_lsreq_entry *) p;
1606 e->type = lsa->header->type;
1607 e->id = lsa->header->id;
1608 e->adv_router = lsa->header->adv_router;
1609 p += sizeof (struct ospf6_lsreq_entry);
1610 }
1611
1612 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1613 oh->length = htons (p - sendbuf);
1614
1615 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1616 on->ospf6_if, oh);
1617 return 0;
1618}
1619
1620int
1621ospf6_lsupdate_send_neighbor (struct thread *thread)
1622{
1623 struct ospf6_neighbor *on;
1624 struct ospf6_header *oh;
1625 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001626 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001627 int num;
1628 struct ospf6_lsa *lsa;
1629
1630 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1631 on->thread_send_lsupdate = (struct thread *) NULL;
1632
hasso6452df02004-08-15 05:52:07 +00001633 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001634 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001635
hasso508e53e2004-05-18 18:57:06 +00001636 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1637 {
1638 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001639 zlog_debug ("Quit to send (neighbor state %s)",
1640 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001641 return 0;
1642 }
1643
1644 /* if we have nothing to send, return */
1645 if (on->lsupdate_list->count == 0 &&
1646 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001647 {
1648 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001649 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001650 return 0;
1651 }
hasso508e53e2004-05-18 18:57:06 +00001652
hasso3b4cd3a2004-05-18 19:28:32 +00001653 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001654 oh = (struct ospf6_header *) sendbuf;
1655 lsupdate = (struct ospf6_lsupdate *)
1656 ((caddr_t) oh + sizeof (struct ospf6_header));
1657
Paul Jakma6ac29a52008-08-15 13:45:30 +01001658 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001659 num = 0;
1660
1661 /* lsupdate_list lists those LSA which doesn't need to be
1662 retransmitted. remove those from the list */
1663 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1664 lsa = ospf6_lsdb_next (lsa))
1665 {
1666 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001667 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
1668 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001669 {
1670 ospf6_lsa_unlock (lsa);
1671 break;
1672 }
1673
hasso508e53e2004-05-18 18:57:06 +00001674 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1675 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1676 p += OSPF6_LSA_SIZE (lsa->header);
1677 num++;
1678
1679 assert (lsa->lock == 2);
1680 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1681 }
1682
1683 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1684 lsa = ospf6_lsdb_next (lsa))
1685 {
1686 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001687 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
1688 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001689 {
1690 ospf6_lsa_unlock (lsa);
1691 break;
1692 }
1693
hasso508e53e2004-05-18 18:57:06 +00001694 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1695 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1696 p += OSPF6_LSA_SIZE (lsa->header);
1697 num++;
1698 }
1699
1700 lsupdate->lsa_number = htonl (num);
1701
1702 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1703 oh->length = htons (p - sendbuf);
1704
1705 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1706 on->ospf6_if, oh);
1707
1708 if (on->lsupdate_list->count != 0 ||
1709 on->retrans_list->count != 0)
1710 {
1711 if (on->lsupdate_list->count != 0)
1712 on->thread_send_lsupdate =
1713 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1714 else
1715 on->thread_send_lsupdate =
1716 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1717 on->ospf6_if->rxmt_interval);
1718 }
1719
1720 return 0;
1721}
1722
1723int
1724ospf6_lsupdate_send_interface (struct thread *thread)
1725{
1726 struct ospf6_interface *oi;
1727 struct ospf6_header *oh;
1728 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001729 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001730 int num;
1731 struct ospf6_lsa *lsa;
1732
1733 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1734 oi->thread_send_lsupdate = (struct thread *) NULL;
1735
1736 if (oi->state <= OSPF6_INTERFACE_WAITING)
1737 {
1738 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001739 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
1740 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001741 return 0;
1742 }
1743
1744 /* if we have nothing to send, return */
1745 if (oi->lsupdate_list->count == 0)
1746 return 0;
1747
hasso3b4cd3a2004-05-18 19:28:32 +00001748 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001749 oh = (struct ospf6_header *) sendbuf;
1750 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1751 sizeof (struct ospf6_header));
1752
Paul Jakma6ac29a52008-08-15 13:45:30 +01001753 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001754 num = 0;
1755
1756 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1757 lsa = ospf6_lsdb_next (lsa))
1758 {
1759 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001760 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
1761 > oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001762 {
1763 ospf6_lsa_unlock (lsa);
1764 break;
1765 }
1766
hasso508e53e2004-05-18 18:57:06 +00001767 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1768 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1769 p += OSPF6_LSA_SIZE (lsa->header);
1770 num++;
1771
1772 assert (lsa->lock == 2);
1773 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1774 }
1775
1776 lsupdate->lsa_number = htonl (num);
1777
1778 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1779 oh->length = htons (p - sendbuf);
1780
1781 if (oi->state == OSPF6_INTERFACE_DR ||
1782 oi->state == OSPF6_INTERFACE_BDR)
1783 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1784 else
1785 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1786
1787 if (oi->lsupdate_list->count > 0)
1788 {
1789 oi->thread_send_lsupdate =
1790 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1791 }
1792
1793 return 0;
1794}
1795
1796int
1797ospf6_lsack_send_neighbor (struct thread *thread)
1798{
1799 struct ospf6_neighbor *on;
1800 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001801 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001802 struct ospf6_lsa *lsa;
1803
1804 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1805 on->thread_send_lsack = (struct thread *) NULL;
1806
1807 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1808 {
1809 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001810 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
1811 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001812 return 0;
1813 }
1814
1815 /* if we have nothing to send, return */
1816 if (on->lsack_list->count == 0)
1817 return 0;
1818
hasso3b4cd3a2004-05-18 19:28:32 +00001819 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001820 oh = (struct ospf6_header *) sendbuf;
1821
Paul Jakma6ac29a52008-08-15 13:45:30 +01001822 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001823
1824 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1825 lsa = ospf6_lsdb_next (lsa))
1826 {
1827 /* MTU check */
1828 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1829 {
1830 /* if we run out of packet size/space here,
1831 better to try again soon. */
1832 THREAD_OFF (on->thread_send_lsack);
1833 on->thread_send_lsack =
1834 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1835
1836 ospf6_lsa_unlock (lsa);
1837 break;
1838 }
1839
1840 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1841 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1842 p += sizeof (struct ospf6_lsa_header);
1843
1844 assert (lsa->lock == 2);
1845 ospf6_lsdb_remove (lsa, on->lsack_list);
1846 }
1847
1848 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1849 oh->length = htons (p - sendbuf);
1850
1851 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1852 on->ospf6_if, oh);
1853 return 0;
1854}
1855
1856int
1857ospf6_lsack_send_interface (struct thread *thread)
1858{
1859 struct ospf6_interface *oi;
1860 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001861 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001862 struct ospf6_lsa *lsa;
1863
1864 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1865 oi->thread_send_lsack = (struct thread *) NULL;
1866
1867 if (oi->state <= OSPF6_INTERFACE_WAITING)
1868 {
1869 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001870 zlog_debug ("Quit to send LSAck to interface %s state %s",
1871 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001872 return 0;
1873 }
1874
1875 /* if we have nothing to send, return */
1876 if (oi->lsack_list->count == 0)
1877 return 0;
1878
hasso3b4cd3a2004-05-18 19:28:32 +00001879 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001880 oh = (struct ospf6_header *) sendbuf;
1881
Paul Jakma6ac29a52008-08-15 13:45:30 +01001882 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001883
1884 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1885 lsa = ospf6_lsdb_next (lsa))
1886 {
1887 /* MTU check */
1888 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
1889 {
1890 /* if we run out of packet size/space here,
1891 better to try again soon. */
1892 THREAD_OFF (oi->thread_send_lsack);
1893 oi->thread_send_lsack =
1894 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1895
1896 ospf6_lsa_unlock (lsa);
1897 break;
1898 }
1899
1900 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1901 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1902 p += sizeof (struct ospf6_lsa_header);
1903
1904 assert (lsa->lock == 2);
1905 ospf6_lsdb_remove (lsa, oi->lsack_list);
1906 }
1907
1908 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1909 oh->length = htons (p - sendbuf);
1910
1911 if (oi->state == OSPF6_INTERFACE_DR ||
1912 oi->state == OSPF6_INTERFACE_BDR)
1913 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1914 else
1915 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1916
1917 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1918 {
1919 oi->thread_send_lsack =
1920 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1921 }
paul718e3742002-12-13 20:15:29 +00001922
1923 return 0;
1924}
1925
1926
hasso508e53e2004-05-18 18:57:06 +00001927/* Commands */
1928DEFUN (debug_ospf6_message,
1929 debug_ospf6_message_cmd,
1930 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1931 DEBUG_STR
1932 OSPF6_STR
1933 "Debug OSPFv3 message\n"
1934 "Debug Unknown message\n"
1935 "Debug Hello message\n"
1936 "Debug Database Description message\n"
1937 "Debug Link State Request message\n"
1938 "Debug Link State Update message\n"
1939 "Debug Link State Acknowledgement message\n"
1940 "Debug All message\n"
1941 )
paul718e3742002-12-13 20:15:29 +00001942{
hasso508e53e2004-05-18 18:57:06 +00001943 unsigned char level = 0;
1944 int type = 0;
paul718e3742002-12-13 20:15:29 +00001945 int i;
1946
hasso508e53e2004-05-18 18:57:06 +00001947 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001948
hasso508e53e2004-05-18 18:57:06 +00001949 /* check type */
1950 if (! strncmp (argv[0], "u", 1))
1951 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1952 else if (! strncmp (argv[0], "h", 1))
1953 type = OSPF6_MESSAGE_TYPE_HELLO;
1954 else if (! strncmp (argv[0], "d", 1))
1955 type = OSPF6_MESSAGE_TYPE_DBDESC;
1956 else if (! strncmp (argv[0], "lsr", 3))
1957 type = OSPF6_MESSAGE_TYPE_LSREQ;
1958 else if (! strncmp (argv[0], "lsu", 3))
1959 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1960 else if (! strncmp (argv[0], "lsa", 3))
1961 type = OSPF6_MESSAGE_TYPE_LSACK;
1962 else if (! strncmp (argv[0], "a", 1))
1963 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001964
hasso508e53e2004-05-18 18:57:06 +00001965 if (argc == 1)
1966 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1967 else if (! strncmp (argv[1], "s", 1))
1968 level = OSPF6_DEBUG_MESSAGE_SEND;
1969 else if (! strncmp (argv[1], "r", 1))
1970 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001971
hasso508e53e2004-05-18 18:57:06 +00001972 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001973 {
hasso508e53e2004-05-18 18:57:06 +00001974 for (i = 0; i < 6; i++)
1975 OSPF6_DEBUG_MESSAGE_ON (i, level);
1976 }
1977 else
1978 OSPF6_DEBUG_MESSAGE_ON (type, level);
1979
1980 return CMD_SUCCESS;
1981}
1982
1983ALIAS (debug_ospf6_message,
1984 debug_ospf6_message_sendrecv_cmd,
1985 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1986 DEBUG_STR
1987 OSPF6_STR
1988 "Debug OSPFv3 message\n"
1989 "Debug Unknown message\n"
1990 "Debug Hello message\n"
1991 "Debug Database Description message\n"
1992 "Debug Link State Request message\n"
1993 "Debug Link State Update message\n"
1994 "Debug Link State Acknowledgement message\n"
1995 "Debug All message\n"
1996 "Debug only sending message\n"
1997 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01001998 )
hasso508e53e2004-05-18 18:57:06 +00001999
2000
2001DEFUN (no_debug_ospf6_message,
2002 no_debug_ospf6_message_cmd,
2003 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2004 NO_STR
2005 DEBUG_STR
2006 OSPF6_STR
2007 "Debug OSPFv3 message\n"
2008 "Debug Unknown message\n"
2009 "Debug Hello message\n"
2010 "Debug Database Description message\n"
2011 "Debug Link State Request message\n"
2012 "Debug Link State Update message\n"
2013 "Debug Link State Acknowledgement message\n"
2014 "Debug All message\n"
2015 )
2016{
2017 unsigned char level = 0;
2018 int type = 0;
2019 int i;
2020
2021 assert (argc > 0);
2022
2023 /* check type */
2024 if (! strncmp (argv[0], "u", 1))
2025 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2026 else if (! strncmp (argv[0], "h", 1))
2027 type = OSPF6_MESSAGE_TYPE_HELLO;
2028 else if (! strncmp (argv[0], "d", 1))
2029 type = OSPF6_MESSAGE_TYPE_DBDESC;
2030 else if (! strncmp (argv[0], "lsr", 3))
2031 type = OSPF6_MESSAGE_TYPE_LSREQ;
2032 else if (! strncmp (argv[0], "lsu", 3))
2033 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2034 else if (! strncmp (argv[0], "lsa", 3))
2035 type = OSPF6_MESSAGE_TYPE_LSACK;
2036 else if (! strncmp (argv[0], "a", 1))
2037 type = OSPF6_MESSAGE_TYPE_ALL;
2038
2039 if (argc == 1)
2040 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2041 else if (! strncmp (argv[1], "s", 1))
2042 level = OSPF6_DEBUG_MESSAGE_SEND;
2043 else if (! strncmp (argv[1], "r", 1))
2044 level = OSPF6_DEBUG_MESSAGE_RECV;
2045
2046 if (type == OSPF6_MESSAGE_TYPE_ALL)
2047 {
2048 for (i = 0; i < 6; i++)
2049 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2050 }
2051 else
2052 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2053
2054 return CMD_SUCCESS;
2055}
2056
2057ALIAS (no_debug_ospf6_message,
2058 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002059 "no debug ospf6 message "
2060 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002061 NO_STR
2062 DEBUG_STR
2063 OSPF6_STR
2064 "Debug OSPFv3 message\n"
2065 "Debug Unknown message\n"
2066 "Debug Hello message\n"
2067 "Debug Database Description message\n"
2068 "Debug Link State Request message\n"
2069 "Debug Link State Update message\n"
2070 "Debug Link State Acknowledgement message\n"
2071 "Debug All message\n"
2072 "Debug only sending message\n"
2073 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002074 )
hasso508e53e2004-05-18 18:57:06 +00002075
2076int
2077config_write_ospf6_debug_message (struct vty *vty)
2078{
paul0c083ee2004-10-10 12:54:58 +00002079 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002080 "lsreq", "lsupdate", "lsack"};
2081 unsigned char s = 0, r = 0;
2082 int i;
2083
2084 for (i = 0; i < 6; i++)
2085 {
2086 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2087 s |= 1 << i;
2088 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2089 r |= 1 << i;
2090 }
2091
2092 if (s == 0x3f && r == 0x3f)
2093 {
hasso049207c2004-08-04 20:02:13 +00002094 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002095 return 0;
2096 }
2097
hasso508e53e2004-05-18 18:57:06 +00002098 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002099 {
hasso049207c2004-08-04 20:02:13 +00002100 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002101 return 0;
2102 }
2103 else if (s == 0 && r == 0x3f)
2104 {
hasso049207c2004-08-04 20:02:13 +00002105 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002106 return 0;
paul718e3742002-12-13 20:15:29 +00002107 }
2108
hasso508e53e2004-05-18 18:57:06 +00002109 /* Unknown message is logged by default */
2110 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2111 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002112 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002113 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002114 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002115 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002116 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002117
hasso508e53e2004-05-18 18:57:06 +00002118 for (i = 1; i < 6; i++)
2119 {
2120 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2121 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002122 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002123 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2124 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002125 VNL);
hasso508e53e2004-05-18 18:57:06 +00002126 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2127 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002128 VNL);
hasso508e53e2004-05-18 18:57:06 +00002129 }
paul718e3742002-12-13 20:15:29 +00002130
2131 return 0;
2132}
2133
paul718e3742002-12-13 20:15:29 +00002134void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002135install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002136{
hasso508e53e2004-05-18 18:57:06 +00002137 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2138 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2139 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2140 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2141 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2142 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2143 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2144 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002145}
2146
paul718e3742002-12-13 20:15:29 +00002147