blob: 19ea2c773dfd85437225ace5541d62363e33338a [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 {
1122 zlog_info ("Could not allocate I/O buffer of size %d.", size);
1123 return iobuflen;
1124 }
1125
1126 if (recvbuf)
1127 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1128 if (sendbuf)
1129 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1130 recvbuf = recvnew;
1131 sendbuf = sendnew;
1132 iobuflen = size;
1133
1134 return iobuflen;
1135}
paul718e3742002-12-13 20:15:29 +00001136
1137int
1138ospf6_receive (struct thread *thread)
1139{
hasso508e53e2004-05-18 18:57:06 +00001140 int sockfd, len;
1141 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001142 struct in6_addr src, dst;
1143 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001144 struct iovec iovector[2];
1145 struct ospf6_interface *oi;
1146 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001147
1148 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001149 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001150 thread_add_read (master, ospf6_receive, NULL, sockfd);
1151
1152 /* initialize */
hasso3b4cd3a2004-05-18 19:28:32 +00001153 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001154 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001155 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001156 iovector[1].iov_base = NULL;
1157 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001158
1159 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001160 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001161 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001162 {
hasso508e53e2004-05-18 18:57:06 +00001163 zlog_err ("Excess message read");
1164 return 0;
1165 }
1166 else if (len < sizeof (struct ospf6_header))
1167 {
1168 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001169 return 0;
1170 }
1171
hasso508e53e2004-05-18 18:57:06 +00001172 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1173 if (oi == NULL || oi->area == NULL)
1174 {
1175 zlog_info ("Message received on disabled interface");
1176 return 0;
1177 }
1178
1179 oh = (struct ospf6_header *) recvbuf;
1180
1181 /* Log */
1182 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1183 {
1184 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1185 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
1186 zlog_info ("%s received on %s",
1187 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1188 zlog_info (" src: %s", srcname);
1189 zlog_info (" dst: %s", dstname);
1190 if (len != ntohs (oh->length))
1191 zlog_info ("Message length does not match actually received: %d", len);
1192
1193 switch (oh->type)
1194 {
1195 case OSPF6_MESSAGE_TYPE_HELLO:
1196 ospf6_hello_print (oh);
1197 break;
1198 case OSPF6_MESSAGE_TYPE_DBDESC:
1199 ospf6_dbdesc_print (oh);
1200 break;
1201 case OSPF6_MESSAGE_TYPE_LSREQ:
1202 ospf6_lsreq_print (oh);
1203 break;
1204 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1205 ospf6_lsupdate_print (oh);
1206 break;
1207 case OSPF6_MESSAGE_TYPE_LSACK:
1208 ospf6_lsack_print (oh);
1209 break;
1210 default:
1211 zlog_info ("Unknown message");
1212 break;
1213 }
1214 }
1215
1216 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1217 {
1218 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1219 zlog_info ("Ignore message on passive interface %s",
1220 oi->interface->name);
1221 return 0;
1222 }
1223
1224 switch (oh->type)
1225 {
1226 case OSPF6_MESSAGE_TYPE_HELLO:
1227 ospf6_hello_recv (&src, &dst, oi, oh);
1228 break;
1229
1230 case OSPF6_MESSAGE_TYPE_DBDESC:
1231 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1232 break;
1233
1234 case OSPF6_MESSAGE_TYPE_LSREQ:
1235 ospf6_lsreq_recv (&src, &dst, oi, oh);
1236 break;
1237
1238 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1239 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1240 break;
1241
1242 case OSPF6_MESSAGE_TYPE_LSACK:
1243 ospf6_lsack_recv (&src, &dst, oi, oh);
1244 break;
1245
1246 default:
1247 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1248 zlog_info ("Unknown message");
1249 break;
1250 }
1251
1252 return 0;
1253}
1254
1255void
1256ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1257 struct ospf6_interface *oi, struct ospf6_header *oh)
1258{
1259 int len;
1260 char srcname[64], dstname[64];
1261 struct iovec iovector[2];
1262
1263 /* initialize */
1264 iovector[0].iov_base = (caddr_t) oh;
1265 iovector[0].iov_len = ntohs (oh->length);
1266 iovector[1].iov_base = NULL;
1267 iovector[1].iov_len = 0;
1268
1269 /* fill OSPF header */
1270 oh->version = OSPFV3_VERSION;
1271 /* message type must be set before */
1272 /* message length must be set before */
1273 oh->router_id = oi->area->ospf6->router_id;
1274 oh->area_id = oi->area->area_id;
1275 /* checksum is calculated by kernel */
1276 oh->instance_id = oi->instance_id;
1277 oh->reserved = 0;
1278
1279 /* Log */
1280 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1281 {
1282 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1283 if (src)
1284 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1285 else
1286 memset (srcname, 0, sizeof (srcname));
1287 zlog_info ("%s send on %s",
1288 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1289 zlog_info (" src: %s", srcname);
1290 zlog_info (" dst: %s", dstname);
1291
1292 switch (oh->type)
1293 {
1294 case OSPF6_MESSAGE_TYPE_HELLO:
1295 ospf6_hello_print (oh);
1296 break;
1297 case OSPF6_MESSAGE_TYPE_DBDESC:
1298 ospf6_dbdesc_print (oh);
1299 break;
1300 case OSPF6_MESSAGE_TYPE_LSREQ:
1301 ospf6_lsreq_print (oh);
1302 break;
1303 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1304 ospf6_lsupdate_print (oh);
1305 break;
1306 case OSPF6_MESSAGE_TYPE_LSACK:
1307 ospf6_lsack_print (oh);
1308 break;
1309 default:
1310 zlog_info ("Unknown message");
1311 assert (0);
1312 break;
1313 }
1314 }
1315
1316 /* send message */
1317 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1318 if (len != ntohs (oh->length))
1319 zlog_err ("Could not send entire message");
1320}
1321
1322int
1323ospf6_hello_send (struct thread *thread)
1324{
1325 struct ospf6_interface *oi;
1326 struct ospf6_header *oh;
1327 struct ospf6_hello *hello;
1328 char *p;
1329 listnode node;
1330 struct ospf6_neighbor *on;
1331
1332 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1333 oi->thread_send_hello = (struct thread *) NULL;
1334
1335 if (oi->state <= OSPF6_INTERFACE_DOWN)
1336 {
1337 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1338 zlog_info ("Unable to send Hello on down interface %s",
1339 oi->interface->name);
1340 return 0;
1341 }
1342
1343 /* set next thread */
1344 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1345 oi, oi->hello_interval);
1346
hasso3b4cd3a2004-05-18 19:28:32 +00001347 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001348 oh = (struct ospf6_header *) sendbuf;
1349 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1350
1351 hello->interface_id = htonl (oi->interface->ifindex);
1352 hello->priority = oi->priority;
1353 hello->options[0] = oi->area->options[0];
1354 hello->options[1] = oi->area->options[1];
1355 hello->options[2] = oi->area->options[2];
1356 hello->hello_interval = htons (oi->hello_interval);
1357 hello->dead_interval = htons (oi->dead_interval);
1358 hello->drouter = oi->drouter;
1359 hello->bdrouter = oi->bdrouter;
1360
1361 p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello));
1362
1363 for (node = listhead (oi->neighbor_list); node; nextnode (node))
1364 {
1365 on = (struct ospf6_neighbor *) getdata (node);
1366
1367 if (on->state < OSPF6_NEIGHBOR_INIT)
1368 continue;
1369
1370 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1371 {
1372 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1373 zlog_info ("sending Hello message: exceeds I/F MTU");
1374 break;
1375 }
1376
1377 memcpy (p, &on->router_id, sizeof (u_int32_t));
1378 p += sizeof (u_int32_t);
1379 }
1380
1381 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1382 oh->length = htons (p - sendbuf);
1383
1384 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1385 return 0;
1386}
1387
1388int
1389ospf6_dbdesc_send (struct thread *thread)
1390{
1391 struct ospf6_neighbor *on;
1392 struct ospf6_header *oh;
1393 struct ospf6_dbdesc *dbdesc;
1394 char *p;
1395 struct ospf6_lsa *lsa;
1396
1397 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1398 on->thread_send_dbdesc = (struct thread *) NULL;
1399
1400 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1401 {
1402 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
1403 zlog_info ("Quit to send DbDesc to neighbor %s state %s",
1404 on->name, ospf6_neighbor_state_str[on->state]);
1405 return 0;
1406 }
1407
1408 /* set next thread if master */
1409 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1410 on->thread_send_dbdesc =
1411 thread_add_timer (master, ospf6_dbdesc_send, on,
1412 on->ospf6_if->rxmt_interval);
1413
hasso3b4cd3a2004-05-18 19:28:32 +00001414 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001415 oh = (struct ospf6_header *) sendbuf;
1416 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1417 sizeof (struct ospf6_header));
1418
1419 /* if this is initial one, initialize sequence number for DbDesc */
1420 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1421 {
1422 struct timeval tv;
1423 if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
1424 tv.tv_sec = 1;
1425 on->dbdesc_seqnum = tv.tv_sec;
1426 }
1427
1428 dbdesc->options[0] = on->ospf6_if->area->options[0];
1429 dbdesc->options[1] = on->ospf6_if->area->options[1];
1430 dbdesc->options[2] = on->ospf6_if->area->options[2];
1431 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1432 dbdesc->bits = on->dbdesc_bits;
1433 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1434
1435 /* if this is not initial one, set LSA headers in dbdesc */
1436 p = (char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
1437 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1438 {
1439 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1440 lsa = ospf6_lsdb_next (lsa))
1441 {
1442 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1443
1444 /* MTU check */
1445 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1446 on->ospf6_if->ifmtu)
1447 {
1448 ospf6_lsa_unlock (lsa);
1449 break;
1450 }
1451 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1452 p += sizeof (struct ospf6_lsa_header);
1453 }
1454 }
1455
1456 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1457 oh->length = htons (p - sendbuf);
1458
1459 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1460 on->ospf6_if, oh);
1461 return 0;
1462}
1463
1464int
1465ospf6_dbdesc_send_newone (struct thread *thread)
1466{
1467 struct ospf6_neighbor *on;
1468 struct ospf6_lsa *lsa;
1469 unsigned int size = 0;
1470
1471 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1472 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1473 zlog_info ("Remove entire dbdesc_list of %s: sending newone", on->name);
1474 ospf6_lsdb_remove_all (on->dbdesc_list);
1475
1476 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1477 so that ospf6_send_dbdesc () can send those LSAs */
1478 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1479 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1480 lsa = ospf6_lsdb_next (lsa))
1481 {
1482 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1483 {
1484 ospf6_lsa_unlock (lsa);
1485 break;
1486 }
1487
1488 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1489 zlog_info ("Move %s from summary_list to dbdesc_list of %s",
1490 lsa->name, on->name);
1491 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1492 ospf6_lsdb_remove (lsa, on->summary_list);
1493 size += sizeof (struct ospf6_lsa_header);
1494 }
1495
1496 if (on->summary_list->count == 0)
1497 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1498
1499 /* If slave, More bit check must be done here */
1500 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1501 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1502 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1503 thread_add_event (master, exchange_done, on, 0);
1504
1505 thread_execute (master, ospf6_dbdesc_send, on, 0);
1506 return 0;
1507}
1508
1509int
1510ospf6_lsreq_send (struct thread *thread)
1511{
1512 struct ospf6_neighbor *on;
1513 struct ospf6_header *oh;
1514 struct ospf6_lsreq_entry *e;
1515 char *p;
1516 struct ospf6_lsa *lsa;
1517
1518 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1519 on->thread_send_lsreq = (struct thread *) NULL;
1520
1521 /* LSReq will be sent only in ExStart or Loading */
1522 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1523 on->state != OSPF6_NEIGHBOR_LOADING)
1524 {
1525 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
1526 zlog_info ("Quit to send LSReq to neighbor %s state %s",
1527 on->name, ospf6_neighbor_state_str[on->state]);
1528 return 0;
1529 }
1530
1531 /* schedule loading_done if request list is empty */
1532 if (on->request_list->count == 0)
1533 {
1534 thread_add_event (master, loading_done, on, 0);
1535 return 0;
1536 }
1537
1538 /* set next thread */
1539 on->thread_send_lsreq =
1540 thread_add_timer (master, ospf6_lsreq_send, on,
1541 on->ospf6_if->rxmt_interval);
1542
hasso3b4cd3a2004-05-18 19:28:32 +00001543 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001544 oh = (struct ospf6_header *) sendbuf;
1545
1546 /* set Request entries in lsreq */
1547 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1548 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1549 lsa = ospf6_lsdb_next (lsa))
1550 {
1551 /* MTU check */
1552 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
1553 {
1554 ospf6_lsa_unlock (lsa);
1555 break;
1556 }
1557
1558 e = (struct ospf6_lsreq_entry *) p;
1559 e->type = lsa->header->type;
1560 e->id = lsa->header->id;
1561 e->adv_router = lsa->header->adv_router;
1562 p += sizeof (struct ospf6_lsreq_entry);
1563 }
1564
1565 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1566 oh->length = htons (p - sendbuf);
1567
1568 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1569 on->ospf6_if, oh);
1570 return 0;
1571}
1572
1573int
1574ospf6_lsupdate_send_neighbor (struct thread *thread)
1575{
1576 struct ospf6_neighbor *on;
1577 struct ospf6_header *oh;
1578 struct ospf6_lsupdate *lsupdate;
1579 char *p;
1580 int num;
1581 struct ospf6_lsa *lsa;
1582
1583 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1584 on->thread_send_lsupdate = (struct thread *) NULL;
1585
1586 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1587 {
1588 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1589 zlog_info ("Quit to send LSUpdate to neighbor %s state %s",
1590 on->name, ospf6_neighbor_state_str[on->state]);
1591 return 0;
1592 }
1593
1594 /* if we have nothing to send, return */
1595 if (on->lsupdate_list->count == 0 &&
1596 on->retrans_list->count == 0)
1597 return 0;
1598
1599 if (IS_OSPF6_DEBUG_LSA (SEND))
1600 zlog_info ("LSA Send to %s", on->name);
1601
hasso3b4cd3a2004-05-18 19:28:32 +00001602 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001603 oh = (struct ospf6_header *) sendbuf;
1604 lsupdate = (struct ospf6_lsupdate *)
1605 ((caddr_t) oh + sizeof (struct ospf6_header));
1606
1607 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1608 num = 0;
1609
1610 /* lsupdate_list lists those LSA which doesn't need to be
1611 retransmitted. remove those from the list */
1612 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1613 lsa = ospf6_lsdb_next (lsa))
1614 {
1615 /* MTU check */
1616 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1617 {
1618 ospf6_lsa_unlock (lsa);
1619 break;
1620 }
1621
1622 if (IS_OSPF6_DEBUG_LSA (SEND))
1623 ospf6_lsa_header_print (lsa);
1624
1625 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1626 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1627 p += OSPF6_LSA_SIZE (lsa->header);
1628 num++;
1629
1630 assert (lsa->lock == 2);
1631 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1632 }
1633
1634 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1635 lsa = ospf6_lsdb_next (lsa))
1636 {
1637 /* MTU check */
1638 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1639 {
1640 ospf6_lsa_unlock (lsa);
1641 break;
1642 }
1643
1644 if (IS_OSPF6_DEBUG_LSA (SEND))
1645 ospf6_lsa_header_print (lsa);
1646
1647 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1648 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1649 p += OSPF6_LSA_SIZE (lsa->header);
1650 num++;
1651 }
1652
1653 lsupdate->lsa_number = htonl (num);
1654
1655 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1656 oh->length = htons (p - sendbuf);
1657
1658 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1659 on->ospf6_if, oh);
1660
1661 if (on->lsupdate_list->count != 0 ||
1662 on->retrans_list->count != 0)
1663 {
1664 if (on->lsupdate_list->count != 0)
1665 on->thread_send_lsupdate =
1666 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1667 else
1668 on->thread_send_lsupdate =
1669 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1670 on->ospf6_if->rxmt_interval);
1671 }
1672
1673 return 0;
1674}
1675
1676int
1677ospf6_lsupdate_send_interface (struct thread *thread)
1678{
1679 struct ospf6_interface *oi;
1680 struct ospf6_header *oh;
1681 struct ospf6_lsupdate *lsupdate;
1682 char *p;
1683 int num;
1684 struct ospf6_lsa *lsa;
1685
1686 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1687 oi->thread_send_lsupdate = (struct thread *) NULL;
1688
1689 if (oi->state <= OSPF6_INTERFACE_WAITING)
1690 {
1691 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1692 zlog_info ("Quit to send LSUpdate to interface %s state %s",
1693 oi->interface->name, ospf6_interface_state_str[oi->state]);
1694 return 0;
1695 }
1696
1697 /* if we have nothing to send, return */
1698 if (oi->lsupdate_list->count == 0)
1699 return 0;
1700
1701 if (IS_OSPF6_DEBUG_LSA (SEND))
1702 zlog_info ("LSA Send to %s", oi->interface->name);
1703
hasso3b4cd3a2004-05-18 19:28:32 +00001704 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001705 oh = (struct ospf6_header *) sendbuf;
1706 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1707 sizeof (struct ospf6_header));
1708
1709 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1710 num = 0;
1711
1712 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1713 lsa = ospf6_lsdb_next (lsa))
1714 {
1715 /* MTU check */
1716 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > oi->ifmtu)
1717 {
1718 ospf6_lsa_unlock (lsa);
1719 break;
1720 }
1721
1722 if (IS_OSPF6_DEBUG_LSA (SEND))
1723 ospf6_lsa_header_print (lsa);
1724
1725 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1726 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1727 p += OSPF6_LSA_SIZE (lsa->header);
1728 num++;
1729
1730 assert (lsa->lock == 2);
1731 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1732 }
1733
1734 lsupdate->lsa_number = htonl (num);
1735
1736 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1737 oh->length = htons (p - sendbuf);
1738
1739 if (oi->state == OSPF6_INTERFACE_DR ||
1740 oi->state == OSPF6_INTERFACE_BDR)
1741 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1742 else
1743 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1744
1745 if (oi->lsupdate_list->count > 0)
1746 {
1747 oi->thread_send_lsupdate =
1748 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1749 }
1750
1751 return 0;
1752}
1753
1754int
1755ospf6_lsack_send_neighbor (struct thread *thread)
1756{
1757 struct ospf6_neighbor *on;
1758 struct ospf6_header *oh;
1759 char *p;
1760 struct ospf6_lsa *lsa;
1761
1762 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1763 on->thread_send_lsack = (struct thread *) NULL;
1764
1765 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1766 {
1767 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1768 zlog_info ("Quit to send LSAck to neighbor %s state %s",
1769 on->name, ospf6_neighbor_state_str[on->state]);
1770 return 0;
1771 }
1772
1773 /* if we have nothing to send, return */
1774 if (on->lsack_list->count == 0)
1775 return 0;
1776
hasso3b4cd3a2004-05-18 19:28:32 +00001777 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001778 oh = (struct ospf6_header *) sendbuf;
1779
1780 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1781
1782 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1783 lsa = ospf6_lsdb_next (lsa))
1784 {
1785 /* MTU check */
1786 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1787 {
1788 /* if we run out of packet size/space here,
1789 better to try again soon. */
1790 THREAD_OFF (on->thread_send_lsack);
1791 on->thread_send_lsack =
1792 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1793
1794 ospf6_lsa_unlock (lsa);
1795 break;
1796 }
1797
1798 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1799 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1800 p += sizeof (struct ospf6_lsa_header);
1801
1802 assert (lsa->lock == 2);
1803 ospf6_lsdb_remove (lsa, on->lsack_list);
1804 }
1805
1806 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1807 oh->length = htons (p - sendbuf);
1808
1809 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1810 on->ospf6_if, oh);
1811 return 0;
1812}
1813
1814int
1815ospf6_lsack_send_interface (struct thread *thread)
1816{
1817 struct ospf6_interface *oi;
1818 struct ospf6_header *oh;
1819 char *p;
1820 struct ospf6_lsa *lsa;
1821
1822 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1823 oi->thread_send_lsack = (struct thread *) NULL;
1824
1825 if (oi->state <= OSPF6_INTERFACE_WAITING)
1826 {
1827 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1828 zlog_info ("Quit to send LSAck to interface %s state %s",
1829 oi->interface->name, ospf6_interface_state_str[oi->state]);
1830 return 0;
1831 }
1832
1833 /* if we have nothing to send, return */
1834 if (oi->lsack_list->count == 0)
1835 return 0;
1836
hasso3b4cd3a2004-05-18 19:28:32 +00001837 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001838 oh = (struct ospf6_header *) sendbuf;
1839
1840 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1841
1842 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1843 lsa = ospf6_lsdb_next (lsa))
1844 {
1845 /* MTU check */
1846 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
1847 {
1848 /* if we run out of packet size/space here,
1849 better to try again soon. */
1850 THREAD_OFF (oi->thread_send_lsack);
1851 oi->thread_send_lsack =
1852 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1853
1854 ospf6_lsa_unlock (lsa);
1855 break;
1856 }
1857
1858 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1859 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1860 p += sizeof (struct ospf6_lsa_header);
1861
1862 assert (lsa->lock == 2);
1863 ospf6_lsdb_remove (lsa, oi->lsack_list);
1864 }
1865
1866 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1867 oh->length = htons (p - sendbuf);
1868
1869 if (oi->state == OSPF6_INTERFACE_DR ||
1870 oi->state == OSPF6_INTERFACE_BDR)
1871 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1872 else
1873 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1874
1875 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1876 {
1877 oi->thread_send_lsack =
1878 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1879 }
paul718e3742002-12-13 20:15:29 +00001880
1881 return 0;
1882}
1883
1884
hasso508e53e2004-05-18 18:57:06 +00001885/* Commands */
1886DEFUN (debug_ospf6_message,
1887 debug_ospf6_message_cmd,
1888 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1889 DEBUG_STR
1890 OSPF6_STR
1891 "Debug OSPFv3 message\n"
1892 "Debug Unknown message\n"
1893 "Debug Hello message\n"
1894 "Debug Database Description message\n"
1895 "Debug Link State Request message\n"
1896 "Debug Link State Update message\n"
1897 "Debug Link State Acknowledgement message\n"
1898 "Debug All message\n"
1899 )
paul718e3742002-12-13 20:15:29 +00001900{
hasso508e53e2004-05-18 18:57:06 +00001901 unsigned char level = 0;
1902 int type = 0;
paul718e3742002-12-13 20:15:29 +00001903 int i;
1904
hasso508e53e2004-05-18 18:57:06 +00001905 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001906
hasso508e53e2004-05-18 18:57:06 +00001907 /* check type */
1908 if (! strncmp (argv[0], "u", 1))
1909 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1910 else if (! strncmp (argv[0], "h", 1))
1911 type = OSPF6_MESSAGE_TYPE_HELLO;
1912 else if (! strncmp (argv[0], "d", 1))
1913 type = OSPF6_MESSAGE_TYPE_DBDESC;
1914 else if (! strncmp (argv[0], "lsr", 3))
1915 type = OSPF6_MESSAGE_TYPE_LSREQ;
1916 else if (! strncmp (argv[0], "lsu", 3))
1917 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1918 else if (! strncmp (argv[0], "lsa", 3))
1919 type = OSPF6_MESSAGE_TYPE_LSACK;
1920 else if (! strncmp (argv[0], "a", 1))
1921 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001922
hasso508e53e2004-05-18 18:57:06 +00001923 if (argc == 1)
1924 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1925 else if (! strncmp (argv[1], "s", 1))
1926 level = OSPF6_DEBUG_MESSAGE_SEND;
1927 else if (! strncmp (argv[1], "r", 1))
1928 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001929
hasso508e53e2004-05-18 18:57:06 +00001930 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001931 {
hasso508e53e2004-05-18 18:57:06 +00001932 for (i = 0; i < 6; i++)
1933 OSPF6_DEBUG_MESSAGE_ON (i, level);
1934 }
1935 else
1936 OSPF6_DEBUG_MESSAGE_ON (type, level);
1937
1938 return CMD_SUCCESS;
1939}
1940
1941ALIAS (debug_ospf6_message,
1942 debug_ospf6_message_sendrecv_cmd,
1943 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1944 DEBUG_STR
1945 OSPF6_STR
1946 "Debug OSPFv3 message\n"
1947 "Debug Unknown message\n"
1948 "Debug Hello message\n"
1949 "Debug Database Description message\n"
1950 "Debug Link State Request message\n"
1951 "Debug Link State Update message\n"
1952 "Debug Link State Acknowledgement message\n"
1953 "Debug All message\n"
1954 "Debug only sending message\n"
1955 "Debug only receiving message\n"
1956 );
1957
1958
1959DEFUN (no_debug_ospf6_message,
1960 no_debug_ospf6_message_cmd,
1961 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1962 NO_STR
1963 DEBUG_STR
1964 OSPF6_STR
1965 "Debug OSPFv3 message\n"
1966 "Debug Unknown message\n"
1967 "Debug Hello message\n"
1968 "Debug Database Description message\n"
1969 "Debug Link State Request message\n"
1970 "Debug Link State Update message\n"
1971 "Debug Link State Acknowledgement message\n"
1972 "Debug All message\n"
1973 )
1974{
1975 unsigned char level = 0;
1976 int type = 0;
1977 int i;
1978
1979 assert (argc > 0);
1980
1981 /* check type */
1982 if (! strncmp (argv[0], "u", 1))
1983 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1984 else if (! strncmp (argv[0], "h", 1))
1985 type = OSPF6_MESSAGE_TYPE_HELLO;
1986 else if (! strncmp (argv[0], "d", 1))
1987 type = OSPF6_MESSAGE_TYPE_DBDESC;
1988 else if (! strncmp (argv[0], "lsr", 3))
1989 type = OSPF6_MESSAGE_TYPE_LSREQ;
1990 else if (! strncmp (argv[0], "lsu", 3))
1991 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1992 else if (! strncmp (argv[0], "lsa", 3))
1993 type = OSPF6_MESSAGE_TYPE_LSACK;
1994 else if (! strncmp (argv[0], "a", 1))
1995 type = OSPF6_MESSAGE_TYPE_ALL;
1996
1997 if (argc == 1)
1998 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1999 else if (! strncmp (argv[1], "s", 1))
2000 level = OSPF6_DEBUG_MESSAGE_SEND;
2001 else if (! strncmp (argv[1], "r", 1))
2002 level = OSPF6_DEBUG_MESSAGE_RECV;
2003
2004 if (type == OSPF6_MESSAGE_TYPE_ALL)
2005 {
2006 for (i = 0; i < 6; i++)
2007 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2008 }
2009 else
2010 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2011
2012 return CMD_SUCCESS;
2013}
2014
2015ALIAS (no_debug_ospf6_message,
2016 no_debug_ospf6_message_sendrecv_cmd,
2017 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2018 NO_STR
2019 DEBUG_STR
2020 OSPF6_STR
2021 "Debug OSPFv3 message\n"
2022 "Debug Unknown message\n"
2023 "Debug Hello message\n"
2024 "Debug Database Description message\n"
2025 "Debug Link State Request message\n"
2026 "Debug Link State Update message\n"
2027 "Debug Link State Acknowledgement message\n"
2028 "Debug All message\n"
2029 "Debug only sending message\n"
2030 "Debug only receiving message\n"
2031 );
2032
2033int
2034config_write_ospf6_debug_message (struct vty *vty)
2035{
2036 char *type_str[] = {"unknown", "hello", "dbdesc",
2037 "lsreq", "lsupdate", "lsack"};
2038 unsigned char s = 0, r = 0;
2039 int i;
2040
2041 for (i = 0; i < 6; i++)
2042 {
2043 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2044 s |= 1 << i;
2045 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2046 r |= 1 << i;
2047 }
2048
2049 if (s == 0x3f && r == 0x3f)
2050 {
2051 vty_out (vty, "debug ospf6 message all%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002052 return 0;
2053 }
2054
hasso508e53e2004-05-18 18:57:06 +00002055 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002056 {
hasso508e53e2004-05-18 18:57:06 +00002057 vty_out (vty, "debug ospf6 message all send%s", VTY_NEWLINE);
2058 return 0;
2059 }
2060 else if (s == 0 && r == 0x3f)
2061 {
2062 vty_out (vty, "debug ospf6 message all recv%s", VTY_NEWLINE);
2063 return 0;
paul718e3742002-12-13 20:15:29 +00002064 }
2065
hasso508e53e2004-05-18 18:57:06 +00002066 /* Unknown message is logged by default */
2067 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2068 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2069 vty_out (vty, "no debug ospf6 message unknown%s", VTY_NEWLINE);
2070 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
2071 vty_out (vty, "no debug ospf6 message unknown send%s", VTY_NEWLINE);
2072 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2073 vty_out (vty, "no debug ospf6 message unknown recv%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002074
hasso508e53e2004-05-18 18:57:06 +00002075 for (i = 1; i < 6; i++)
2076 {
2077 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2078 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2079 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VTY_NEWLINE);
2080 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2081 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
2082 VTY_NEWLINE);
2083 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2084 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
2085 VTY_NEWLINE);
2086 }
paul718e3742002-12-13 20:15:29 +00002087
2088 return 0;
2089}
2090
paul718e3742002-12-13 20:15:29 +00002091void
hasso508e53e2004-05-18 18:57:06 +00002092install_element_ospf6_debug_message ()
paul718e3742002-12-13 20:15:29 +00002093{
hasso508e53e2004-05-18 18:57:06 +00002094 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2095 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2096 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2097 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2098 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2099 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2100 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2101 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002102}
2103
paul718e3742002-12-13 20:15:29 +00002104