blob: a4e5d67409895b1b2d0723017ce0bf986ceeaa6a [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
275void
276ospf6_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;
325 on->ifindex = ntohl (hello->interface_id);
326 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
paul718e3742002-12-13 20:15:29 +0000327 }
328
329 /* 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
811void
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
829 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
830 {
831 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000832 zlog_debug ("Seems to be from Secondary I/F of the neighbor, ignore");
hasso508e53e2004-05-18 18:57:06 +0000833 return;
834 }
835
836 dbdesc = (struct ospf6_dbdesc *)
837 ((caddr_t) oh + sizeof (struct ospf6_header));
838
839 /* Interface MTU check */
840 if (ntohs (dbdesc->ifmtu) != oi->ifmtu)
841 {
842 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000843 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000844 return;
845 }
846
847 if (dbdesc->reserved1 || dbdesc->reserved2)
848 {
849 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000850 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
851 on->name);
hasso508e53e2004-05-18 18:57:06 +0000852 dbdesc->reserved1 = 0;
853 dbdesc->reserved2 = 0;
854 }
855
856 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
857 ospf6_dbdesc_recv_master (oh, on);
858 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
859 ospf6_dbdesc_recv_slave (oh, on);
860 else
861 {
862 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000863 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000864 }
865}
866
867void
868ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
869 struct ospf6_interface *oi, struct ospf6_header *oh)
870{
871 struct ospf6_neighbor *on;
872 char *p;
873 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000874 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000875 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000876
hasso508e53e2004-05-18 18:57:06 +0000877 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
878 return;
paul718e3742002-12-13 20:15:29 +0000879
hasso508e53e2004-05-18 18:57:06 +0000880 on = ospf6_neighbor_lookup (oh->router_id, oi);
881 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000882 {
hasso508e53e2004-05-18 18:57:06 +0000883 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000884 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000885 return;
886 }
887
hasso508e53e2004-05-18 18:57:06 +0000888 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +0000889 {
hasso508e53e2004-05-18 18:57:06 +0000890 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000891 zlog_debug ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +0000892 return;
893 }
894
hasso508e53e2004-05-18 18:57:06 +0000895 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
896 on->state != OSPF6_NEIGHBOR_LOADING &&
897 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000898 {
hasso508e53e2004-05-18 18:57:06 +0000899 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000900 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000901 return;
902 }
903
hasso508e53e2004-05-18 18:57:06 +0000904 /* Process each request */
905 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
906 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
907 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000908 {
hasso508e53e2004-05-18 18:57:06 +0000909 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000910
911 switch (OSPF6_LSA_SCOPE (e->type))
912 {
913 case OSPF6_SCOPE_LINKLOCAL:
914 lsdb = on->ospf6_if->lsdb;
915 break;
916 case OSPF6_SCOPE_AREA:
917 lsdb = on->ospf6_if->area->lsdb;
918 break;
919 case OSPF6_SCOPE_AS:
920 lsdb = on->ospf6_if->area->ospf6->lsdb;
921 break;
922 default:
923 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000924 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000925 continue;
926 break;
927 }
paul718e3742002-12-13 20:15:29 +0000928
hasso508e53e2004-05-18 18:57:06 +0000929 /* Find database copy */
930 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
931 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000932 {
hasso508e53e2004-05-18 18:57:06 +0000933 char id[16], adv_router[16];
934 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
935 {
936 inet_ntop (AF_INET, &e->id, id, sizeof (id));
937 inet_ntop (AF_INET, &e->adv_router, adv_router,
938 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000939 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
940 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000941 }
942 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000943 return;
944 }
945
hasso508e53e2004-05-18 18:57:06 +0000946 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000947 }
948
hasso508e53e2004-05-18 18:57:06 +0000949 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000950 {
hasso508e53e2004-05-18 18:57:06 +0000951 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000952 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000953 }
954
hasso508e53e2004-05-18 18:57:06 +0000955 /* schedule send lsupdate */
956 THREAD_OFF (on->thread_send_lsupdate);
957 on->thread_send_lsupdate =
958 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000959}
960
961void
hasso508e53e2004-05-18 18:57:06 +0000962ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
963 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000964{
hasso508e53e2004-05-18 18:57:06 +0000965 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +0000966 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000967 unsigned long num;
968 char *p;
paul718e3742002-12-13 20:15:29 +0000969
hasso508e53e2004-05-18 18:57:06 +0000970 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
971 return;
paul718e3742002-12-13 20:15:29 +0000972
hasso508e53e2004-05-18 18:57:06 +0000973 on = ospf6_neighbor_lookup (oh->router_id, oi);
974 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000975 {
hasso508e53e2004-05-18 18:57:06 +0000976 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000977 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000978 return;
979 }
980
hasso508e53e2004-05-18 18:57:06 +0000981 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +0000982 {
hasso508e53e2004-05-18 18:57:06 +0000983 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000984 zlog_debug ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +0000985 return;
986 }
987
hasso508e53e2004-05-18 18:57:06 +0000988 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
989 on->state != OSPF6_NEIGHBOR_LOADING &&
990 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000991 {
hasso508e53e2004-05-18 18:57:06 +0000992 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000993 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000994 return;
995 }
996
hasso508e53e2004-05-18 18:57:06 +0000997 lsupdate = (struct ospf6_lsupdate *)
998 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000999
hasso508e53e2004-05-18 18:57:06 +00001000 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +00001001
hasso508e53e2004-05-18 18:57:06 +00001002 /* Process LSAs */
1003 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1004 p < OSPF6_MESSAGE_END (oh) &&
1005 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1006 p += OSPF6_LSA_SIZE (p))
1007 {
1008 if (num == 0)
1009 break;
1010 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
1011 {
1012 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001013 zlog_debug ("Malformed LSA length, quit processing");
hasso508e53e2004-05-18 18:57:06 +00001014 break;
1015 }
1016
hasso6452df02004-08-15 05:52:07 +00001017 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001018 num--;
1019 }
1020
1021 if (num != 0)
1022 {
1023 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001024 zlog_debug ("Malformed LSA number or LSA length");
hasso508e53e2004-05-18 18:57:06 +00001025 }
1026 if (p != OSPF6_MESSAGE_END (oh))
1027 {
1028 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001029 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001030 }
paul718e3742002-12-13 20:15:29 +00001031
1032 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1033 with the proper Link State Update packet(s), the Link state request
1034 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001035 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001036 can be recognized as a response to our previous LS Request */
1037 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1038 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1039 on->state == OSPF6_NEIGHBOR_LOADING))
1040 {
1041 THREAD_OFF (on->thread_send_lsreq);
1042 on->thread_send_lsreq =
1043 thread_add_event (master, ospf6_lsreq_send, on, 0);
1044 }
paul718e3742002-12-13 20:15:29 +00001045}
1046
1047void
hasso508e53e2004-05-18 18:57:06 +00001048ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1049 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001050{
hasso508e53e2004-05-18 18:57:06 +00001051 struct ospf6_neighbor *on;
1052 char *p;
1053 struct ospf6_lsa *his, *mine;
1054 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001055
hasso508e53e2004-05-18 18:57:06 +00001056 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1057 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
1058 return;
paul718e3742002-12-13 20:15:29 +00001059
hasso508e53e2004-05-18 18:57:06 +00001060 on = ospf6_neighbor_lookup (oh->router_id, oi);
1061 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001062 {
hasso508e53e2004-05-18 18:57:06 +00001063 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001064 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001065 return;
1066 }
1067
hasso508e53e2004-05-18 18:57:06 +00001068 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +00001069 {
hasso508e53e2004-05-18 18:57:06 +00001070 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001071 zlog_debug ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +00001072 return;
1073 }
1074
hasso508e53e2004-05-18 18:57:06 +00001075 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1076 on->state != OSPF6_NEIGHBOR_LOADING &&
1077 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001078 {
hasso508e53e2004-05-18 18:57:06 +00001079 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001080 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001081 return;
1082 }
1083
hasso508e53e2004-05-18 18:57:06 +00001084 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1085 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1086 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001087 {
hasso508e53e2004-05-18 18:57:06 +00001088 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001089
hasso6452df02004-08-15 05:52:07 +00001090 switch (OSPF6_LSA_SCOPE (his->header->type))
1091 {
1092 case OSPF6_SCOPE_LINKLOCAL:
1093 lsdb = on->ospf6_if->lsdb;
1094 break;
1095 case OSPF6_SCOPE_AREA:
1096 lsdb = on->ospf6_if->area->lsdb;
1097 break;
1098 case OSPF6_SCOPE_AS:
1099 lsdb = on->ospf6_if->area->ospf6->lsdb;
1100 break;
1101 case OSPF6_SCOPE_RESERVED:
1102 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001103 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001104 ospf6_lsa_delete (his);
1105 continue;
1106 break;
1107 }
1108
1109 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001110 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001111
1112 /* Find database copy */
1113 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1114 his->header->adv_router, lsdb);
1115 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001116 {
hasso508e53e2004-05-18 18:57:06 +00001117 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001118 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001119 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001120 continue;
1121 }
1122
hasso508e53e2004-05-18 18:57:06 +00001123 /* Check if the LSA is on his retrans-list */
1124 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1125 his->header->adv_router, on->retrans_list);
1126 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001127 {
hasso508e53e2004-05-18 18:57:06 +00001128 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001129 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001130 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001131 continue;
1132 }
1133
hasso508e53e2004-05-18 18:57:06 +00001134 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001135 {
hasso508e53e2004-05-18 18:57:06 +00001136 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001137 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001138 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001139 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001140 ospf6_lsa_delete (his);
1141 continue;
paul718e3742002-12-13 20:15:29 +00001142 }
1143
hasso6452df02004-08-15 05:52:07 +00001144 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001145 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1146 on->name);
hasso508e53e2004-05-18 18:57:06 +00001147
1148 if (OSPF6_LSA_IS_MAXAGE (mine))
1149 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
1150
hasso6452df02004-08-15 05:52:07 +00001151 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001152 ospf6_lsdb_remove (mine, on->retrans_list);
1153 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001154 }
1155
hasso508e53e2004-05-18 18:57:06 +00001156 if (p != OSPF6_MESSAGE_END (oh))
1157 {
1158 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001159 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001160 }
paul718e3742002-12-13 20:15:29 +00001161}
1162
paul0c083ee2004-10-10 12:54:58 +00001163u_char *recvbuf = NULL;
1164u_char *sendbuf = NULL;
1165unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001166
1167int
paul0c083ee2004-10-10 12:54:58 +00001168ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001169{
1170 char *recvnew, *sendnew;
1171
1172 if (size <= iobuflen)
1173 return iobuflen;
1174
1175 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1176 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1177 if (recvnew == NULL || sendnew == NULL)
1178 {
hassob596c712004-07-09 18:33:43 +00001179 if (recvnew)
1180 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1181 if (sendnew)
1182 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001183 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001184 return iobuflen;
1185 }
1186
1187 if (recvbuf)
1188 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1189 if (sendbuf)
1190 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1191 recvbuf = recvnew;
1192 sendbuf = sendnew;
1193 iobuflen = size;
1194
1195 return iobuflen;
1196}
paul718e3742002-12-13 20:15:29 +00001197
1198int
1199ospf6_receive (struct thread *thread)
1200{
paul0c083ee2004-10-10 12:54:58 +00001201 int sockfd;
1202 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001203 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001204 struct in6_addr src, dst;
1205 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001206 struct iovec iovector[2];
1207 struct ospf6_interface *oi;
1208 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001209
1210 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001211 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001212 thread_add_read (master, ospf6_receive, NULL, sockfd);
1213
1214 /* initialize */
hasso3b4cd3a2004-05-18 19:28:32 +00001215 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001216 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001217 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001218 iovector[1].iov_base = NULL;
1219 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001220
1221 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001222 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001223 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001224 {
hasso508e53e2004-05-18 18:57:06 +00001225 zlog_err ("Excess message read");
1226 return 0;
1227 }
1228 else if (len < sizeof (struct ospf6_header))
1229 {
1230 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001231 return 0;
1232 }
1233
hasso508e53e2004-05-18 18:57:06 +00001234 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1235 if (oi == NULL || oi->area == NULL)
1236 {
hassoc6487d62004-12-24 06:00:11 +00001237 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001238 return 0;
1239 }
1240
1241 oh = (struct ospf6_header *) recvbuf;
1242
1243 /* Log */
1244 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1245 {
1246 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1247 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001248 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001249 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001250 zlog_debug (" src: %s", srcname);
1251 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001252 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001253 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001254
1255 switch (oh->type)
1256 {
1257 case OSPF6_MESSAGE_TYPE_HELLO:
1258 ospf6_hello_print (oh);
1259 break;
1260 case OSPF6_MESSAGE_TYPE_DBDESC:
1261 ospf6_dbdesc_print (oh);
1262 break;
1263 case OSPF6_MESSAGE_TYPE_LSREQ:
1264 ospf6_lsreq_print (oh);
1265 break;
1266 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1267 ospf6_lsupdate_print (oh);
1268 break;
1269 case OSPF6_MESSAGE_TYPE_LSACK:
1270 ospf6_lsack_print (oh);
1271 break;
1272 default:
hassoc6487d62004-12-24 06:00:11 +00001273 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001274 break;
1275 }
1276 }
1277
1278 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1279 {
1280 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001281 zlog_debug ("Ignore message on passive interface %s",
hasso508e53e2004-05-18 18:57:06 +00001282 oi->interface->name);
1283 return 0;
1284 }
1285
1286 switch (oh->type)
1287 {
1288 case OSPF6_MESSAGE_TYPE_HELLO:
1289 ospf6_hello_recv (&src, &dst, oi, oh);
1290 break;
1291
1292 case OSPF6_MESSAGE_TYPE_DBDESC:
1293 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1294 break;
1295
1296 case OSPF6_MESSAGE_TYPE_LSREQ:
1297 ospf6_lsreq_recv (&src, &dst, oi, oh);
1298 break;
1299
1300 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1301 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1302 break;
1303
1304 case OSPF6_MESSAGE_TYPE_LSACK:
1305 ospf6_lsack_recv (&src, &dst, oi, oh);
1306 break;
1307
1308 default:
1309 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001310 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001311 break;
1312 }
1313
1314 return 0;
1315}
1316
1317void
1318ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1319 struct ospf6_interface *oi, struct ospf6_header *oh)
1320{
1321 int len;
1322 char srcname[64], dstname[64];
1323 struct iovec iovector[2];
1324
1325 /* initialize */
1326 iovector[0].iov_base = (caddr_t) oh;
1327 iovector[0].iov_len = ntohs (oh->length);
1328 iovector[1].iov_base = NULL;
1329 iovector[1].iov_len = 0;
1330
1331 /* fill OSPF header */
1332 oh->version = OSPFV3_VERSION;
1333 /* message type must be set before */
1334 /* message length must be set before */
1335 oh->router_id = oi->area->ospf6->router_id;
1336 oh->area_id = oi->area->area_id;
1337 /* checksum is calculated by kernel */
1338 oh->instance_id = oi->instance_id;
1339 oh->reserved = 0;
1340
1341 /* Log */
1342 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1343 {
1344 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1345 if (src)
1346 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1347 else
1348 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001349 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001350 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001351 zlog_debug (" src: %s", srcname);
1352 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001353
1354 switch (oh->type)
1355 {
1356 case OSPF6_MESSAGE_TYPE_HELLO:
1357 ospf6_hello_print (oh);
1358 break;
1359 case OSPF6_MESSAGE_TYPE_DBDESC:
1360 ospf6_dbdesc_print (oh);
1361 break;
1362 case OSPF6_MESSAGE_TYPE_LSREQ:
1363 ospf6_lsreq_print (oh);
1364 break;
1365 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1366 ospf6_lsupdate_print (oh);
1367 break;
1368 case OSPF6_MESSAGE_TYPE_LSACK:
1369 ospf6_lsack_print (oh);
1370 break;
1371 default:
hassoc6487d62004-12-24 06:00:11 +00001372 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001373 assert (0);
1374 break;
1375 }
1376 }
1377
1378 /* send message */
1379 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1380 if (len != ntohs (oh->length))
1381 zlog_err ("Could not send entire message");
1382}
1383
1384int
1385ospf6_hello_send (struct thread *thread)
1386{
1387 struct ospf6_interface *oi;
1388 struct ospf6_header *oh;
1389 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001390 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001391 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001392 struct ospf6_neighbor *on;
1393
1394 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1395 oi->thread_send_hello = (struct thread *) NULL;
1396
1397 if (oi->state <= OSPF6_INTERFACE_DOWN)
1398 {
1399 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001400 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001401 oi->interface->name);
1402 return 0;
1403 }
1404
1405 /* set next thread */
1406 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1407 oi, oi->hello_interval);
1408
hasso3b4cd3a2004-05-18 19:28:32 +00001409 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001410 oh = (struct ospf6_header *) sendbuf;
1411 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1412
1413 hello->interface_id = htonl (oi->interface->ifindex);
1414 hello->priority = oi->priority;
1415 hello->options[0] = oi->area->options[0];
1416 hello->options[1] = oi->area->options[1];
1417 hello->options[2] = oi->area->options[2];
1418 hello->hello_interval = htons (oi->hello_interval);
1419 hello->dead_interval = htons (oi->dead_interval);
1420 hello->drouter = oi->drouter;
1421 hello->bdrouter = oi->bdrouter;
1422
1423 p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello));
1424
paul1eb8ef22005-04-07 07:30:20 +00001425 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001426 {
hasso508e53e2004-05-18 18:57:06 +00001427 if (on->state < OSPF6_NEIGHBOR_INIT)
1428 continue;
1429
1430 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1431 {
1432 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001433 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001434 break;
1435 }
1436
1437 memcpy (p, &on->router_id, sizeof (u_int32_t));
1438 p += sizeof (u_int32_t);
1439 }
1440
1441 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1442 oh->length = htons (p - sendbuf);
1443
1444 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1445 return 0;
1446}
1447
1448int
1449ospf6_dbdesc_send (struct thread *thread)
1450{
1451 struct ospf6_neighbor *on;
1452 struct ospf6_header *oh;
1453 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001454 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001455 struct ospf6_lsa *lsa;
1456
1457 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1458 on->thread_send_dbdesc = (struct thread *) NULL;
1459
1460 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1461 {
1462 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001463 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1464 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001465 return 0;
1466 }
1467
1468 /* set next thread if master */
1469 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1470 on->thread_send_dbdesc =
1471 thread_add_timer (master, ospf6_dbdesc_send, on,
1472 on->ospf6_if->rxmt_interval);
1473
hasso3b4cd3a2004-05-18 19:28:32 +00001474 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001475 oh = (struct ospf6_header *) sendbuf;
1476 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1477 sizeof (struct ospf6_header));
1478
1479 /* if this is initial one, initialize sequence number for DbDesc */
1480 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1481 {
1482 struct timeval tv;
1483 if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
1484 tv.tv_sec = 1;
1485 on->dbdesc_seqnum = tv.tv_sec;
1486 }
1487
1488 dbdesc->options[0] = on->ospf6_if->area->options[0];
1489 dbdesc->options[1] = on->ospf6_if->area->options[1];
1490 dbdesc->options[2] = on->ospf6_if->area->options[2];
1491 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1492 dbdesc->bits = on->dbdesc_bits;
1493 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1494
1495 /* if this is not initial one, set LSA headers in dbdesc */
1496 p = (char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
1497 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1498 {
1499 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1500 lsa = ospf6_lsdb_next (lsa))
1501 {
1502 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1503
1504 /* MTU check */
1505 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1506 on->ospf6_if->ifmtu)
1507 {
1508 ospf6_lsa_unlock (lsa);
1509 break;
1510 }
1511 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1512 p += sizeof (struct ospf6_lsa_header);
1513 }
1514 }
1515
1516 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1517 oh->length = htons (p - sendbuf);
1518
1519 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1520 on->ospf6_if, oh);
1521 return 0;
1522}
1523
1524int
1525ospf6_dbdesc_send_newone (struct thread *thread)
1526{
1527 struct ospf6_neighbor *on;
1528 struct ospf6_lsa *lsa;
1529 unsigned int size = 0;
1530
1531 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001532 ospf6_lsdb_remove_all (on->dbdesc_list);
1533
1534 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1535 so that ospf6_send_dbdesc () can send those LSAs */
1536 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1537 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1538 lsa = ospf6_lsdb_next (lsa))
1539 {
1540 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1541 {
1542 ospf6_lsa_unlock (lsa);
1543 break;
1544 }
1545
hasso508e53e2004-05-18 18:57:06 +00001546 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1547 ospf6_lsdb_remove (lsa, on->summary_list);
1548 size += sizeof (struct ospf6_lsa_header);
1549 }
1550
1551 if (on->summary_list->count == 0)
1552 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1553
1554 /* If slave, More bit check must be done here */
1555 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1556 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1557 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1558 thread_add_event (master, exchange_done, on, 0);
1559
1560 thread_execute (master, ospf6_dbdesc_send, on, 0);
1561 return 0;
1562}
1563
1564int
1565ospf6_lsreq_send (struct thread *thread)
1566{
1567 struct ospf6_neighbor *on;
1568 struct ospf6_header *oh;
1569 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001570 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001571 struct ospf6_lsa *lsa;
1572
1573 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1574 on->thread_send_lsreq = (struct thread *) NULL;
1575
1576 /* LSReq will be sent only in ExStart or Loading */
1577 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1578 on->state != OSPF6_NEIGHBOR_LOADING)
1579 {
1580 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001581 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1582 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001583 return 0;
1584 }
1585
1586 /* schedule loading_done if request list is empty */
1587 if (on->request_list->count == 0)
1588 {
1589 thread_add_event (master, loading_done, on, 0);
1590 return 0;
1591 }
1592
1593 /* set next thread */
1594 on->thread_send_lsreq =
1595 thread_add_timer (master, ospf6_lsreq_send, on,
1596 on->ospf6_if->rxmt_interval);
1597
hasso3b4cd3a2004-05-18 19:28:32 +00001598 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001599 oh = (struct ospf6_header *) sendbuf;
1600
1601 /* set Request entries in lsreq */
1602 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1603 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1604 lsa = ospf6_lsdb_next (lsa))
1605 {
1606 /* MTU check */
1607 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
1608 {
1609 ospf6_lsa_unlock (lsa);
1610 break;
1611 }
1612
1613 e = (struct ospf6_lsreq_entry *) p;
1614 e->type = lsa->header->type;
1615 e->id = lsa->header->id;
1616 e->adv_router = lsa->header->adv_router;
1617 p += sizeof (struct ospf6_lsreq_entry);
1618 }
1619
1620 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1621 oh->length = htons (p - sendbuf);
1622
1623 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1624 on->ospf6_if, oh);
1625 return 0;
1626}
1627
1628int
1629ospf6_lsupdate_send_neighbor (struct thread *thread)
1630{
1631 struct ospf6_neighbor *on;
1632 struct ospf6_header *oh;
1633 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001634 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001635 int num;
1636 struct ospf6_lsa *lsa;
1637
1638 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1639 on->thread_send_lsupdate = (struct thread *) NULL;
1640
hasso6452df02004-08-15 05:52:07 +00001641 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001642 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001643
hasso508e53e2004-05-18 18:57:06 +00001644 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1645 {
1646 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001647 zlog_debug ("Quit to send (neighbor state %s)",
1648 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001649 return 0;
1650 }
1651
1652 /* if we have nothing to send, return */
1653 if (on->lsupdate_list->count == 0 &&
1654 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001655 {
1656 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001657 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001658 return 0;
1659 }
hasso508e53e2004-05-18 18:57:06 +00001660
hasso3b4cd3a2004-05-18 19:28:32 +00001661 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001662 oh = (struct ospf6_header *) sendbuf;
1663 lsupdate = (struct ospf6_lsupdate *)
1664 ((caddr_t) oh + sizeof (struct ospf6_header));
1665
1666 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1667 num = 0;
1668
1669 /* lsupdate_list lists those LSA which doesn't need to be
1670 retransmitted. remove those from the list */
1671 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1672 lsa = ospf6_lsdb_next (lsa))
1673 {
1674 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001675 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
1676 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001677 {
1678 ospf6_lsa_unlock (lsa);
1679 break;
1680 }
1681
hasso508e53e2004-05-18 18:57:06 +00001682 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1683 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1684 p += OSPF6_LSA_SIZE (lsa->header);
1685 num++;
1686
1687 assert (lsa->lock == 2);
1688 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1689 }
1690
1691 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1692 lsa = ospf6_lsdb_next (lsa))
1693 {
1694 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001695 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
1696 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001697 {
1698 ospf6_lsa_unlock (lsa);
1699 break;
1700 }
1701
hasso508e53e2004-05-18 18:57:06 +00001702 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1703 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1704 p += OSPF6_LSA_SIZE (lsa->header);
1705 num++;
1706 }
1707
1708 lsupdate->lsa_number = htonl (num);
1709
1710 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1711 oh->length = htons (p - sendbuf);
1712
1713 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1714 on->ospf6_if, oh);
1715
1716 if (on->lsupdate_list->count != 0 ||
1717 on->retrans_list->count != 0)
1718 {
1719 if (on->lsupdate_list->count != 0)
1720 on->thread_send_lsupdate =
1721 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1722 else
1723 on->thread_send_lsupdate =
1724 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1725 on->ospf6_if->rxmt_interval);
1726 }
1727
1728 return 0;
1729}
1730
1731int
1732ospf6_lsupdate_send_interface (struct thread *thread)
1733{
1734 struct ospf6_interface *oi;
1735 struct ospf6_header *oh;
1736 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001737 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001738 int num;
1739 struct ospf6_lsa *lsa;
1740
1741 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1742 oi->thread_send_lsupdate = (struct thread *) NULL;
1743
1744 if (oi->state <= OSPF6_INTERFACE_WAITING)
1745 {
1746 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001747 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
1748 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001749 return 0;
1750 }
1751
1752 /* if we have nothing to send, return */
1753 if (oi->lsupdate_list->count == 0)
1754 return 0;
1755
hasso3b4cd3a2004-05-18 19:28:32 +00001756 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001757 oh = (struct ospf6_header *) sendbuf;
1758 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1759 sizeof (struct ospf6_header));
1760
1761 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1762 num = 0;
1763
1764 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1765 lsa = ospf6_lsdb_next (lsa))
1766 {
1767 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001768 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
1769 > oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00001770 {
1771 ospf6_lsa_unlock (lsa);
1772 break;
1773 }
1774
hasso508e53e2004-05-18 18:57:06 +00001775 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1776 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1777 p += OSPF6_LSA_SIZE (lsa->header);
1778 num++;
1779
1780 assert (lsa->lock == 2);
1781 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1782 }
1783
1784 lsupdate->lsa_number = htonl (num);
1785
1786 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1787 oh->length = htons (p - sendbuf);
1788
1789 if (oi->state == OSPF6_INTERFACE_DR ||
1790 oi->state == OSPF6_INTERFACE_BDR)
1791 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1792 else
1793 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1794
1795 if (oi->lsupdate_list->count > 0)
1796 {
1797 oi->thread_send_lsupdate =
1798 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1799 }
1800
1801 return 0;
1802}
1803
1804int
1805ospf6_lsack_send_neighbor (struct thread *thread)
1806{
1807 struct ospf6_neighbor *on;
1808 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001809 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001810 struct ospf6_lsa *lsa;
1811
1812 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1813 on->thread_send_lsack = (struct thread *) NULL;
1814
1815 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1816 {
1817 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001818 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
1819 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001820 return 0;
1821 }
1822
1823 /* if we have nothing to send, return */
1824 if (on->lsack_list->count == 0)
1825 return 0;
1826
hasso3b4cd3a2004-05-18 19:28:32 +00001827 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001828 oh = (struct ospf6_header *) sendbuf;
1829
1830 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1831
1832 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1833 lsa = ospf6_lsdb_next (lsa))
1834 {
1835 /* MTU check */
1836 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1837 {
1838 /* if we run out of packet size/space here,
1839 better to try again soon. */
1840 THREAD_OFF (on->thread_send_lsack);
1841 on->thread_send_lsack =
1842 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1843
1844 ospf6_lsa_unlock (lsa);
1845 break;
1846 }
1847
1848 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1849 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1850 p += sizeof (struct ospf6_lsa_header);
1851
1852 assert (lsa->lock == 2);
1853 ospf6_lsdb_remove (lsa, on->lsack_list);
1854 }
1855
1856 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1857 oh->length = htons (p - sendbuf);
1858
1859 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1860 on->ospf6_if, oh);
1861 return 0;
1862}
1863
1864int
1865ospf6_lsack_send_interface (struct thread *thread)
1866{
1867 struct ospf6_interface *oi;
1868 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00001869 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001870 struct ospf6_lsa *lsa;
1871
1872 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1873 oi->thread_send_lsack = (struct thread *) NULL;
1874
1875 if (oi->state <= OSPF6_INTERFACE_WAITING)
1876 {
1877 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00001878 zlog_debug ("Quit to send LSAck to interface %s state %s",
1879 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00001880 return 0;
1881 }
1882
1883 /* if we have nothing to send, return */
1884 if (oi->lsack_list->count == 0)
1885 return 0;
1886
hasso3b4cd3a2004-05-18 19:28:32 +00001887 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001888 oh = (struct ospf6_header *) sendbuf;
1889
1890 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1891
1892 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1893 lsa = ospf6_lsdb_next (lsa))
1894 {
1895 /* MTU check */
1896 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
1897 {
1898 /* if we run out of packet size/space here,
1899 better to try again soon. */
1900 THREAD_OFF (oi->thread_send_lsack);
1901 oi->thread_send_lsack =
1902 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1903
1904 ospf6_lsa_unlock (lsa);
1905 break;
1906 }
1907
1908 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1909 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1910 p += sizeof (struct ospf6_lsa_header);
1911
1912 assert (lsa->lock == 2);
1913 ospf6_lsdb_remove (lsa, oi->lsack_list);
1914 }
1915
1916 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1917 oh->length = htons (p - sendbuf);
1918
1919 if (oi->state == OSPF6_INTERFACE_DR ||
1920 oi->state == OSPF6_INTERFACE_BDR)
1921 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1922 else
1923 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1924
1925 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1926 {
1927 oi->thread_send_lsack =
1928 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1929 }
paul718e3742002-12-13 20:15:29 +00001930
1931 return 0;
1932}
1933
1934
hasso508e53e2004-05-18 18:57:06 +00001935/* Commands */
1936DEFUN (debug_ospf6_message,
1937 debug_ospf6_message_cmd,
1938 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1939 DEBUG_STR
1940 OSPF6_STR
1941 "Debug OSPFv3 message\n"
1942 "Debug Unknown message\n"
1943 "Debug Hello message\n"
1944 "Debug Database Description message\n"
1945 "Debug Link State Request message\n"
1946 "Debug Link State Update message\n"
1947 "Debug Link State Acknowledgement message\n"
1948 "Debug All message\n"
1949 )
paul718e3742002-12-13 20:15:29 +00001950{
hasso508e53e2004-05-18 18:57:06 +00001951 unsigned char level = 0;
1952 int type = 0;
paul718e3742002-12-13 20:15:29 +00001953 int i;
1954
hasso508e53e2004-05-18 18:57:06 +00001955 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001956
hasso508e53e2004-05-18 18:57:06 +00001957 /* check type */
1958 if (! strncmp (argv[0], "u", 1))
1959 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1960 else if (! strncmp (argv[0], "h", 1))
1961 type = OSPF6_MESSAGE_TYPE_HELLO;
1962 else if (! strncmp (argv[0], "d", 1))
1963 type = OSPF6_MESSAGE_TYPE_DBDESC;
1964 else if (! strncmp (argv[0], "lsr", 3))
1965 type = OSPF6_MESSAGE_TYPE_LSREQ;
1966 else if (! strncmp (argv[0], "lsu", 3))
1967 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1968 else if (! strncmp (argv[0], "lsa", 3))
1969 type = OSPF6_MESSAGE_TYPE_LSACK;
1970 else if (! strncmp (argv[0], "a", 1))
1971 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001972
hasso508e53e2004-05-18 18:57:06 +00001973 if (argc == 1)
1974 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1975 else if (! strncmp (argv[1], "s", 1))
1976 level = OSPF6_DEBUG_MESSAGE_SEND;
1977 else if (! strncmp (argv[1], "r", 1))
1978 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001979
hasso508e53e2004-05-18 18:57:06 +00001980 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001981 {
hasso508e53e2004-05-18 18:57:06 +00001982 for (i = 0; i < 6; i++)
1983 OSPF6_DEBUG_MESSAGE_ON (i, level);
1984 }
1985 else
1986 OSPF6_DEBUG_MESSAGE_ON (type, level);
1987
1988 return CMD_SUCCESS;
1989}
1990
1991ALIAS (debug_ospf6_message,
1992 debug_ospf6_message_sendrecv_cmd,
1993 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1994 DEBUG_STR
1995 OSPF6_STR
1996 "Debug OSPFv3 message\n"
1997 "Debug Unknown message\n"
1998 "Debug Hello message\n"
1999 "Debug Database Description message\n"
2000 "Debug Link State Request message\n"
2001 "Debug Link State Update message\n"
2002 "Debug Link State Acknowledgement message\n"
2003 "Debug All message\n"
2004 "Debug only sending message\n"
2005 "Debug only receiving message\n"
2006 );
2007
2008
2009DEFUN (no_debug_ospf6_message,
2010 no_debug_ospf6_message_cmd,
2011 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2012 NO_STR
2013 DEBUG_STR
2014 OSPF6_STR
2015 "Debug OSPFv3 message\n"
2016 "Debug Unknown message\n"
2017 "Debug Hello message\n"
2018 "Debug Database Description message\n"
2019 "Debug Link State Request message\n"
2020 "Debug Link State Update message\n"
2021 "Debug Link State Acknowledgement message\n"
2022 "Debug All message\n"
2023 )
2024{
2025 unsigned char level = 0;
2026 int type = 0;
2027 int i;
2028
2029 assert (argc > 0);
2030
2031 /* check type */
2032 if (! strncmp (argv[0], "u", 1))
2033 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2034 else if (! strncmp (argv[0], "h", 1))
2035 type = OSPF6_MESSAGE_TYPE_HELLO;
2036 else if (! strncmp (argv[0], "d", 1))
2037 type = OSPF6_MESSAGE_TYPE_DBDESC;
2038 else if (! strncmp (argv[0], "lsr", 3))
2039 type = OSPF6_MESSAGE_TYPE_LSREQ;
2040 else if (! strncmp (argv[0], "lsu", 3))
2041 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2042 else if (! strncmp (argv[0], "lsa", 3))
2043 type = OSPF6_MESSAGE_TYPE_LSACK;
2044 else if (! strncmp (argv[0], "a", 1))
2045 type = OSPF6_MESSAGE_TYPE_ALL;
2046
2047 if (argc == 1)
2048 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2049 else if (! strncmp (argv[1], "s", 1))
2050 level = OSPF6_DEBUG_MESSAGE_SEND;
2051 else if (! strncmp (argv[1], "r", 1))
2052 level = OSPF6_DEBUG_MESSAGE_RECV;
2053
2054 if (type == OSPF6_MESSAGE_TYPE_ALL)
2055 {
2056 for (i = 0; i < 6; i++)
2057 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2058 }
2059 else
2060 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2061
2062 return CMD_SUCCESS;
2063}
2064
2065ALIAS (no_debug_ospf6_message,
2066 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002067 "no debug ospf6 message "
2068 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002069 NO_STR
2070 DEBUG_STR
2071 OSPF6_STR
2072 "Debug OSPFv3 message\n"
2073 "Debug Unknown message\n"
2074 "Debug Hello message\n"
2075 "Debug Database Description message\n"
2076 "Debug Link State Request message\n"
2077 "Debug Link State Update message\n"
2078 "Debug Link State Acknowledgement message\n"
2079 "Debug All message\n"
2080 "Debug only sending message\n"
2081 "Debug only receiving message\n"
2082 );
2083
2084int
2085config_write_ospf6_debug_message (struct vty *vty)
2086{
paul0c083ee2004-10-10 12:54:58 +00002087 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002088 "lsreq", "lsupdate", "lsack"};
2089 unsigned char s = 0, r = 0;
2090 int i;
2091
2092 for (i = 0; i < 6; i++)
2093 {
2094 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2095 s |= 1 << i;
2096 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2097 r |= 1 << i;
2098 }
2099
2100 if (s == 0x3f && r == 0x3f)
2101 {
hasso049207c2004-08-04 20:02:13 +00002102 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002103 return 0;
2104 }
2105
hasso508e53e2004-05-18 18:57:06 +00002106 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002107 {
hasso049207c2004-08-04 20:02:13 +00002108 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002109 return 0;
2110 }
2111 else if (s == 0 && r == 0x3f)
2112 {
hasso049207c2004-08-04 20:02:13 +00002113 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002114 return 0;
paul718e3742002-12-13 20:15:29 +00002115 }
2116
hasso508e53e2004-05-18 18:57:06 +00002117 /* Unknown message is logged by default */
2118 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2119 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002120 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002121 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002122 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002123 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002124 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002125
hasso508e53e2004-05-18 18:57:06 +00002126 for (i = 1; i < 6; i++)
2127 {
2128 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2129 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002130 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002131 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2132 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002133 VNL);
hasso508e53e2004-05-18 18:57:06 +00002134 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2135 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002136 VNL);
hasso508e53e2004-05-18 18:57:06 +00002137 }
paul718e3742002-12-13 20:15:29 +00002138
2139 return 0;
2140}
2141
paul718e3742002-12-13 20:15:29 +00002142void
hasso508e53e2004-05-18 18:57:06 +00002143install_element_ospf6_debug_message ()
paul718e3742002-12-13 20:15:29 +00002144{
hasso508e53e2004-05-18 18:57:06 +00002145 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2146 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2147 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2148 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2149 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2150 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2151 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2152 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002153}
2154
paul718e3742002-12-13 20:15:29 +00002155