blob: 71ff3628341951eaa505686d10f2d7466ee08658 [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
paul718e3742002-12-13 20:15:29 +000031#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000032#include "ospf6_proto.h"
33#include "ospf6_lsa.h"
34#include "ospf6_lsdb.h"
35#include "ospf6_network.h"
36#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000037
hasso508e53e2004-05-18 18:57:06 +000038#include "ospf6_top.h"
39#include "ospf6_area.h"
40#include "ospf6_neighbor.h"
41#include "ospf6_interface.h"
42
43#include "ospf6_flood.h"
44
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 {
248 if (oh->area_id == 0)
249 {
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);
522 his->scope = ospf6_get_lsa_scope (his->header->type, on);
523 lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
524 if (lsdb == NULL)
525 {
526 zlog_warn ("Can't decide scoped LSDB");
527 ospf6_lsa_delete (his);
528 thread_add_event (master, seqnumber_mismatch, on, 0);
529 return;
530 }
531
532 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
533 ospf6_area_is_stub (on->ospf6_if->area))
534 {
535 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
536 zlog_info ("E-bit mismatch with LSA Headers");
537 ospf6_lsa_delete (his);
538 thread_add_event (master, seqnumber_mismatch, on, 0);
539 return;
540 }
541
542 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
543 his->header->adv_router, lsdb);
544 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
545 {
546 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
547 zlog_info ("Add %s's request-list: %s", on->name, his->name);
548 ospf6_lsdb_add (his, on->request_list);
549 }
550 else
551 ospf6_lsa_delete (his);
552 }
553
554 if (p != OSPF6_MESSAGE_END (oh))
555 {
556 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
557 zlog_info ("Trailing garbage ignored");
558 }
559
560 /* Increment sequence number */
561 on->dbdesc_seqnum ++;
562
563 /* schedule send lsreq */
564 if (on->thread_send_lsreq == NULL)
565 on->thread_send_lsreq =
566 thread_add_event (master, ospf6_lsreq_send, on, 0);
567
568 THREAD_OFF (on->thread_send_dbdesc);
569
570 /* More bit check */
571 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
572 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
573 thread_add_event (master, exchange_done, on, 0);
574 else
575 on->thread_send_dbdesc =
576 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
577
578 /* save last received dbdesc */
579 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
580}
581
582static void
583ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
584 struct ospf6_neighbor *on)
585{
586 struct ospf6_dbdesc *dbdesc;
587 char *p;
588
589 dbdesc = (struct ospf6_dbdesc *)
590 ((caddr_t) oh + sizeof (struct ospf6_header));
591
592 if (on->state < OSPF6_NEIGHBOR_INIT)
593 {
594 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
595 zlog_info ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000596 return;
597 }
598
hasso508e53e2004-05-18 18:57:06 +0000599 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000600 {
hasso508e53e2004-05-18 18:57:06 +0000601 case OSPF6_NEIGHBOR_TWOWAY:
602 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
603 zlog_info ("Neighbor state is 2-Way, ignore");
604 return;
605
606 case OSPF6_NEIGHBOR_INIT:
607 thread_execute (master, twoway_received, on, 0);
608 if (on->state != OSPF6_NEIGHBOR_EXSTART)
609 {
610 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
611 zlog_info ("Neighbor state is not ExStart, ignore");
612 return;
613 }
614 /* else fall through to ExStart */
615
616 case OSPF6_NEIGHBOR_EXSTART:
617 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
618 and process LSA Headers. Otherwise, ignore this message */
619 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
620 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
621 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
622 ntohs (oh->length) == sizeof (struct ospf6_header) +
623 sizeof (struct ospf6_dbdesc))
624 {
625 /* set the master/slave bit to slave */
626 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
627
628 /* set the DD sequence number to one specified by master */
629 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
630
631 /* schedule NegotiationDone */
632 thread_execute (master, negotiation_done, on, 0);
633
634 /* Record neighbor options */
635 memcpy (on->options, dbdesc->options, sizeof (on->options));
636 }
637 else
638 {
639 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
640 zlog_info ("Negotiation failed");
641 return;
642 }
643 break;
644
645 case OSPF6_NEIGHBOR_EXCHANGE:
646 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
647 {
648 /* Duplicated DatabaseDescription causes slave to retransmit */
649 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
650 zlog_info ("Duplicated dbdesc causes retransmit");
651 THREAD_OFF (on->thread_send_dbdesc);
652 on->thread_send_dbdesc =
653 thread_add_event (master, ospf6_dbdesc_send, on, 0);
654 return;
655 }
656
657 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
658 {
659 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
660 zlog_info ("Master/Slave bit mismatch");
661 thread_add_event (master, seqnumber_mismatch, on, 0);
662 return;
663 }
664
665 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
666 {
667 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
668 zlog_info ("Initialize bit mismatch");
669 thread_add_event (master, seqnumber_mismatch, on, 0);
670 return;
671 }
672
673 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
674 {
675 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
676 zlog_info ("Option field mismatch");
677 thread_add_event (master, seqnumber_mismatch, on, 0);
678 return;
679 }
680
681 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
682 {
683 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
684 zlog_info ("Sequence number mismatch (%#lx expected)",
685 (u_long) on->dbdesc_seqnum + 1);
686 thread_add_event (master, seqnumber_mismatch, on, 0);
687 return;
688 }
689 break;
690
691 case OSPF6_NEIGHBOR_LOADING:
692 case OSPF6_NEIGHBOR_FULL:
693 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
694 {
695 /* Duplicated DatabaseDescription causes slave to retransmit */
696 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
697 zlog_info ("Duplicated dbdesc causes retransmit");
698 THREAD_OFF (on->thread_send_dbdesc);
699 on->thread_send_dbdesc =
700 thread_add_event (master, ospf6_dbdesc_send, on, 0);
701 return;
702 }
703
704 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
705 zlog_info ("Not duplicate dbdesc in state %s",
706 ospf6_neighbor_state_str[on->state]);
707 thread_add_event (master, seqnumber_mismatch, on, 0);
708 return;
709
710 default:
711 assert (0);
712 break;
paul718e3742002-12-13 20:15:29 +0000713 }
714
hasso508e53e2004-05-18 18:57:06 +0000715 /* Process LSA headers */
716 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
717 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
718 p += sizeof (struct ospf6_lsa_header))
719 {
720 struct ospf6_lsa *his, *mine;
721 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000722
hasso508e53e2004-05-18 18:57:06 +0000723 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
724 his->scope = ospf6_get_lsa_scope (his->header->type, on);
725 lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
726 if (lsdb == NULL)
727 {
728 zlog_warn ("Can't decide scoped LSDB");
729 ospf6_lsa_delete (his);
730 thread_add_event (master, seqnumber_mismatch, on, 0);
731 return;
732 }
733
734 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
735 ospf6_area_is_stub (on->ospf6_if->area))
736 {
737 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
738 zlog_info ("E-bit mismatch with LSA Headers");
739 ospf6_lsa_delete (his);
740 thread_add_event (master, seqnumber_mismatch, on, 0);
741 return;
742 }
743
744 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
745 his->header->adv_router, lsdb);
746 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
747 {
748 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
749 zlog_info ("Add %s to request-list of %s", his->name, on->name);
750 ospf6_lsdb_add (his, on->request_list);
751 }
752 else
753 ospf6_lsa_delete (his);
754 }
755
756 if (p != OSPF6_MESSAGE_END (oh))
757 {
758 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
759 zlog_info ("Trailing garbage ignored");
760 }
761
762 /* Set sequence number to Master's */
763 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
764
765 /* schedule send lsreq */
766 if (on->thread_send_lsreq == NULL)
767 on->thread_send_lsreq =
768 thread_add_event (master, ospf6_lsreq_send, on, 0);
769
770 THREAD_OFF (on->thread_send_dbdesc);
771 on->thread_send_dbdesc =
772 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
773
774 /* save last received dbdesc */
775 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000776}
777
778void
hasso508e53e2004-05-18 18:57:06 +0000779ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
780 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000781{
hasso508e53e2004-05-18 18:57:06 +0000782 struct ospf6_neighbor *on;
783 struct ospf6_dbdesc *dbdesc;
784
785 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
786 return;
787
788 on = ospf6_neighbor_lookup (oh->router_id, oi);
789 if (on == NULL)
790 {
791 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
792 zlog_info ("Neighbor not found, ignore");
793 return;
794 }
795
796 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
797 {
798 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
799 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
800 return;
801 }
802
803 dbdesc = (struct ospf6_dbdesc *)
804 ((caddr_t) oh + sizeof (struct ospf6_header));
805
806 /* Interface MTU check */
807 if (ntohs (dbdesc->ifmtu) != oi->ifmtu)
808 {
809 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
810 zlog_info ("I/F MTU mismatch");
811 return;
812 }
813
814 if (dbdesc->reserved1 || dbdesc->reserved2)
815 {
816 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
817 zlog_info ("Non-0 reserved field in %s's DbDesc, correct",
818 on->name);
819 dbdesc->reserved1 = 0;
820 dbdesc->reserved2 = 0;
821 }
822
823 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
824 ospf6_dbdesc_recv_master (oh, on);
825 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
826 ospf6_dbdesc_recv_slave (oh, on);
827 else
828 {
829 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
830 zlog_info ("Can't decide which is master, ignore");
831 }
832}
833
834void
835ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
836 struct ospf6_interface *oi, struct ospf6_header *oh)
837{
838 struct ospf6_neighbor *on;
839 char *p;
840 struct ospf6_lsreq_entry *e;
841 void *scope = NULL;
842 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000843 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000844
hasso508e53e2004-05-18 18:57:06 +0000845 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
846 return;
paul718e3742002-12-13 20:15:29 +0000847
hasso508e53e2004-05-18 18:57:06 +0000848 on = ospf6_neighbor_lookup (oh->router_id, oi);
849 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000850 {
hasso508e53e2004-05-18 18:57:06 +0000851 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
852 zlog_info ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000853 return;
854 }
855
hasso508e53e2004-05-18 18:57:06 +0000856 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +0000857 {
hasso508e53e2004-05-18 18:57:06 +0000858 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
859 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +0000860 return;
861 }
862
hasso508e53e2004-05-18 18:57:06 +0000863 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
864 on->state != OSPF6_NEIGHBOR_LOADING &&
865 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000866 {
hasso508e53e2004-05-18 18:57:06 +0000867 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
868 zlog_info ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000869 return;
870 }
871
hasso508e53e2004-05-18 18:57:06 +0000872 /* Process each request */
873 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
874 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
875 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000876 {
hasso508e53e2004-05-18 18:57:06 +0000877 e = (struct ospf6_lsreq_entry *) p;
878 scope = ospf6_get_lsa_scope (e->type, on);
879 lsdb = ospf6_get_scoped_lsdb (e->type, scope);
paul718e3742002-12-13 20:15:29 +0000880
hasso508e53e2004-05-18 18:57:06 +0000881 /* Find database copy */
882 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
883 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000884 {
hasso508e53e2004-05-18 18:57:06 +0000885 char id[16], adv_router[16];
886 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
887 {
888 inet_ntop (AF_INET, &e->id, id, sizeof (id));
889 inet_ntop (AF_INET, &e->adv_router, adv_router,
890 sizeof (adv_router));
891 zlog_info ("Can't find requested [%s Id:%s Adv:%s]",
892 OSPF6_LSTYPE_NAME (e->type), id, adv_router);
893 }
894 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000895 return;
896 }
897
hasso508e53e2004-05-18 18:57:06 +0000898 if (IS_OSPF6_DEBUG_LSA (DATABASE))
899 zlog_info ("Add copy of %s to lsupdate_list of %s",
900 lsa->name, on->name);
901 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000902 }
903
hasso508e53e2004-05-18 18:57:06 +0000904 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000905 {
hasso508e53e2004-05-18 18:57:06 +0000906 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
907 zlog_info ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000908 }
909
hasso508e53e2004-05-18 18:57:06 +0000910 /* schedule send lsupdate */
911 THREAD_OFF (on->thread_send_lsupdate);
912 on->thread_send_lsupdate =
913 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000914}
915
916void
hasso508e53e2004-05-18 18:57:06 +0000917ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
918 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000919{
hasso508e53e2004-05-18 18:57:06 +0000920 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +0000921 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000922 unsigned long num;
923 char *p;
paul718e3742002-12-13 20:15:29 +0000924
hasso508e53e2004-05-18 18:57:06 +0000925 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
926 return;
paul718e3742002-12-13 20:15:29 +0000927
hasso508e53e2004-05-18 18:57:06 +0000928 on = ospf6_neighbor_lookup (oh->router_id, oi);
929 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000930 {
hasso508e53e2004-05-18 18:57:06 +0000931 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
932 zlog_info ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000933 return;
934 }
935
hasso508e53e2004-05-18 18:57:06 +0000936 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +0000937 {
hasso508e53e2004-05-18 18:57:06 +0000938 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
939 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +0000940 return;
941 }
942
hasso508e53e2004-05-18 18:57:06 +0000943 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
944 on->state != OSPF6_NEIGHBOR_LOADING &&
945 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000946 {
hasso508e53e2004-05-18 18:57:06 +0000947 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
948 zlog_info ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000949 return;
950 }
951
hasso508e53e2004-05-18 18:57:06 +0000952 lsupdate = (struct ospf6_lsupdate *)
953 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000954
hasso508e53e2004-05-18 18:57:06 +0000955 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +0000956
hasso508e53e2004-05-18 18:57:06 +0000957 /* Process LSAs */
958 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
959 p < OSPF6_MESSAGE_END (oh) &&
960 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
961 p += OSPF6_LSA_SIZE (p))
962 {
963 if (num == 0)
964 break;
965 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
966 {
967 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
968 zlog_info ("Malformed LSA length, quit processing");
969 break;
970 }
971
972 ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on);
973 num--;
974 }
975
976 if (num != 0)
977 {
978 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
979 zlog_info ("Malformed LSA number or LSA length");
980 }
981 if (p != OSPF6_MESSAGE_END (oh))
982 {
983 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
984 zlog_info ("Trailing garbage ignored");
985 }
paul718e3742002-12-13 20:15:29 +0000986
987 /* RFC2328 Section 10.9: When the neighbor responds to these requests
988 with the proper Link State Update packet(s), the Link state request
989 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +0000990 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +0000991 can be recognized as a response to our previous LS Request */
992 if (! IN6_IS_ADDR_MULTICAST (dst) &&
993 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
994 on->state == OSPF6_NEIGHBOR_LOADING))
995 {
996 THREAD_OFF (on->thread_send_lsreq);
997 on->thread_send_lsreq =
998 thread_add_event (master, ospf6_lsreq_send, on, 0);
999 }
paul718e3742002-12-13 20:15:29 +00001000}
1001
1002void
hasso508e53e2004-05-18 18:57:06 +00001003ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1004 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001005{
hasso508e53e2004-05-18 18:57:06 +00001006 struct ospf6_neighbor *on;
1007 char *p;
1008 struct ospf6_lsa *his, *mine;
1009 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001010
hasso508e53e2004-05-18 18:57:06 +00001011 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1012 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
1013 return;
paul718e3742002-12-13 20:15:29 +00001014
hasso508e53e2004-05-18 18:57:06 +00001015 on = ospf6_neighbor_lookup (oh->router_id, oi);
1016 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001017 {
hasso508e53e2004-05-18 18:57:06 +00001018 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1019 zlog_info ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001020 return;
1021 }
1022
hasso508e53e2004-05-18 18:57:06 +00001023 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +00001024 {
hasso508e53e2004-05-18 18:57:06 +00001025 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1026 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +00001027 return;
1028 }
1029
hasso508e53e2004-05-18 18:57:06 +00001030 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1031 on->state != OSPF6_NEIGHBOR_LOADING &&
1032 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001033 {
hasso508e53e2004-05-18 18:57:06 +00001034 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1035 zlog_info ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001036 return;
1037 }
1038
hasso508e53e2004-05-18 18:57:06 +00001039 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1040 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1041 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001042 {
hasso508e53e2004-05-18 18:57:06 +00001043 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
1044 his->scope = ospf6_get_lsa_scope (his->header->type, on);
1045 lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
paul718e3742002-12-13 20:15:29 +00001046
hasso508e53e2004-05-18 18:57:06 +00001047 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
1048 IS_OSPF6_DEBUG_LSA (SEND))
1049 zlog_info ("%s acknowledged by %s", his->name, on->name);
1050
1051 /* Find database copy */
1052 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1053 his->header->adv_router, lsdb);
1054 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001055 {
hasso508e53e2004-05-18 18:57:06 +00001056 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1057 zlog_info ("No database copy");
1058 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001059 continue;
1060 }
1061
hasso508e53e2004-05-18 18:57:06 +00001062 /* Check if the LSA is on his retrans-list */
1063 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1064 his->header->adv_router, on->retrans_list);
1065 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001066 {
hasso508e53e2004-05-18 18:57:06 +00001067 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1068 zlog_info ("Not on %s's retrans-list", on->name);
1069 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001070 continue;
1071 }
1072
hasso508e53e2004-05-18 18:57:06 +00001073 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001074 {
hasso508e53e2004-05-18 18:57:06 +00001075 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001076 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001077 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1078 zlog_info ("Questionable acknowledgement");
1079 ospf6_lsa_delete (his);
1080 continue;
paul718e3742002-12-13 20:15:29 +00001081 }
1082
hasso508e53e2004-05-18 18:57:06 +00001083 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
1084 IS_OSPF6_DEBUG_LSA (SEND))
1085 zlog_info ("Acknowledged, remove from %s's retrans-list",
1086 on->name);
1087
1088 if (OSPF6_LSA_IS_MAXAGE (mine))
1089 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
1090
1091 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1092 zlog_info ("remove %s from retrans_list of %s",
1093 mine->name, on->name);
hasso3b4cd3a2004-05-18 19:28:32 +00001094 ospf6_decrement_onretrans (mine);
hasso508e53e2004-05-18 18:57:06 +00001095 ospf6_lsdb_remove (mine, on->retrans_list);
1096 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001097 }
1098
hasso508e53e2004-05-18 18:57:06 +00001099 if (p != OSPF6_MESSAGE_END (oh))
1100 {
1101 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1102 zlog_info ("Trailing garbage ignored");
1103 }
paul718e3742002-12-13 20:15:29 +00001104}
1105
hasso3b4cd3a2004-05-18 19:28:32 +00001106char *recvbuf = NULL;
1107char *sendbuf = NULL;
1108int iobuflen = 0;
1109
1110int
1111ospf6_iobuf_size (int size)
1112{
1113 char *recvnew, *sendnew;
1114
1115 if (size <= iobuflen)
1116 return iobuflen;
1117
1118 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1119 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1120 if (recvnew == NULL || sendnew == NULL)
1121 {
hassob596c712004-07-09 18:33:43 +00001122 if (recvnew)
1123 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1124 if (sendnew)
1125 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hasso3b4cd3a2004-05-18 19:28:32 +00001126 zlog_info ("Could not allocate I/O buffer of size %d.", size);
1127 return iobuflen;
1128 }
1129
1130 if (recvbuf)
1131 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1132 if (sendbuf)
1133 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1134 recvbuf = recvnew;
1135 sendbuf = sendnew;
1136 iobuflen = size;
1137
1138 return iobuflen;
1139}
paul718e3742002-12-13 20:15:29 +00001140
1141int
1142ospf6_receive (struct thread *thread)
1143{
hasso508e53e2004-05-18 18:57:06 +00001144 int sockfd, len;
1145 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001146 struct in6_addr src, dst;
1147 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001148 struct iovec iovector[2];
1149 struct ospf6_interface *oi;
1150 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001151
1152 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001153 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001154 thread_add_read (master, ospf6_receive, NULL, sockfd);
1155
1156 /* initialize */
hasso3b4cd3a2004-05-18 19:28:32 +00001157 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001158 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001159 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001160 iovector[1].iov_base = NULL;
1161 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001162
1163 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001164 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001165 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001166 {
hasso508e53e2004-05-18 18:57:06 +00001167 zlog_err ("Excess message read");
1168 return 0;
1169 }
1170 else if (len < sizeof (struct ospf6_header))
1171 {
1172 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001173 return 0;
1174 }
1175
hasso508e53e2004-05-18 18:57:06 +00001176 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1177 if (oi == NULL || oi->area == NULL)
1178 {
1179 zlog_info ("Message received on disabled interface");
1180 return 0;
1181 }
1182
1183 oh = (struct ospf6_header *) recvbuf;
1184
1185 /* Log */
1186 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1187 {
1188 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1189 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
1190 zlog_info ("%s received on %s",
1191 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1192 zlog_info (" src: %s", srcname);
1193 zlog_info (" dst: %s", dstname);
1194 if (len != ntohs (oh->length))
1195 zlog_info ("Message length does not match actually received: %d", len);
1196
1197 switch (oh->type)
1198 {
1199 case OSPF6_MESSAGE_TYPE_HELLO:
1200 ospf6_hello_print (oh);
1201 break;
1202 case OSPF6_MESSAGE_TYPE_DBDESC:
1203 ospf6_dbdesc_print (oh);
1204 break;
1205 case OSPF6_MESSAGE_TYPE_LSREQ:
1206 ospf6_lsreq_print (oh);
1207 break;
1208 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1209 ospf6_lsupdate_print (oh);
1210 break;
1211 case OSPF6_MESSAGE_TYPE_LSACK:
1212 ospf6_lsack_print (oh);
1213 break;
1214 default:
1215 zlog_info ("Unknown message");
1216 break;
1217 }
1218 }
1219
1220 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1221 {
1222 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1223 zlog_info ("Ignore message on passive interface %s",
1224 oi->interface->name);
1225 return 0;
1226 }
1227
1228 switch (oh->type)
1229 {
1230 case OSPF6_MESSAGE_TYPE_HELLO:
1231 ospf6_hello_recv (&src, &dst, oi, oh);
1232 break;
1233
1234 case OSPF6_MESSAGE_TYPE_DBDESC:
1235 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1236 break;
1237
1238 case OSPF6_MESSAGE_TYPE_LSREQ:
1239 ospf6_lsreq_recv (&src, &dst, oi, oh);
1240 break;
1241
1242 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1243 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1244 break;
1245
1246 case OSPF6_MESSAGE_TYPE_LSACK:
1247 ospf6_lsack_recv (&src, &dst, oi, oh);
1248 break;
1249
1250 default:
1251 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1252 zlog_info ("Unknown message");
1253 break;
1254 }
1255
1256 return 0;
1257}
1258
1259void
1260ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1261 struct ospf6_interface *oi, struct ospf6_header *oh)
1262{
1263 int len;
1264 char srcname[64], dstname[64];
1265 struct iovec iovector[2];
1266
1267 /* initialize */
1268 iovector[0].iov_base = (caddr_t) oh;
1269 iovector[0].iov_len = ntohs (oh->length);
1270 iovector[1].iov_base = NULL;
1271 iovector[1].iov_len = 0;
1272
1273 /* fill OSPF header */
1274 oh->version = OSPFV3_VERSION;
1275 /* message type must be set before */
1276 /* message length must be set before */
1277 oh->router_id = oi->area->ospf6->router_id;
1278 oh->area_id = oi->area->area_id;
1279 /* checksum is calculated by kernel */
1280 oh->instance_id = oi->instance_id;
1281 oh->reserved = 0;
1282
1283 /* Log */
1284 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1285 {
1286 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1287 if (src)
1288 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1289 else
1290 memset (srcname, 0, sizeof (srcname));
1291 zlog_info ("%s send on %s",
1292 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1293 zlog_info (" src: %s", srcname);
1294 zlog_info (" dst: %s", dstname);
1295
1296 switch (oh->type)
1297 {
1298 case OSPF6_MESSAGE_TYPE_HELLO:
1299 ospf6_hello_print (oh);
1300 break;
1301 case OSPF6_MESSAGE_TYPE_DBDESC:
1302 ospf6_dbdesc_print (oh);
1303 break;
1304 case OSPF6_MESSAGE_TYPE_LSREQ:
1305 ospf6_lsreq_print (oh);
1306 break;
1307 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1308 ospf6_lsupdate_print (oh);
1309 break;
1310 case OSPF6_MESSAGE_TYPE_LSACK:
1311 ospf6_lsack_print (oh);
1312 break;
1313 default:
1314 zlog_info ("Unknown message");
1315 assert (0);
1316 break;
1317 }
1318 }
1319
1320 /* send message */
1321 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1322 if (len != ntohs (oh->length))
1323 zlog_err ("Could not send entire message");
1324}
1325
1326int
1327ospf6_hello_send (struct thread *thread)
1328{
1329 struct ospf6_interface *oi;
1330 struct ospf6_header *oh;
1331 struct ospf6_hello *hello;
1332 char *p;
1333 listnode node;
1334 struct ospf6_neighbor *on;
1335
1336 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1337 oi->thread_send_hello = (struct thread *) NULL;
1338
1339 if (oi->state <= OSPF6_INTERFACE_DOWN)
1340 {
1341 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1342 zlog_info ("Unable to send Hello on down interface %s",
1343 oi->interface->name);
1344 return 0;
1345 }
1346
1347 /* set next thread */
1348 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1349 oi, oi->hello_interval);
1350
hasso3b4cd3a2004-05-18 19:28:32 +00001351 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001352 oh = (struct ospf6_header *) sendbuf;
1353 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1354
1355 hello->interface_id = htonl (oi->interface->ifindex);
1356 hello->priority = oi->priority;
1357 hello->options[0] = oi->area->options[0];
1358 hello->options[1] = oi->area->options[1];
1359 hello->options[2] = oi->area->options[2];
1360 hello->hello_interval = htons (oi->hello_interval);
1361 hello->dead_interval = htons (oi->dead_interval);
1362 hello->drouter = oi->drouter;
1363 hello->bdrouter = oi->bdrouter;
1364
1365 p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello));
1366
1367 for (node = listhead (oi->neighbor_list); node; nextnode (node))
1368 {
1369 on = (struct ospf6_neighbor *) getdata (node);
1370
1371 if (on->state < OSPF6_NEIGHBOR_INIT)
1372 continue;
1373
1374 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1375 {
1376 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1377 zlog_info ("sending Hello message: exceeds I/F MTU");
1378 break;
1379 }
1380
1381 memcpy (p, &on->router_id, sizeof (u_int32_t));
1382 p += sizeof (u_int32_t);
1383 }
1384
1385 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1386 oh->length = htons (p - sendbuf);
1387
1388 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1389 return 0;
1390}
1391
1392int
1393ospf6_dbdesc_send (struct thread *thread)
1394{
1395 struct ospf6_neighbor *on;
1396 struct ospf6_header *oh;
1397 struct ospf6_dbdesc *dbdesc;
1398 char *p;
1399 struct ospf6_lsa *lsa;
1400
1401 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1402 on->thread_send_dbdesc = (struct thread *) NULL;
1403
1404 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1405 {
1406 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
1407 zlog_info ("Quit to send DbDesc to neighbor %s state %s",
1408 on->name, ospf6_neighbor_state_str[on->state]);
1409 return 0;
1410 }
1411
1412 /* set next thread if master */
1413 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1414 on->thread_send_dbdesc =
1415 thread_add_timer (master, ospf6_dbdesc_send, on,
1416 on->ospf6_if->rxmt_interval);
1417
hasso3b4cd3a2004-05-18 19:28:32 +00001418 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001419 oh = (struct ospf6_header *) sendbuf;
1420 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1421 sizeof (struct ospf6_header));
1422
1423 /* if this is initial one, initialize sequence number for DbDesc */
1424 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1425 {
1426 struct timeval tv;
1427 if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
1428 tv.tv_sec = 1;
1429 on->dbdesc_seqnum = tv.tv_sec;
1430 }
1431
1432 dbdesc->options[0] = on->ospf6_if->area->options[0];
1433 dbdesc->options[1] = on->ospf6_if->area->options[1];
1434 dbdesc->options[2] = on->ospf6_if->area->options[2];
1435 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1436 dbdesc->bits = on->dbdesc_bits;
1437 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1438
1439 /* if this is not initial one, set LSA headers in dbdesc */
1440 p = (char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
1441 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1442 {
1443 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1444 lsa = ospf6_lsdb_next (lsa))
1445 {
1446 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1447
1448 /* MTU check */
1449 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1450 on->ospf6_if->ifmtu)
1451 {
1452 ospf6_lsa_unlock (lsa);
1453 break;
1454 }
1455 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1456 p += sizeof (struct ospf6_lsa_header);
1457 }
1458 }
1459
1460 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1461 oh->length = htons (p - sendbuf);
1462
1463 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1464 on->ospf6_if, oh);
1465 return 0;
1466}
1467
1468int
1469ospf6_dbdesc_send_newone (struct thread *thread)
1470{
1471 struct ospf6_neighbor *on;
1472 struct ospf6_lsa *lsa;
1473 unsigned int size = 0;
1474
1475 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1476 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1477 zlog_info ("Remove entire dbdesc_list of %s: sending newone", on->name);
1478 ospf6_lsdb_remove_all (on->dbdesc_list);
1479
1480 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1481 so that ospf6_send_dbdesc () can send those LSAs */
1482 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1483 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1484 lsa = ospf6_lsdb_next (lsa))
1485 {
1486 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1487 {
1488 ospf6_lsa_unlock (lsa);
1489 break;
1490 }
1491
1492 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1493 zlog_info ("Move %s from summary_list to dbdesc_list of %s",
1494 lsa->name, on->name);
1495 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1496 ospf6_lsdb_remove (lsa, on->summary_list);
1497 size += sizeof (struct ospf6_lsa_header);
1498 }
1499
1500 if (on->summary_list->count == 0)
1501 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1502
1503 /* If slave, More bit check must be done here */
1504 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1505 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1506 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1507 thread_add_event (master, exchange_done, on, 0);
1508
1509 thread_execute (master, ospf6_dbdesc_send, on, 0);
1510 return 0;
1511}
1512
1513int
1514ospf6_lsreq_send (struct thread *thread)
1515{
1516 struct ospf6_neighbor *on;
1517 struct ospf6_header *oh;
1518 struct ospf6_lsreq_entry *e;
1519 char *p;
1520 struct ospf6_lsa *lsa;
1521
1522 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1523 on->thread_send_lsreq = (struct thread *) NULL;
1524
1525 /* LSReq will be sent only in ExStart or Loading */
1526 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1527 on->state != OSPF6_NEIGHBOR_LOADING)
1528 {
1529 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
1530 zlog_info ("Quit to send LSReq to neighbor %s state %s",
1531 on->name, ospf6_neighbor_state_str[on->state]);
1532 return 0;
1533 }
1534
1535 /* schedule loading_done if request list is empty */
1536 if (on->request_list->count == 0)
1537 {
1538 thread_add_event (master, loading_done, on, 0);
1539 return 0;
1540 }
1541
1542 /* set next thread */
1543 on->thread_send_lsreq =
1544 thread_add_timer (master, ospf6_lsreq_send, on,
1545 on->ospf6_if->rxmt_interval);
1546
hasso3b4cd3a2004-05-18 19:28:32 +00001547 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001548 oh = (struct ospf6_header *) sendbuf;
1549
1550 /* set Request entries in lsreq */
1551 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1552 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1553 lsa = ospf6_lsdb_next (lsa))
1554 {
1555 /* MTU check */
1556 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
1557 {
1558 ospf6_lsa_unlock (lsa);
1559 break;
1560 }
1561
1562 e = (struct ospf6_lsreq_entry *) p;
1563 e->type = lsa->header->type;
1564 e->id = lsa->header->id;
1565 e->adv_router = lsa->header->adv_router;
1566 p += sizeof (struct ospf6_lsreq_entry);
1567 }
1568
1569 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1570 oh->length = htons (p - sendbuf);
1571
1572 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1573 on->ospf6_if, oh);
1574 return 0;
1575}
1576
1577int
1578ospf6_lsupdate_send_neighbor (struct thread *thread)
1579{
1580 struct ospf6_neighbor *on;
1581 struct ospf6_header *oh;
1582 struct ospf6_lsupdate *lsupdate;
1583 char *p;
1584 int num;
1585 struct ospf6_lsa *lsa;
1586
1587 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1588 on->thread_send_lsupdate = (struct thread *) NULL;
1589
1590 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1591 {
1592 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1593 zlog_info ("Quit to send LSUpdate to neighbor %s state %s",
1594 on->name, ospf6_neighbor_state_str[on->state]);
1595 return 0;
1596 }
1597
1598 /* if we have nothing to send, return */
1599 if (on->lsupdate_list->count == 0 &&
1600 on->retrans_list->count == 0)
1601 return 0;
1602
1603 if (IS_OSPF6_DEBUG_LSA (SEND))
1604 zlog_info ("LSA Send to %s", on->name);
1605
hasso3b4cd3a2004-05-18 19:28:32 +00001606 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001607 oh = (struct ospf6_header *) sendbuf;
1608 lsupdate = (struct ospf6_lsupdate *)
1609 ((caddr_t) oh + sizeof (struct ospf6_header));
1610
1611 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1612 num = 0;
1613
1614 /* lsupdate_list lists those LSA which doesn't need to be
1615 retransmitted. remove those from the list */
1616 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1617 lsa = ospf6_lsdb_next (lsa))
1618 {
1619 /* MTU check */
1620 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1621 {
1622 ospf6_lsa_unlock (lsa);
1623 break;
1624 }
1625
1626 if (IS_OSPF6_DEBUG_LSA (SEND))
1627 ospf6_lsa_header_print (lsa);
1628
1629 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1630 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1631 p += OSPF6_LSA_SIZE (lsa->header);
1632 num++;
1633
1634 assert (lsa->lock == 2);
1635 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1636 }
1637
1638 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1639 lsa = ospf6_lsdb_next (lsa))
1640 {
1641 /* MTU check */
1642 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1643 {
1644 ospf6_lsa_unlock (lsa);
1645 break;
1646 }
1647
1648 if (IS_OSPF6_DEBUG_LSA (SEND))
1649 ospf6_lsa_header_print (lsa);
1650
1651 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1652 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1653 p += OSPF6_LSA_SIZE (lsa->header);
1654 num++;
1655 }
1656
1657 lsupdate->lsa_number = htonl (num);
1658
1659 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1660 oh->length = htons (p - sendbuf);
1661
1662 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1663 on->ospf6_if, oh);
1664
1665 if (on->lsupdate_list->count != 0 ||
1666 on->retrans_list->count != 0)
1667 {
1668 if (on->lsupdate_list->count != 0)
1669 on->thread_send_lsupdate =
1670 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1671 else
1672 on->thread_send_lsupdate =
1673 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1674 on->ospf6_if->rxmt_interval);
1675 }
1676
1677 return 0;
1678}
1679
1680int
1681ospf6_lsupdate_send_interface (struct thread *thread)
1682{
1683 struct ospf6_interface *oi;
1684 struct ospf6_header *oh;
1685 struct ospf6_lsupdate *lsupdate;
1686 char *p;
1687 int num;
1688 struct ospf6_lsa *lsa;
1689
1690 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1691 oi->thread_send_lsupdate = (struct thread *) NULL;
1692
1693 if (oi->state <= OSPF6_INTERFACE_WAITING)
1694 {
1695 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1696 zlog_info ("Quit to send LSUpdate to interface %s state %s",
1697 oi->interface->name, ospf6_interface_state_str[oi->state]);
1698 return 0;
1699 }
1700
1701 /* if we have nothing to send, return */
1702 if (oi->lsupdate_list->count == 0)
1703 return 0;
1704
1705 if (IS_OSPF6_DEBUG_LSA (SEND))
1706 zlog_info ("LSA Send to %s", oi->interface->name);
1707
hasso3b4cd3a2004-05-18 19:28:32 +00001708 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001709 oh = (struct ospf6_header *) sendbuf;
1710 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1711 sizeof (struct ospf6_header));
1712
1713 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1714 num = 0;
1715
1716 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1717 lsa = ospf6_lsdb_next (lsa))
1718 {
1719 /* MTU check */
1720 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > oi->ifmtu)
1721 {
1722 ospf6_lsa_unlock (lsa);
1723 break;
1724 }
1725
1726 if (IS_OSPF6_DEBUG_LSA (SEND))
1727 ospf6_lsa_header_print (lsa);
1728
1729 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1730 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1731 p += OSPF6_LSA_SIZE (lsa->header);
1732 num++;
1733
1734 assert (lsa->lock == 2);
1735 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1736 }
1737
1738 lsupdate->lsa_number = htonl (num);
1739
1740 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1741 oh->length = htons (p - sendbuf);
1742
1743 if (oi->state == OSPF6_INTERFACE_DR ||
1744 oi->state == OSPF6_INTERFACE_BDR)
1745 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1746 else
1747 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1748
1749 if (oi->lsupdate_list->count > 0)
1750 {
1751 oi->thread_send_lsupdate =
1752 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1753 }
1754
1755 return 0;
1756}
1757
1758int
1759ospf6_lsack_send_neighbor (struct thread *thread)
1760{
1761 struct ospf6_neighbor *on;
1762 struct ospf6_header *oh;
1763 char *p;
1764 struct ospf6_lsa *lsa;
1765
1766 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1767 on->thread_send_lsack = (struct thread *) NULL;
1768
1769 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1770 {
1771 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1772 zlog_info ("Quit to send LSAck to neighbor %s state %s",
1773 on->name, ospf6_neighbor_state_str[on->state]);
1774 return 0;
1775 }
1776
1777 /* if we have nothing to send, return */
1778 if (on->lsack_list->count == 0)
1779 return 0;
1780
hasso3b4cd3a2004-05-18 19:28:32 +00001781 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001782 oh = (struct ospf6_header *) sendbuf;
1783
1784 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1785
1786 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1787 lsa = ospf6_lsdb_next (lsa))
1788 {
1789 /* MTU check */
1790 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1791 {
1792 /* if we run out of packet size/space here,
1793 better to try again soon. */
1794 THREAD_OFF (on->thread_send_lsack);
1795 on->thread_send_lsack =
1796 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1797
1798 ospf6_lsa_unlock (lsa);
1799 break;
1800 }
1801
1802 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1803 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1804 p += sizeof (struct ospf6_lsa_header);
1805
1806 assert (lsa->lock == 2);
1807 ospf6_lsdb_remove (lsa, on->lsack_list);
1808 }
1809
1810 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1811 oh->length = htons (p - sendbuf);
1812
1813 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1814 on->ospf6_if, oh);
1815 return 0;
1816}
1817
1818int
1819ospf6_lsack_send_interface (struct thread *thread)
1820{
1821 struct ospf6_interface *oi;
1822 struct ospf6_header *oh;
1823 char *p;
1824 struct ospf6_lsa *lsa;
1825
1826 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1827 oi->thread_send_lsack = (struct thread *) NULL;
1828
1829 if (oi->state <= OSPF6_INTERFACE_WAITING)
1830 {
1831 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1832 zlog_info ("Quit to send LSAck to interface %s state %s",
1833 oi->interface->name, ospf6_interface_state_str[oi->state]);
1834 return 0;
1835 }
1836
1837 /* if we have nothing to send, return */
1838 if (oi->lsack_list->count == 0)
1839 return 0;
1840
hasso3b4cd3a2004-05-18 19:28:32 +00001841 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001842 oh = (struct ospf6_header *) sendbuf;
1843
1844 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1845
1846 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1847 lsa = ospf6_lsdb_next (lsa))
1848 {
1849 /* MTU check */
1850 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
1851 {
1852 /* if we run out of packet size/space here,
1853 better to try again soon. */
1854 THREAD_OFF (oi->thread_send_lsack);
1855 oi->thread_send_lsack =
1856 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1857
1858 ospf6_lsa_unlock (lsa);
1859 break;
1860 }
1861
1862 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1863 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1864 p += sizeof (struct ospf6_lsa_header);
1865
1866 assert (lsa->lock == 2);
1867 ospf6_lsdb_remove (lsa, oi->lsack_list);
1868 }
1869
1870 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1871 oh->length = htons (p - sendbuf);
1872
1873 if (oi->state == OSPF6_INTERFACE_DR ||
1874 oi->state == OSPF6_INTERFACE_BDR)
1875 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1876 else
1877 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1878
1879 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1880 {
1881 oi->thread_send_lsack =
1882 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1883 }
paul718e3742002-12-13 20:15:29 +00001884
1885 return 0;
1886}
1887
1888
hasso508e53e2004-05-18 18:57:06 +00001889/* Commands */
1890DEFUN (debug_ospf6_message,
1891 debug_ospf6_message_cmd,
1892 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1893 DEBUG_STR
1894 OSPF6_STR
1895 "Debug OSPFv3 message\n"
1896 "Debug Unknown message\n"
1897 "Debug Hello message\n"
1898 "Debug Database Description message\n"
1899 "Debug Link State Request message\n"
1900 "Debug Link State Update message\n"
1901 "Debug Link State Acknowledgement message\n"
1902 "Debug All message\n"
1903 )
paul718e3742002-12-13 20:15:29 +00001904{
hasso508e53e2004-05-18 18:57:06 +00001905 unsigned char level = 0;
1906 int type = 0;
paul718e3742002-12-13 20:15:29 +00001907 int i;
1908
hasso508e53e2004-05-18 18:57:06 +00001909 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001910
hasso508e53e2004-05-18 18:57:06 +00001911 /* check type */
1912 if (! strncmp (argv[0], "u", 1))
1913 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1914 else if (! strncmp (argv[0], "h", 1))
1915 type = OSPF6_MESSAGE_TYPE_HELLO;
1916 else if (! strncmp (argv[0], "d", 1))
1917 type = OSPF6_MESSAGE_TYPE_DBDESC;
1918 else if (! strncmp (argv[0], "lsr", 3))
1919 type = OSPF6_MESSAGE_TYPE_LSREQ;
1920 else if (! strncmp (argv[0], "lsu", 3))
1921 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1922 else if (! strncmp (argv[0], "lsa", 3))
1923 type = OSPF6_MESSAGE_TYPE_LSACK;
1924 else if (! strncmp (argv[0], "a", 1))
1925 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001926
hasso508e53e2004-05-18 18:57:06 +00001927 if (argc == 1)
1928 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1929 else if (! strncmp (argv[1], "s", 1))
1930 level = OSPF6_DEBUG_MESSAGE_SEND;
1931 else if (! strncmp (argv[1], "r", 1))
1932 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001933
hasso508e53e2004-05-18 18:57:06 +00001934 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001935 {
hasso508e53e2004-05-18 18:57:06 +00001936 for (i = 0; i < 6; i++)
1937 OSPF6_DEBUG_MESSAGE_ON (i, level);
1938 }
1939 else
1940 OSPF6_DEBUG_MESSAGE_ON (type, level);
1941
1942 return CMD_SUCCESS;
1943}
1944
1945ALIAS (debug_ospf6_message,
1946 debug_ospf6_message_sendrecv_cmd,
1947 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1948 DEBUG_STR
1949 OSPF6_STR
1950 "Debug OSPFv3 message\n"
1951 "Debug Unknown message\n"
1952 "Debug Hello message\n"
1953 "Debug Database Description message\n"
1954 "Debug Link State Request message\n"
1955 "Debug Link State Update message\n"
1956 "Debug Link State Acknowledgement message\n"
1957 "Debug All message\n"
1958 "Debug only sending message\n"
1959 "Debug only receiving message\n"
1960 );
1961
1962
1963DEFUN (no_debug_ospf6_message,
1964 no_debug_ospf6_message_cmd,
1965 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1966 NO_STR
1967 DEBUG_STR
1968 OSPF6_STR
1969 "Debug OSPFv3 message\n"
1970 "Debug Unknown message\n"
1971 "Debug Hello message\n"
1972 "Debug Database Description message\n"
1973 "Debug Link State Request message\n"
1974 "Debug Link State Update message\n"
1975 "Debug Link State Acknowledgement message\n"
1976 "Debug All message\n"
1977 )
1978{
1979 unsigned char level = 0;
1980 int type = 0;
1981 int i;
1982
1983 assert (argc > 0);
1984
1985 /* check type */
1986 if (! strncmp (argv[0], "u", 1))
1987 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1988 else if (! strncmp (argv[0], "h", 1))
1989 type = OSPF6_MESSAGE_TYPE_HELLO;
1990 else if (! strncmp (argv[0], "d", 1))
1991 type = OSPF6_MESSAGE_TYPE_DBDESC;
1992 else if (! strncmp (argv[0], "lsr", 3))
1993 type = OSPF6_MESSAGE_TYPE_LSREQ;
1994 else if (! strncmp (argv[0], "lsu", 3))
1995 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1996 else if (! strncmp (argv[0], "lsa", 3))
1997 type = OSPF6_MESSAGE_TYPE_LSACK;
1998 else if (! strncmp (argv[0], "a", 1))
1999 type = OSPF6_MESSAGE_TYPE_ALL;
2000
2001 if (argc == 1)
2002 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2003 else if (! strncmp (argv[1], "s", 1))
2004 level = OSPF6_DEBUG_MESSAGE_SEND;
2005 else if (! strncmp (argv[1], "r", 1))
2006 level = OSPF6_DEBUG_MESSAGE_RECV;
2007
2008 if (type == OSPF6_MESSAGE_TYPE_ALL)
2009 {
2010 for (i = 0; i < 6; i++)
2011 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2012 }
2013 else
2014 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2015
2016 return CMD_SUCCESS;
2017}
2018
2019ALIAS (no_debug_ospf6_message,
2020 no_debug_ospf6_message_sendrecv_cmd,
2021 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2022 NO_STR
2023 DEBUG_STR
2024 OSPF6_STR
2025 "Debug OSPFv3 message\n"
2026 "Debug Unknown message\n"
2027 "Debug Hello message\n"
2028 "Debug Database Description message\n"
2029 "Debug Link State Request message\n"
2030 "Debug Link State Update message\n"
2031 "Debug Link State Acknowledgement message\n"
2032 "Debug All message\n"
2033 "Debug only sending message\n"
2034 "Debug only receiving message\n"
2035 );
2036
2037int
2038config_write_ospf6_debug_message (struct vty *vty)
2039{
2040 char *type_str[] = {"unknown", "hello", "dbdesc",
2041 "lsreq", "lsupdate", "lsack"};
2042 unsigned char s = 0, r = 0;
2043 int i;
2044
2045 for (i = 0; i < 6; i++)
2046 {
2047 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2048 s |= 1 << i;
2049 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2050 r |= 1 << i;
2051 }
2052
2053 if (s == 0x3f && r == 0x3f)
2054 {
2055 vty_out (vty, "debug ospf6 message all%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002056 return 0;
2057 }
2058
hasso508e53e2004-05-18 18:57:06 +00002059 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002060 {
hasso508e53e2004-05-18 18:57:06 +00002061 vty_out (vty, "debug ospf6 message all send%s", VTY_NEWLINE);
2062 return 0;
2063 }
2064 else if (s == 0 && r == 0x3f)
2065 {
2066 vty_out (vty, "debug ospf6 message all recv%s", VTY_NEWLINE);
2067 return 0;
paul718e3742002-12-13 20:15:29 +00002068 }
2069
hasso508e53e2004-05-18 18:57:06 +00002070 /* Unknown message is logged by default */
2071 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2072 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2073 vty_out (vty, "no debug ospf6 message unknown%s", VTY_NEWLINE);
2074 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
2075 vty_out (vty, "no debug ospf6 message unknown send%s", VTY_NEWLINE);
2076 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2077 vty_out (vty, "no debug ospf6 message unknown recv%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002078
hasso508e53e2004-05-18 18:57:06 +00002079 for (i = 1; i < 6; i++)
2080 {
2081 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2082 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2083 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VTY_NEWLINE);
2084 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2085 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
2086 VTY_NEWLINE);
2087 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2088 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
2089 VTY_NEWLINE);
2090 }
paul718e3742002-12-13 20:15:29 +00002091
2092 return 0;
2093}
2094
paul718e3742002-12-13 20:15:29 +00002095void
hasso508e53e2004-05-18 18:57:06 +00002096install_element_ospf6_debug_message ()
paul718e3742002-12-13 20:15:29 +00002097{
hasso508e53e2004-05-18 18:57:06 +00002098 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2099 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2100 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2101 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2102 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2103 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2104 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2105 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002106}
2107
paul718e3742002-12-13 20:15:29 +00002108