blob: 7e022da5597a79f8a15019580139f97f17980ea0 [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};
46char *ospf6_message_type_str[] =
47 { "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
hasso508e53e2004-05-18 18:57:06 +000058 zlog_info (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
59 oh->version, oh->type, ntohs (oh->length), router_id);
60 zlog_info (" Area-ID:%s Cksum:%hx Instance-ID:%d",
61 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
hasso508e53e2004-05-18 18:57:06 +000082 zlog_info (" I/F-Id:%ld Priority:%d Option:%s",
83 (u_long) ntohl (hello->interface_id), hello->priority, options);
84 zlog_info (" HelloInterval:%hu DeadInterval:%hu",
85 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
86 zlog_info (" 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));
paul718e3742002-12-13 20:15:29 +000093 zlog_info (" Neighbor: %s", neighbor);
94 }
hasso508e53e2004-05-18 18:57:06 +000095
96 if (p != OSPF6_MESSAGE_END (oh))
97 zlog_info ("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
hasso508e53e2004-05-18 18:57:06 +0000115 zlog_info (" MBZ: %#x Option: %s IfMTU: %hu",
116 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
117 zlog_info (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
118 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))
130 zlog_info ("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));
149 zlog_info (" [%s Id:%s Adv:%s]",
150 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))
154 zlog_info ("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);
171 zlog_info (" 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 {
181 zlog_info (" Malformed LSA length, quit printing");
182 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
193 zlog_info (" Trailing garbage exists");
194 while (p < OSPF6_MESSAGE_END (oh))
195 {
196 snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
197 num++;
198 if (num == 8)
199 {
200 zlog_info (" %s", buf);
201 memset (buf, 0, sizeof (buf));
202 num = 0;
203 }
204 }
205 if (num)
206 zlog_info (" %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))
224 zlog_info ("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))
241 zlog_info ("Message with unknown version");
242 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))
251 zlog_info ("Message may be via Virtual Link: not supported");
252 return MSG_NG;
253 }
254
255 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
256 zlog_info ("Area-ID mismatch");
257 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))
264 zlog_info ("Instance-ID mismatch");
265 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))
296 zlog_info ("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))
304 zlog_info ("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))
313 zlog_info ("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))
343 zlog_info ("Trailing garbage ignored");
344 }
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))
407 zlog_info ("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))
415 zlog_info ("Neighbor state is 2-Way, ignore");
416 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))
423 zlog_info ("Neighbor state is not ExStart, ignore");
424 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))
444 zlog_info ("Negotiation failed");
445 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))
454 zlog_info ("Duplicated dbdesc discarded by Master, ignore");
455 return;
456 }
457
458 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
459 {
460 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
461 zlog_info ("Master/Slave bit mismatch");
462 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))
469 zlog_info ("Initialize bit mismatch");
470 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))
477 zlog_info ("Option field mismatch");
478 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))
485 zlog_info ("Sequence number mismatch (%#lx expected)",
486 (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))
498 zlog_info ("Duplicated dbdesc discarded by Master, ignore");
499 return;
500 }
501
502 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
503 zlog_info ("Not duplicate dbdesc in state %s",
504 ospf6_neighbor_state_str[on->state]);
505 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))
524 zlog_info ("%s", his->name);
525
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))
539 zlog_info ("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))
hasso6452df02004-08-15 05:52:07 +0000549 zlog_info ("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))
560 zlog_info ("Add request (No database copy)", his->name);
561 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))
566 zlog_info ("Add request (Received MoreRecent)", his->name);
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))
572 zlog_info ("Discard (Existing MoreRecent)", his->name);
573 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))
580 zlog_info ("Trailing garbage ignored");
581 }
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))
618 zlog_info ("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))
626 zlog_info ("Neighbor state is 2-Way, ignore");
627 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))
634 zlog_info ("Neighbor state is not ExStart, ignore");
635 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))
663 zlog_info ("Negotiation failed");
664 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))
673 zlog_info ("Duplicated dbdesc causes retransmit");
674 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))
683 zlog_info ("Master/Slave bit mismatch");
684 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))
691 zlog_info ("Initialize bit mismatch");
692 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))
699 zlog_info ("Option field mismatch");
700 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))
707 zlog_info ("Sequence number mismatch (%#lx expected)",
708 (u_long) on->dbdesc_seqnum + 1);
709 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))
720 zlog_info ("Duplicated dbdesc causes retransmit");
721 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))
728 zlog_info ("Not duplicate dbdesc in state %s",
729 ospf6_neighbor_state_str[on->state]);
730 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))
761 zlog_info ("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))
771 zlog_info ("E-bit mismatch with LSA Headers");
772 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))
782 zlog_info ("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))
792 zlog_info ("Trailing garbage ignored");
793 }
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))
825 zlog_info ("Neighbor not found, ignore");
826 return;
827 }
828
829 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
830 {
831 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
832 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
833 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))
843 zlog_info ("I/F MTU mismatch");
844 return;
845 }
846
847 if (dbdesc->reserved1 || dbdesc->reserved2)
848 {
849 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
850 zlog_info ("Non-0 reserved field in %s's DbDesc, correct",
851 on->name);
852 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))
863 zlog_info ("Can't decide which is master, ignore");
864 }
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))
884 zlog_info ("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))
891 zlog_info ("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))
900 zlog_info ("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))
924 zlog_info ("Ignoring LSA of reserved scope");
925 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));
939 zlog_info ("Can't find requested [%s Id:%s Adv:%s]",
940 OSPF6_LSTYPE_NAME (e->type), id, adv_router);
941 }
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))
952 zlog_info ("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))
977 zlog_info ("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))
984 zlog_info ("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))
993 zlog_info ("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))
1013 zlog_info ("Malformed LSA length, quit processing");
1014 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))
1024 zlog_info ("Malformed LSA number or LSA length");
1025 }
1026 if (p != OSPF6_MESSAGE_END (oh))
1027 {
1028 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1029 zlog_info ("Trailing garbage ignored");
1030 }
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))
1064 zlog_info ("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))
1071 zlog_info ("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))
1080 zlog_info ("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))
1103 zlog_info ("Ignoring LSA of reserved scope");
1104 ospf6_lsa_delete (his);
1105 continue;
1106 break;
1107 }
1108
1109 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hasso508e53e2004-05-18 18:57:06 +00001110 zlog_info ("%s acknowledged by %s", his->name, on->name);
1111
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))
1118 zlog_info ("No database copy");
1119 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))
1129 zlog_info ("Not on %s's retrans-list", on->name);
1130 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))
1139 zlog_info ("Questionable acknowledgement");
1140 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))
hasso508e53e2004-05-18 18:57:06 +00001145 zlog_info ("Acknowledged, remove from %s's retrans-list",
1146 on->name);
1147
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))
1159 zlog_info ("Trailing garbage ignored");
1160 }
paul718e3742002-12-13 20:15:29 +00001161}
1162
hasso3b4cd3a2004-05-18 19:28:32 +00001163char *recvbuf = NULL;
1164char *sendbuf = NULL;
1165int iobuflen = 0;
1166
1167int
1168ospf6_iobuf_size (int size)
1169{
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);
hasso3b4cd3a2004-05-18 19:28:32 +00001183 zlog_info ("Could not allocate I/O buffer of size %d.", size);
1184 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{
hasso508e53e2004-05-18 18:57:06 +00001201 int sockfd, len;
1202 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001203 struct in6_addr src, dst;
1204 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001205 struct iovec iovector[2];
1206 struct ospf6_interface *oi;
1207 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001208
1209 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001210 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001211 thread_add_read (master, ospf6_receive, NULL, sockfd);
1212
1213 /* initialize */
hasso3b4cd3a2004-05-18 19:28:32 +00001214 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001215 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001216 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001217 iovector[1].iov_base = NULL;
1218 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001219
1220 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001221 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001222 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001223 {
hasso508e53e2004-05-18 18:57:06 +00001224 zlog_err ("Excess message read");
1225 return 0;
1226 }
1227 else if (len < sizeof (struct ospf6_header))
1228 {
1229 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001230 return 0;
1231 }
1232
hasso508e53e2004-05-18 18:57:06 +00001233 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1234 if (oi == NULL || oi->area == NULL)
1235 {
1236 zlog_info ("Message received on disabled interface");
1237 return 0;
1238 }
1239
1240 oh = (struct ospf6_header *) recvbuf;
1241
1242 /* Log */
1243 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1244 {
1245 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1246 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
1247 zlog_info ("%s received on %s",
1248 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1249 zlog_info (" src: %s", srcname);
1250 zlog_info (" dst: %s", dstname);
1251 if (len != ntohs (oh->length))
1252 zlog_info ("Message length does not match actually received: %d", len);
1253
1254 switch (oh->type)
1255 {
1256 case OSPF6_MESSAGE_TYPE_HELLO:
1257 ospf6_hello_print (oh);
1258 break;
1259 case OSPF6_MESSAGE_TYPE_DBDESC:
1260 ospf6_dbdesc_print (oh);
1261 break;
1262 case OSPF6_MESSAGE_TYPE_LSREQ:
1263 ospf6_lsreq_print (oh);
1264 break;
1265 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1266 ospf6_lsupdate_print (oh);
1267 break;
1268 case OSPF6_MESSAGE_TYPE_LSACK:
1269 ospf6_lsack_print (oh);
1270 break;
1271 default:
1272 zlog_info ("Unknown message");
1273 break;
1274 }
1275 }
1276
1277 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1278 {
1279 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1280 zlog_info ("Ignore message on passive interface %s",
1281 oi->interface->name);
1282 return 0;
1283 }
1284
1285 switch (oh->type)
1286 {
1287 case OSPF6_MESSAGE_TYPE_HELLO:
1288 ospf6_hello_recv (&src, &dst, oi, oh);
1289 break;
1290
1291 case OSPF6_MESSAGE_TYPE_DBDESC:
1292 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1293 break;
1294
1295 case OSPF6_MESSAGE_TYPE_LSREQ:
1296 ospf6_lsreq_recv (&src, &dst, oi, oh);
1297 break;
1298
1299 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1300 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1301 break;
1302
1303 case OSPF6_MESSAGE_TYPE_LSACK:
1304 ospf6_lsack_recv (&src, &dst, oi, oh);
1305 break;
1306
1307 default:
1308 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1309 zlog_info ("Unknown message");
1310 break;
1311 }
1312
1313 return 0;
1314}
1315
1316void
1317ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1318 struct ospf6_interface *oi, struct ospf6_header *oh)
1319{
1320 int len;
1321 char srcname[64], dstname[64];
1322 struct iovec iovector[2];
1323
1324 /* initialize */
1325 iovector[0].iov_base = (caddr_t) oh;
1326 iovector[0].iov_len = ntohs (oh->length);
1327 iovector[1].iov_base = NULL;
1328 iovector[1].iov_len = 0;
1329
1330 /* fill OSPF header */
1331 oh->version = OSPFV3_VERSION;
1332 /* message type must be set before */
1333 /* message length must be set before */
1334 oh->router_id = oi->area->ospf6->router_id;
1335 oh->area_id = oi->area->area_id;
1336 /* checksum is calculated by kernel */
1337 oh->instance_id = oi->instance_id;
1338 oh->reserved = 0;
1339
1340 /* Log */
1341 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1342 {
1343 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1344 if (src)
1345 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1346 else
1347 memset (srcname, 0, sizeof (srcname));
1348 zlog_info ("%s send on %s",
1349 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1350 zlog_info (" src: %s", srcname);
1351 zlog_info (" dst: %s", dstname);
1352
1353 switch (oh->type)
1354 {
1355 case OSPF6_MESSAGE_TYPE_HELLO:
1356 ospf6_hello_print (oh);
1357 break;
1358 case OSPF6_MESSAGE_TYPE_DBDESC:
1359 ospf6_dbdesc_print (oh);
1360 break;
1361 case OSPF6_MESSAGE_TYPE_LSREQ:
1362 ospf6_lsreq_print (oh);
1363 break;
1364 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1365 ospf6_lsupdate_print (oh);
1366 break;
1367 case OSPF6_MESSAGE_TYPE_LSACK:
1368 ospf6_lsack_print (oh);
1369 break;
1370 default:
1371 zlog_info ("Unknown message");
1372 assert (0);
1373 break;
1374 }
1375 }
1376
1377 /* send message */
1378 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1379 if (len != ntohs (oh->length))
1380 zlog_err ("Could not send entire message");
1381}
1382
1383int
1384ospf6_hello_send (struct thread *thread)
1385{
1386 struct ospf6_interface *oi;
1387 struct ospf6_header *oh;
1388 struct ospf6_hello *hello;
1389 char *p;
1390 listnode node;
1391 struct ospf6_neighbor *on;
1392
1393 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1394 oi->thread_send_hello = (struct thread *) NULL;
1395
1396 if (oi->state <= OSPF6_INTERFACE_DOWN)
1397 {
1398 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1399 zlog_info ("Unable to send Hello on down interface %s",
1400 oi->interface->name);
1401 return 0;
1402 }
1403
1404 /* set next thread */
1405 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1406 oi, oi->hello_interval);
1407
hasso3b4cd3a2004-05-18 19:28:32 +00001408 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001409 oh = (struct ospf6_header *) sendbuf;
1410 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1411
1412 hello->interface_id = htonl (oi->interface->ifindex);
1413 hello->priority = oi->priority;
1414 hello->options[0] = oi->area->options[0];
1415 hello->options[1] = oi->area->options[1];
1416 hello->options[2] = oi->area->options[2];
1417 hello->hello_interval = htons (oi->hello_interval);
1418 hello->dead_interval = htons (oi->dead_interval);
1419 hello->drouter = oi->drouter;
1420 hello->bdrouter = oi->bdrouter;
1421
1422 p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello));
1423
1424 for (node = listhead (oi->neighbor_list); node; nextnode (node))
1425 {
1426 on = (struct ospf6_neighbor *) getdata (node);
1427
1428 if (on->state < OSPF6_NEIGHBOR_INIT)
1429 continue;
1430
1431 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1432 {
1433 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1434 zlog_info ("sending Hello message: exceeds I/F MTU");
1435 break;
1436 }
1437
1438 memcpy (p, &on->router_id, sizeof (u_int32_t));
1439 p += sizeof (u_int32_t);
1440 }
1441
1442 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1443 oh->length = htons (p - sendbuf);
1444
1445 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1446 return 0;
1447}
1448
1449int
1450ospf6_dbdesc_send (struct thread *thread)
1451{
1452 struct ospf6_neighbor *on;
1453 struct ospf6_header *oh;
1454 struct ospf6_dbdesc *dbdesc;
1455 char *p;
1456 struct ospf6_lsa *lsa;
1457
1458 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1459 on->thread_send_dbdesc = (struct thread *) NULL;
1460
1461 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1462 {
1463 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
1464 zlog_info ("Quit to send DbDesc to neighbor %s state %s",
1465 on->name, ospf6_neighbor_state_str[on->state]);
1466 return 0;
1467 }
1468
1469 /* set next thread if master */
1470 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1471 on->thread_send_dbdesc =
1472 thread_add_timer (master, ospf6_dbdesc_send, on,
1473 on->ospf6_if->rxmt_interval);
1474
hasso3b4cd3a2004-05-18 19:28:32 +00001475 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001476 oh = (struct ospf6_header *) sendbuf;
1477 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1478 sizeof (struct ospf6_header));
1479
1480 /* if this is initial one, initialize sequence number for DbDesc */
1481 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1482 {
1483 struct timeval tv;
1484 if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
1485 tv.tv_sec = 1;
1486 on->dbdesc_seqnum = tv.tv_sec;
1487 }
1488
1489 dbdesc->options[0] = on->ospf6_if->area->options[0];
1490 dbdesc->options[1] = on->ospf6_if->area->options[1];
1491 dbdesc->options[2] = on->ospf6_if->area->options[2];
1492 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1493 dbdesc->bits = on->dbdesc_bits;
1494 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1495
1496 /* if this is not initial one, set LSA headers in dbdesc */
1497 p = (char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
1498 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1499 {
1500 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1501 lsa = ospf6_lsdb_next (lsa))
1502 {
1503 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1504
1505 /* MTU check */
1506 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1507 on->ospf6_if->ifmtu)
1508 {
1509 ospf6_lsa_unlock (lsa);
1510 break;
1511 }
1512 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1513 p += sizeof (struct ospf6_lsa_header);
1514 }
1515 }
1516
1517 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1518 oh->length = htons (p - sendbuf);
1519
1520 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1521 on->ospf6_if, oh);
1522 return 0;
1523}
1524
1525int
1526ospf6_dbdesc_send_newone (struct thread *thread)
1527{
1528 struct ospf6_neighbor *on;
1529 struct ospf6_lsa *lsa;
1530 unsigned int size = 0;
1531
1532 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001533 ospf6_lsdb_remove_all (on->dbdesc_list);
1534
1535 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1536 so that ospf6_send_dbdesc () can send those LSAs */
1537 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1538 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1539 lsa = ospf6_lsdb_next (lsa))
1540 {
1541 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1542 {
1543 ospf6_lsa_unlock (lsa);
1544 break;
1545 }
1546
hasso508e53e2004-05-18 18:57:06 +00001547 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1548 ospf6_lsdb_remove (lsa, on->summary_list);
1549 size += sizeof (struct ospf6_lsa_header);
1550 }
1551
1552 if (on->summary_list->count == 0)
1553 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1554
1555 /* If slave, More bit check must be done here */
1556 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1557 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1558 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1559 thread_add_event (master, exchange_done, on, 0);
1560
1561 thread_execute (master, ospf6_dbdesc_send, on, 0);
1562 return 0;
1563}
1564
1565int
1566ospf6_lsreq_send (struct thread *thread)
1567{
1568 struct ospf6_neighbor *on;
1569 struct ospf6_header *oh;
1570 struct ospf6_lsreq_entry *e;
1571 char *p;
1572 struct ospf6_lsa *lsa;
1573
1574 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1575 on->thread_send_lsreq = (struct thread *) NULL;
1576
1577 /* LSReq will be sent only in ExStart or Loading */
1578 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1579 on->state != OSPF6_NEIGHBOR_LOADING)
1580 {
1581 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
1582 zlog_info ("Quit to send LSReq to neighbor %s state %s",
1583 on->name, ospf6_neighbor_state_str[on->state]);
1584 return 0;
1585 }
1586
1587 /* schedule loading_done if request list is empty */
1588 if (on->request_list->count == 0)
1589 {
1590 thread_add_event (master, loading_done, on, 0);
1591 return 0;
1592 }
1593
1594 /* set next thread */
1595 on->thread_send_lsreq =
1596 thread_add_timer (master, ospf6_lsreq_send, on,
1597 on->ospf6_if->rxmt_interval);
1598
hasso3b4cd3a2004-05-18 19:28:32 +00001599 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001600 oh = (struct ospf6_header *) sendbuf;
1601
1602 /* set Request entries in lsreq */
1603 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1604 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1605 lsa = ospf6_lsdb_next (lsa))
1606 {
1607 /* MTU check */
1608 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
1609 {
1610 ospf6_lsa_unlock (lsa);
1611 break;
1612 }
1613
1614 e = (struct ospf6_lsreq_entry *) p;
1615 e->type = lsa->header->type;
1616 e->id = lsa->header->id;
1617 e->adv_router = lsa->header->adv_router;
1618 p += sizeof (struct ospf6_lsreq_entry);
1619 }
1620
1621 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1622 oh->length = htons (p - sendbuf);
1623
1624 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1625 on->ospf6_if, oh);
1626 return 0;
1627}
1628
1629int
1630ospf6_lsupdate_send_neighbor (struct thread *thread)
1631{
1632 struct ospf6_neighbor *on;
1633 struct ospf6_header *oh;
1634 struct ospf6_lsupdate *lsupdate;
1635 char *p;
1636 int num;
1637 struct ospf6_lsa *lsa;
1638
1639 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1640 on->thread_send_lsupdate = (struct thread *) NULL;
1641
hasso6452df02004-08-15 05:52:07 +00001642 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1643 zlog_info ("LSUpdate to neighbor %s", on->name);
1644
hasso508e53e2004-05-18 18:57:06 +00001645 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1646 {
1647 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hasso6452df02004-08-15 05:52:07 +00001648 zlog_info ("Quit to send (neighbor state %s)",
1649 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001650 return 0;
1651 }
1652
1653 /* if we have nothing to send, return */
1654 if (on->lsupdate_list->count == 0 &&
1655 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001656 {
1657 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1658 zlog_info ("Quit to send (nothing to send)");
1659 return 0;
1660 }
hasso508e53e2004-05-18 18:57:06 +00001661
hasso3b4cd3a2004-05-18 19:28:32 +00001662 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001663 oh = (struct ospf6_header *) sendbuf;
1664 lsupdate = (struct ospf6_lsupdate *)
1665 ((caddr_t) oh + sizeof (struct ospf6_header));
1666
1667 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1668 num = 0;
1669
1670 /* lsupdate_list lists those LSA which doesn't need to be
1671 retransmitted. remove those from the list */
1672 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1673 lsa = ospf6_lsdb_next (lsa))
1674 {
1675 /* MTU check */
1676 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1677 {
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 */
1695 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1696 {
1697 ospf6_lsa_unlock (lsa);
1698 break;
1699 }
1700
hasso508e53e2004-05-18 18:57:06 +00001701 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1702 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1703 p += OSPF6_LSA_SIZE (lsa->header);
1704 num++;
1705 }
1706
1707 lsupdate->lsa_number = htonl (num);
1708
1709 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1710 oh->length = htons (p - sendbuf);
1711
1712 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1713 on->ospf6_if, oh);
1714
1715 if (on->lsupdate_list->count != 0 ||
1716 on->retrans_list->count != 0)
1717 {
1718 if (on->lsupdate_list->count != 0)
1719 on->thread_send_lsupdate =
1720 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1721 else
1722 on->thread_send_lsupdate =
1723 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1724 on->ospf6_if->rxmt_interval);
1725 }
1726
1727 return 0;
1728}
1729
1730int
1731ospf6_lsupdate_send_interface (struct thread *thread)
1732{
1733 struct ospf6_interface *oi;
1734 struct ospf6_header *oh;
1735 struct ospf6_lsupdate *lsupdate;
1736 char *p;
1737 int num;
1738 struct ospf6_lsa *lsa;
1739
1740 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1741 oi->thread_send_lsupdate = (struct thread *) NULL;
1742
1743 if (oi->state <= OSPF6_INTERFACE_WAITING)
1744 {
1745 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1746 zlog_info ("Quit to send LSUpdate to interface %s state %s",
1747 oi->interface->name, ospf6_interface_state_str[oi->state]);
1748 return 0;
1749 }
1750
1751 /* if we have nothing to send, return */
1752 if (oi->lsupdate_list->count == 0)
1753 return 0;
1754
1755 if (IS_OSPF6_DEBUG_LSA (SEND))
1756 zlog_info ("LSA Send to %s", oi->interface->name);
1757
hasso3b4cd3a2004-05-18 19:28:32 +00001758 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001759 oh = (struct ospf6_header *) sendbuf;
1760 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1761 sizeof (struct ospf6_header));
1762
1763 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1764 num = 0;
1765
1766 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1767 lsa = ospf6_lsdb_next (lsa))
1768 {
1769 /* MTU check */
1770 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > oi->ifmtu)
1771 {
1772 ospf6_lsa_unlock (lsa);
1773 break;
1774 }
1775
1776 if (IS_OSPF6_DEBUG_LSA (SEND))
1777 ospf6_lsa_header_print (lsa);
1778
1779 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1780 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1781 p += OSPF6_LSA_SIZE (lsa->header);
1782 num++;
1783
1784 assert (lsa->lock == 2);
1785 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1786 }
1787
1788 lsupdate->lsa_number = htonl (num);
1789
1790 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1791 oh->length = htons (p - sendbuf);
1792
1793 if (oi->state == OSPF6_INTERFACE_DR ||
1794 oi->state == OSPF6_INTERFACE_BDR)
1795 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1796 else
1797 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1798
1799 if (oi->lsupdate_list->count > 0)
1800 {
1801 oi->thread_send_lsupdate =
1802 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1803 }
1804
1805 return 0;
1806}
1807
1808int
1809ospf6_lsack_send_neighbor (struct thread *thread)
1810{
1811 struct ospf6_neighbor *on;
1812 struct ospf6_header *oh;
1813 char *p;
1814 struct ospf6_lsa *lsa;
1815
1816 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1817 on->thread_send_lsack = (struct thread *) NULL;
1818
1819 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1820 {
1821 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1822 zlog_info ("Quit to send LSAck to neighbor %s state %s",
1823 on->name, ospf6_neighbor_state_str[on->state]);
1824 return 0;
1825 }
1826
1827 /* if we have nothing to send, return */
1828 if (on->lsack_list->count == 0)
1829 return 0;
1830
hasso3b4cd3a2004-05-18 19:28:32 +00001831 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001832 oh = (struct ospf6_header *) sendbuf;
1833
1834 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1835
1836 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1837 lsa = ospf6_lsdb_next (lsa))
1838 {
1839 /* MTU check */
1840 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1841 {
1842 /* if we run out of packet size/space here,
1843 better to try again soon. */
1844 THREAD_OFF (on->thread_send_lsack);
1845 on->thread_send_lsack =
1846 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1847
1848 ospf6_lsa_unlock (lsa);
1849 break;
1850 }
1851
1852 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1853 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1854 p += sizeof (struct ospf6_lsa_header);
1855
1856 assert (lsa->lock == 2);
1857 ospf6_lsdb_remove (lsa, on->lsack_list);
1858 }
1859
1860 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1861 oh->length = htons (p - sendbuf);
1862
1863 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1864 on->ospf6_if, oh);
1865 return 0;
1866}
1867
1868int
1869ospf6_lsack_send_interface (struct thread *thread)
1870{
1871 struct ospf6_interface *oi;
1872 struct ospf6_header *oh;
1873 char *p;
1874 struct ospf6_lsa *lsa;
1875
1876 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1877 oi->thread_send_lsack = (struct thread *) NULL;
1878
1879 if (oi->state <= OSPF6_INTERFACE_WAITING)
1880 {
1881 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1882 zlog_info ("Quit to send LSAck to interface %s state %s",
1883 oi->interface->name, ospf6_interface_state_str[oi->state]);
1884 return 0;
1885 }
1886
1887 /* if we have nothing to send, return */
1888 if (oi->lsack_list->count == 0)
1889 return 0;
1890
hasso3b4cd3a2004-05-18 19:28:32 +00001891 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001892 oh = (struct ospf6_header *) sendbuf;
1893
1894 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1895
1896 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1897 lsa = ospf6_lsdb_next (lsa))
1898 {
1899 /* MTU check */
1900 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
1901 {
1902 /* if we run out of packet size/space here,
1903 better to try again soon. */
1904 THREAD_OFF (oi->thread_send_lsack);
1905 oi->thread_send_lsack =
1906 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1907
1908 ospf6_lsa_unlock (lsa);
1909 break;
1910 }
1911
1912 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1913 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1914 p += sizeof (struct ospf6_lsa_header);
1915
1916 assert (lsa->lock == 2);
1917 ospf6_lsdb_remove (lsa, oi->lsack_list);
1918 }
1919
1920 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1921 oh->length = htons (p - sendbuf);
1922
1923 if (oi->state == OSPF6_INTERFACE_DR ||
1924 oi->state == OSPF6_INTERFACE_BDR)
1925 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1926 else
1927 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1928
1929 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1930 {
1931 oi->thread_send_lsack =
1932 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1933 }
paul718e3742002-12-13 20:15:29 +00001934
1935 return 0;
1936}
1937
1938
hasso508e53e2004-05-18 18:57:06 +00001939/* Commands */
1940DEFUN (debug_ospf6_message,
1941 debug_ospf6_message_cmd,
1942 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1943 DEBUG_STR
1944 OSPF6_STR
1945 "Debug OSPFv3 message\n"
1946 "Debug Unknown message\n"
1947 "Debug Hello message\n"
1948 "Debug Database Description message\n"
1949 "Debug Link State Request message\n"
1950 "Debug Link State Update message\n"
1951 "Debug Link State Acknowledgement message\n"
1952 "Debug All message\n"
1953 )
paul718e3742002-12-13 20:15:29 +00001954{
hasso508e53e2004-05-18 18:57:06 +00001955 unsigned char level = 0;
1956 int type = 0;
paul718e3742002-12-13 20:15:29 +00001957 int i;
1958
hasso508e53e2004-05-18 18:57:06 +00001959 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001960
hasso508e53e2004-05-18 18:57:06 +00001961 /* check type */
1962 if (! strncmp (argv[0], "u", 1))
1963 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1964 else if (! strncmp (argv[0], "h", 1))
1965 type = OSPF6_MESSAGE_TYPE_HELLO;
1966 else if (! strncmp (argv[0], "d", 1))
1967 type = OSPF6_MESSAGE_TYPE_DBDESC;
1968 else if (! strncmp (argv[0], "lsr", 3))
1969 type = OSPF6_MESSAGE_TYPE_LSREQ;
1970 else if (! strncmp (argv[0], "lsu", 3))
1971 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1972 else if (! strncmp (argv[0], "lsa", 3))
1973 type = OSPF6_MESSAGE_TYPE_LSACK;
1974 else if (! strncmp (argv[0], "a", 1))
1975 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001976
hasso508e53e2004-05-18 18:57:06 +00001977 if (argc == 1)
1978 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1979 else if (! strncmp (argv[1], "s", 1))
1980 level = OSPF6_DEBUG_MESSAGE_SEND;
1981 else if (! strncmp (argv[1], "r", 1))
1982 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001983
hasso508e53e2004-05-18 18:57:06 +00001984 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001985 {
hasso508e53e2004-05-18 18:57:06 +00001986 for (i = 0; i < 6; i++)
1987 OSPF6_DEBUG_MESSAGE_ON (i, level);
1988 }
1989 else
1990 OSPF6_DEBUG_MESSAGE_ON (type, level);
1991
1992 return CMD_SUCCESS;
1993}
1994
1995ALIAS (debug_ospf6_message,
1996 debug_ospf6_message_sendrecv_cmd,
1997 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1998 DEBUG_STR
1999 OSPF6_STR
2000 "Debug OSPFv3 message\n"
2001 "Debug Unknown message\n"
2002 "Debug Hello message\n"
2003 "Debug Database Description message\n"
2004 "Debug Link State Request message\n"
2005 "Debug Link State Update message\n"
2006 "Debug Link State Acknowledgement message\n"
2007 "Debug All message\n"
2008 "Debug only sending message\n"
2009 "Debug only receiving message\n"
2010 );
2011
2012
2013DEFUN (no_debug_ospf6_message,
2014 no_debug_ospf6_message_cmd,
2015 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2016 NO_STR
2017 DEBUG_STR
2018 OSPF6_STR
2019 "Debug OSPFv3 message\n"
2020 "Debug Unknown message\n"
2021 "Debug Hello message\n"
2022 "Debug Database Description message\n"
2023 "Debug Link State Request message\n"
2024 "Debug Link State Update message\n"
2025 "Debug Link State Acknowledgement message\n"
2026 "Debug All message\n"
2027 )
2028{
2029 unsigned char level = 0;
2030 int type = 0;
2031 int i;
2032
2033 assert (argc > 0);
2034
2035 /* check type */
2036 if (! strncmp (argv[0], "u", 1))
2037 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2038 else if (! strncmp (argv[0], "h", 1))
2039 type = OSPF6_MESSAGE_TYPE_HELLO;
2040 else if (! strncmp (argv[0], "d", 1))
2041 type = OSPF6_MESSAGE_TYPE_DBDESC;
2042 else if (! strncmp (argv[0], "lsr", 3))
2043 type = OSPF6_MESSAGE_TYPE_LSREQ;
2044 else if (! strncmp (argv[0], "lsu", 3))
2045 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2046 else if (! strncmp (argv[0], "lsa", 3))
2047 type = OSPF6_MESSAGE_TYPE_LSACK;
2048 else if (! strncmp (argv[0], "a", 1))
2049 type = OSPF6_MESSAGE_TYPE_ALL;
2050
2051 if (argc == 1)
2052 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2053 else if (! strncmp (argv[1], "s", 1))
2054 level = OSPF6_DEBUG_MESSAGE_SEND;
2055 else if (! strncmp (argv[1], "r", 1))
2056 level = OSPF6_DEBUG_MESSAGE_RECV;
2057
2058 if (type == OSPF6_MESSAGE_TYPE_ALL)
2059 {
2060 for (i = 0; i < 6; i++)
2061 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2062 }
2063 else
2064 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2065
2066 return CMD_SUCCESS;
2067}
2068
2069ALIAS (no_debug_ospf6_message,
2070 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002071 "no debug ospf6 message "
2072 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002073 NO_STR
2074 DEBUG_STR
2075 OSPF6_STR
2076 "Debug OSPFv3 message\n"
2077 "Debug Unknown message\n"
2078 "Debug Hello message\n"
2079 "Debug Database Description message\n"
2080 "Debug Link State Request message\n"
2081 "Debug Link State Update message\n"
2082 "Debug Link State Acknowledgement message\n"
2083 "Debug All message\n"
2084 "Debug only sending message\n"
2085 "Debug only receiving message\n"
2086 );
2087
2088int
2089config_write_ospf6_debug_message (struct vty *vty)
2090{
2091 char *type_str[] = {"unknown", "hello", "dbdesc",
2092 "lsreq", "lsupdate", "lsack"};
2093 unsigned char s = 0, r = 0;
2094 int i;
2095
2096 for (i = 0; i < 6; i++)
2097 {
2098 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2099 s |= 1 << i;
2100 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2101 r |= 1 << i;
2102 }
2103
2104 if (s == 0x3f && r == 0x3f)
2105 {
hasso049207c2004-08-04 20:02:13 +00002106 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002107 return 0;
2108 }
2109
hasso508e53e2004-05-18 18:57:06 +00002110 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002111 {
hasso049207c2004-08-04 20:02:13 +00002112 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002113 return 0;
2114 }
2115 else if (s == 0 && r == 0x3f)
2116 {
hasso049207c2004-08-04 20:02:13 +00002117 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002118 return 0;
paul718e3742002-12-13 20:15:29 +00002119 }
2120
hasso508e53e2004-05-18 18:57:06 +00002121 /* Unknown message is logged by default */
2122 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2123 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002124 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002125 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002126 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002127 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002128 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002129
hasso508e53e2004-05-18 18:57:06 +00002130 for (i = 1; i < 6; i++)
2131 {
2132 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2133 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002134 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002135 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2136 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002137 VNL);
hasso508e53e2004-05-18 18:57:06 +00002138 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2139 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002140 VNL);
hasso508e53e2004-05-18 18:57:06 +00002141 }
paul718e3742002-12-13 20:15:29 +00002142
2143 return 0;
2144}
2145
paul718e3742002-12-13 20:15:29 +00002146void
hasso508e53e2004-05-18 18:57:06 +00002147install_element_ospf6_debug_message ()
paul718e3742002-12-13 20:15:29 +00002148{
hasso508e53e2004-05-18 18:57:06 +00002149 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2150 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2151 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2152 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2153 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2154 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2155 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2156 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002157}
2158
paul718e3742002-12-13 20:15:29 +00002159