blob: 21b799e00f116135e15acc93efe1bb67cec1df6f [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
24#include "log.h"
25#include "vty.h"
26#include "command.h"
27#include "thread.h"
28#include "linklist.h"
29
paul718e3742002-12-13 20:15:29 +000030#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
34#include "ospf6_network.h"
35#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000036
hasso508e53e2004-05-18 18:57:06 +000037#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_neighbor.h"
40#include "ospf6_interface.h"
41
42#include "ospf6_flood.h"
43
44unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
45char *ospf6_message_type_str[] =
46 { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
47
48/* print functions */
49
50static void
51ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000052{
hasso508e53e2004-05-18 18:57:06 +000053 char router_id[16], area_id[16];
54 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
55 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000056
hasso508e53e2004-05-18 18:57:06 +000057 zlog_info (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
58 oh->version, oh->type, ntohs (oh->length), router_id);
59 zlog_info (" Area-ID:%s Cksum:%hx Instance-ID:%d",
60 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +000061}
paul718e3742002-12-13 20:15:29 +000062
63void
hasso508e53e2004-05-18 18:57:06 +000064ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000065{
paul718e3742002-12-13 20:15:29 +000066 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +000067 char options[16];
68 char drouter[16], bdrouter[16], neighbor[16];
69 char *p;
paul718e3742002-12-13 20:15:29 +000070
hasso508e53e2004-05-18 18:57:06 +000071 ospf6_header_print (oh);
72 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +000073
hasso508e53e2004-05-18 18:57:06 +000074 hello = (struct ospf6_hello *)
75 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +000076
hasso508e53e2004-05-18 18:57:06 +000077 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
78 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
79 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +000080
hasso508e53e2004-05-18 18:57:06 +000081 zlog_info (" I/F-Id:%ld Priority:%d Option:%s",
82 (u_long) ntohl (hello->interface_id), hello->priority, options);
83 zlog_info (" HelloInterval:%hu DeadInterval:%hu",
84 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
85 zlog_info (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +000086
hasso508e53e2004-05-18 18:57:06 +000087 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
88 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
89 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +000090 {
hasso508e53e2004-05-18 18:57:06 +000091 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
paul718e3742002-12-13 20:15:29 +000092 zlog_info (" Neighbor: %s", neighbor);
93 }
hasso508e53e2004-05-18 18:57:06 +000094
95 if (p != OSPF6_MESSAGE_END (oh))
96 zlog_info ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +000097}
98
hasso508e53e2004-05-18 18:57:06 +000099void
100ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000101{
paul718e3742002-12-13 20:15:29 +0000102 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000103 char options[16];
104 char *p;
paul718e3742002-12-13 20:15:29 +0000105
hasso508e53e2004-05-18 18:57:06 +0000106 ospf6_header_print (oh);
107 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000108
hasso508e53e2004-05-18 18:57:06 +0000109 dbdesc = (struct ospf6_dbdesc *)
110 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000111
hasso508e53e2004-05-18 18:57:06 +0000112 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000113
hasso508e53e2004-05-18 18:57:06 +0000114 zlog_info (" MBZ: %#x Option: %s IfMTU: %hu",
115 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
116 zlog_info (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
117 dbdesc->reserved2,
118 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
119 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
120 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
121 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000122
hasso508e53e2004-05-18 18:57:06 +0000123 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
124 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
125 p += sizeof (struct ospf6_lsa_header))
126 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
127
128 if (p != OSPF6_MESSAGE_END (oh))
129 zlog_info ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000130}
131
hasso508e53e2004-05-18 18:57:06 +0000132void
133ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000134{
hasso508e53e2004-05-18 18:57:06 +0000135 char id[16], adv_router[16];
136 char *p;
paul718e3742002-12-13 20:15:29 +0000137
hasso508e53e2004-05-18 18:57:06 +0000138 ospf6_header_print (oh);
139 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000140
hasso508e53e2004-05-18 18:57:06 +0000141 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
142 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
143 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000144 {
hasso508e53e2004-05-18 18:57:06 +0000145 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
146 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
147 inet_ntop (AF_INET, &e->id, id, sizeof (id));
148 zlog_info (" [%s Id:%s Adv:%s]",
149 OSPF6_LSTYPE_NAME (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000150 }
hasso508e53e2004-05-18 18:57:06 +0000151
152 if (p != OSPF6_MESSAGE_END (oh))
153 zlog_info ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000154}
155
hasso508e53e2004-05-18 18:57:06 +0000156void
157ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000158{
paul718e3742002-12-13 20:15:29 +0000159 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000160 u_long num;
161 char *p;
paul718e3742002-12-13 20:15:29 +0000162
hasso508e53e2004-05-18 18:57:06 +0000163 ospf6_header_print (oh);
164 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000165
hasso508e53e2004-05-18 18:57:06 +0000166 lsupdate = (struct ospf6_lsupdate *)
167 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000168
hasso508e53e2004-05-18 18:57:06 +0000169 num = ntohl (lsupdate->lsa_number);
170 zlog_info (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000171
hasso508e53e2004-05-18 18:57:06 +0000172 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
173 p < OSPF6_MESSAGE_END (oh) &&
174 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
175 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000176 {
hasso508e53e2004-05-18 18:57:06 +0000177 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
178 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
179 {
180 zlog_info (" Malformed LSA length, quit printing");
181 break;
182 }
183 }
paul718e3742002-12-13 20:15:29 +0000184
hasso508e53e2004-05-18 18:57:06 +0000185 if (p != OSPF6_MESSAGE_END (oh))
186 {
187 char buf[32];
188
189 int num = 0;
190 memset (buf, 0, sizeof (buf));
191
192 zlog_info (" Trailing garbage exists");
193 while (p < OSPF6_MESSAGE_END (oh))
194 {
195 snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
196 num++;
197 if (num == 8)
198 {
199 zlog_info (" %s", buf);
200 memset (buf, 0, sizeof (buf));
201 num = 0;
202 }
203 }
204 if (num)
205 zlog_info (" %s", buf);
paul718e3742002-12-13 20:15:29 +0000206 }
207}
208
hasso508e53e2004-05-18 18:57:06 +0000209void
210ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000211{
hasso508e53e2004-05-18 18:57:06 +0000212 char *p;
paul718e3742002-12-13 20:15:29 +0000213
hasso508e53e2004-05-18 18:57:06 +0000214 ospf6_header_print (oh);
215 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000216
hasso508e53e2004-05-18 18:57:06 +0000217 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
218 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
219 p += sizeof (struct ospf6_lsa_header))
220 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
221
222 if (p != OSPF6_MESSAGE_END (oh))
223 zlog_info ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000224}
225
hasso508e53e2004-05-18 18:57:06 +0000226/* Receive function */
227#define MSG_OK 0
228#define MSG_NG 1
229static int
230ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst,
231 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000232{
paul718e3742002-12-13 20:15:29 +0000233 u_char type;
hasso508e53e2004-05-18 18:57:06 +0000234 type = OSPF6_MESSAGE_TYPE_CANONICAL (oh->type);
paul718e3742002-12-13 20:15:29 +0000235
hasso508e53e2004-05-18 18:57:06 +0000236 /* version check */
237 if (oh->version != OSPFV3_VERSION)
paul718e3742002-12-13 20:15:29 +0000238 {
hasso508e53e2004-05-18 18:57:06 +0000239 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
240 zlog_info ("Message with unknown version");
241 return MSG_NG;
paul718e3742002-12-13 20:15:29 +0000242 }
243
hasso508e53e2004-05-18 18:57:06 +0000244 /* Area-ID check */
245 if (oh->area_id != oi->area->area_id)
246 {
247 if (oh->area_id == 0)
248 {
249 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
250 zlog_info ("Message may be via Virtual Link: not supported");
251 return MSG_NG;
252 }
253
254 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
255 zlog_info ("Area-ID mismatch");
256 return MSG_NG;
257 }
258
259 /* Instance-ID check */
260 if (oh->instance_id != oi->instance_id)
261 {
262 if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
263 zlog_info ("Instance-ID mismatch");
264 return MSG_NG;
265 }
266
267 /* Router-ID check */
268 if (oh->router_id == oi->area->ospf6->router_id)
269 zlog_warn ("Detect duplicate Router-ID");
270
271 return MSG_OK;
272}
273
274void
275ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
276 struct ospf6_interface *oi, struct ospf6_header *oh)
277{
278 struct ospf6_hello *hello;
279 struct ospf6_neighbor *on;
280 char *p;
281 int twoway = 0;
282 int neighborchange = 0;
283 int backupseen = 0;
284
285 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
286 return;
287
288 hello = (struct ospf6_hello *)
289 ((caddr_t) oh + sizeof (struct ospf6_header));
290
paul718e3742002-12-13 20:15:29 +0000291 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000292 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000293 {
hasso508e53e2004-05-18 18:57:06 +0000294 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
295 zlog_info ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000296 return;
297 }
298
299 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000300 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000301 {
hasso508e53e2004-05-18 18:57:06 +0000302 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
303 zlog_info ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000304 return;
305 }
306
hasso508e53e2004-05-18 18:57:06 +0000307 /* E-bit check */
308 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
309 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000310 {
hasso508e53e2004-05-18 18:57:06 +0000311 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
312 zlog_info ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000313 return;
314 }
315
hasso508e53e2004-05-18 18:57:06 +0000316 /* Find neighbor, create if not exist */
317 on = ospf6_neighbor_lookup (oh->router_id, oi);
318 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000319 {
hasso508e53e2004-05-18 18:57:06 +0000320 on = ospf6_neighbor_create (oh->router_id, oi);
321 on->prev_drouter = on->drouter = hello->drouter;
322 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
323 on->priority = hello->priority;
324 on->ifindex = ntohl (hello->interface_id);
325 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
paul718e3742002-12-13 20:15:29 +0000326 }
327
328 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000329 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
330 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
331 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000332 {
hasso508e53e2004-05-18 18:57:06 +0000333 u_int32_t *router_id = (u_int32_t *) p;
334
335 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000336 twoway++;
paul718e3742002-12-13 20:15:29 +0000337 }
338
hasso508e53e2004-05-18 18:57:06 +0000339 if (p != OSPF6_MESSAGE_END (oh))
340 {
341 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
342 zlog_info ("Trailing garbage ignored");
343 }
344
345 /* RouterPriority check */
346 if (on->priority != hello->priority)
347 {
348 on->priority = hello->priority;
349 neighborchange++;
350 }
351
352 /* DR check */
353 if (on->drouter != hello->drouter)
354 {
355 on->prev_drouter = on->drouter;
356 on->drouter = hello->drouter;
357 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
358 neighborchange++;
359 }
360
361 /* BDR check */
362 if (on->bdrouter != hello->bdrouter)
363 {
364 on->prev_bdrouter = on->bdrouter;
365 on->bdrouter = hello->bdrouter;
366 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
367 neighborchange++;
368 }
paul718e3742002-12-13 20:15:29 +0000369
370 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000371 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000372 {
hasso508e53e2004-05-18 18:57:06 +0000373 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000374 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000375 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000376 backupseen++;
377 }
378
hasso508e53e2004-05-18 18:57:06 +0000379 /* Execute neighbor events */
380 thread_execute (master, hello_received, on, 0);
381 if (twoway)
382 thread_execute (master, twoway_received, on, 0);
383 else
384 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000385
hasso508e53e2004-05-18 18:57:06 +0000386 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000387 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000388 thread_add_event (master, backup_seen, oi, 0);
389 if (neighborchange)
390 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000391}
392
hasso508e53e2004-05-18 18:57:06 +0000393static void
394ospf6_dbdesc_recv_master (struct ospf6_header *oh,
395 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000396{
paul718e3742002-12-13 20:15:29 +0000397 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000398 char *p;
paul718e3742002-12-13 20:15:29 +0000399
hasso508e53e2004-05-18 18:57:06 +0000400 dbdesc = (struct ospf6_dbdesc *)
401 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000402
hasso508e53e2004-05-18 18:57:06 +0000403 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000404 {
hasso508e53e2004-05-18 18:57:06 +0000405 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
406 zlog_info ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000407 return;
408 }
409
hasso508e53e2004-05-18 18:57:06 +0000410 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000411 {
hasso508e53e2004-05-18 18:57:06 +0000412 case OSPF6_NEIGHBOR_TWOWAY:
413 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
414 zlog_info ("Neighbor state is 2-Way, ignore");
415 return;
416
417 case OSPF6_NEIGHBOR_INIT:
418 thread_execute (master, twoway_received, on, 0);
419 if (on->state != OSPF6_NEIGHBOR_EXSTART)
420 {
421 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
422 zlog_info ("Neighbor state is not ExStart, ignore");
423 return;
424 }
425 /* else fall through to ExStart */
426
427 case OSPF6_NEIGHBOR_EXSTART:
428 /* if neighbor obeys us as our slave, schedule negotiation_done
429 and process LSA Headers. Otherwise, ignore this message */
430 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
431 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
432 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
433 {
434 /* execute NegotiationDone */
435 thread_execute (master, negotiation_done, on, 0);
436
437 /* Record neighbor options */
438 memcpy (on->options, dbdesc->options, sizeof (on->options));
439 }
440 else
441 {
442 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
443 zlog_info ("Negotiation failed");
444 return;
445 }
446 /* fall through to exchange */
447
448 case OSPF6_NEIGHBOR_EXCHANGE:
449 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
450 {
451 /* Duplicated DatabaseDescription is dropped by master */
452 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
453 zlog_info ("Duplicated dbdesc discarded by Master, ignore");
454 return;
455 }
456
457 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
458 {
459 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
460 zlog_info ("Master/Slave bit mismatch");
461 thread_add_event (master, seqnumber_mismatch, on, 0);
462 return;
463 }
464
465 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
466 {
467 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
468 zlog_info ("Initialize bit mismatch");
469 thread_add_event (master, seqnumber_mismatch, on, 0);
470 return;
471 }
472
473 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
474 {
475 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
476 zlog_info ("Option field mismatch");
477 thread_add_event (master, seqnumber_mismatch, on, 0);
478 return;
479 }
480
481 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
482 {
483 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
484 zlog_info ("Sequence number mismatch (%#lx expected)",
485 (u_long) on->dbdesc_seqnum);
486 thread_add_event (master, seqnumber_mismatch, on, 0);
487 return;
488 }
489 break;
490
491 case OSPF6_NEIGHBOR_LOADING:
492 case OSPF6_NEIGHBOR_FULL:
493 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
494 {
495 /* Duplicated DatabaseDescription is dropped by master */
496 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
497 zlog_info ("Duplicated dbdesc discarded by Master, ignore");
498 return;
499 }
500
501 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
502 zlog_info ("Not duplicate dbdesc in state %s",
503 ospf6_neighbor_state_str[on->state]);
504 thread_add_event (master, seqnumber_mismatch, on, 0);
505 return;
506
507 default:
508 assert (0);
509 break;
510 }
511
512 /* Process LSA headers */
513 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
514 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
515 p += sizeof (struct ospf6_lsa_header))
516 {
517 struct ospf6_lsa *his, *mine;
518 struct ospf6_lsdb *lsdb = NULL;
519
520 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
521 his->scope = ospf6_get_lsa_scope (his->header->type, on);
522 lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
523 if (lsdb == NULL)
524 {
525 zlog_warn ("Can't decide scoped LSDB");
526 ospf6_lsa_delete (his);
527 thread_add_event (master, seqnumber_mismatch, on, 0);
528 return;
529 }
530
531 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
532 ospf6_area_is_stub (on->ospf6_if->area))
533 {
534 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
535 zlog_info ("E-bit mismatch with LSA Headers");
536 ospf6_lsa_delete (his);
537 thread_add_event (master, seqnumber_mismatch, on, 0);
538 return;
539 }
540
541 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
542 his->header->adv_router, lsdb);
543 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
544 {
545 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
546 zlog_info ("Add %s's request-list: %s", on->name, his->name);
547 ospf6_lsdb_add (his, on->request_list);
548 }
549 else
550 ospf6_lsa_delete (his);
551 }
552
553 if (p != OSPF6_MESSAGE_END (oh))
554 {
555 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
556 zlog_info ("Trailing garbage ignored");
557 }
558
559 /* Increment sequence number */
560 on->dbdesc_seqnum ++;
561
562 /* schedule send lsreq */
563 if (on->thread_send_lsreq == NULL)
564 on->thread_send_lsreq =
565 thread_add_event (master, ospf6_lsreq_send, on, 0);
566
567 THREAD_OFF (on->thread_send_dbdesc);
568
569 /* More bit check */
570 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
571 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
572 thread_add_event (master, exchange_done, on, 0);
573 else
574 on->thread_send_dbdesc =
575 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
576
577 /* save last received dbdesc */
578 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
579}
580
581static void
582ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
583 struct ospf6_neighbor *on)
584{
585 struct ospf6_dbdesc *dbdesc;
586 char *p;
587
588 dbdesc = (struct ospf6_dbdesc *)
589 ((caddr_t) oh + sizeof (struct ospf6_header));
590
591 if (on->state < OSPF6_NEIGHBOR_INIT)
592 {
593 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
594 zlog_info ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000595 return;
596 }
597
hasso508e53e2004-05-18 18:57:06 +0000598 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000599 {
hasso508e53e2004-05-18 18:57:06 +0000600 case OSPF6_NEIGHBOR_TWOWAY:
601 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
602 zlog_info ("Neighbor state is 2-Way, ignore");
603 return;
604
605 case OSPF6_NEIGHBOR_INIT:
606 thread_execute (master, twoway_received, on, 0);
607 if (on->state != OSPF6_NEIGHBOR_EXSTART)
608 {
609 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
610 zlog_info ("Neighbor state is not ExStart, ignore");
611 return;
612 }
613 /* else fall through to ExStart */
614
615 case OSPF6_NEIGHBOR_EXSTART:
616 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
617 and process LSA Headers. Otherwise, ignore this message */
618 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
619 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
620 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
621 ntohs (oh->length) == sizeof (struct ospf6_header) +
622 sizeof (struct ospf6_dbdesc))
623 {
624 /* set the master/slave bit to slave */
625 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
626
627 /* set the DD sequence number to one specified by master */
628 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
629
630 /* schedule NegotiationDone */
631 thread_execute (master, negotiation_done, on, 0);
632
633 /* Record neighbor options */
634 memcpy (on->options, dbdesc->options, sizeof (on->options));
635 }
636 else
637 {
638 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
639 zlog_info ("Negotiation failed");
640 return;
641 }
642 break;
643
644 case OSPF6_NEIGHBOR_EXCHANGE:
645 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
646 {
647 /* Duplicated DatabaseDescription causes slave to retransmit */
648 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
649 zlog_info ("Duplicated dbdesc causes retransmit");
650 THREAD_OFF (on->thread_send_dbdesc);
651 on->thread_send_dbdesc =
652 thread_add_event (master, ospf6_dbdesc_send, on, 0);
653 return;
654 }
655
656 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
657 {
658 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
659 zlog_info ("Master/Slave bit mismatch");
660 thread_add_event (master, seqnumber_mismatch, on, 0);
661 return;
662 }
663
664 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
665 {
666 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
667 zlog_info ("Initialize bit mismatch");
668 thread_add_event (master, seqnumber_mismatch, on, 0);
669 return;
670 }
671
672 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
673 {
674 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
675 zlog_info ("Option field mismatch");
676 thread_add_event (master, seqnumber_mismatch, on, 0);
677 return;
678 }
679
680 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
681 {
682 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
683 zlog_info ("Sequence number mismatch (%#lx expected)",
684 (u_long) on->dbdesc_seqnum + 1);
685 thread_add_event (master, seqnumber_mismatch, on, 0);
686 return;
687 }
688 break;
689
690 case OSPF6_NEIGHBOR_LOADING:
691 case OSPF6_NEIGHBOR_FULL:
692 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
693 {
694 /* Duplicated DatabaseDescription causes slave to retransmit */
695 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
696 zlog_info ("Duplicated dbdesc causes retransmit");
697 THREAD_OFF (on->thread_send_dbdesc);
698 on->thread_send_dbdesc =
699 thread_add_event (master, ospf6_dbdesc_send, on, 0);
700 return;
701 }
702
703 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
704 zlog_info ("Not duplicate dbdesc in state %s",
705 ospf6_neighbor_state_str[on->state]);
706 thread_add_event (master, seqnumber_mismatch, on, 0);
707 return;
708
709 default:
710 assert (0);
711 break;
paul718e3742002-12-13 20:15:29 +0000712 }
713
hasso508e53e2004-05-18 18:57:06 +0000714 /* Process LSA headers */
715 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
716 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
717 p += sizeof (struct ospf6_lsa_header))
718 {
719 struct ospf6_lsa *his, *mine;
720 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000721
hasso508e53e2004-05-18 18:57:06 +0000722 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
723 his->scope = ospf6_get_lsa_scope (his->header->type, on);
724 lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
725 if (lsdb == NULL)
726 {
727 zlog_warn ("Can't decide scoped LSDB");
728 ospf6_lsa_delete (his);
729 thread_add_event (master, seqnumber_mismatch, on, 0);
730 return;
731 }
732
733 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
734 ospf6_area_is_stub (on->ospf6_if->area))
735 {
736 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
737 zlog_info ("E-bit mismatch with LSA Headers");
738 ospf6_lsa_delete (his);
739 thread_add_event (master, seqnumber_mismatch, on, 0);
740 return;
741 }
742
743 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
744 his->header->adv_router, lsdb);
745 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
746 {
747 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
748 zlog_info ("Add %s to request-list of %s", his->name, on->name);
749 ospf6_lsdb_add (his, on->request_list);
750 }
751 else
752 ospf6_lsa_delete (his);
753 }
754
755 if (p != OSPF6_MESSAGE_END (oh))
756 {
757 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
758 zlog_info ("Trailing garbage ignored");
759 }
760
761 /* Set sequence number to Master's */
762 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
763
764 /* schedule send lsreq */
765 if (on->thread_send_lsreq == NULL)
766 on->thread_send_lsreq =
767 thread_add_event (master, ospf6_lsreq_send, on, 0);
768
769 THREAD_OFF (on->thread_send_dbdesc);
770 on->thread_send_dbdesc =
771 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
772
773 /* save last received dbdesc */
774 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000775}
776
777void
hasso508e53e2004-05-18 18:57:06 +0000778ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
779 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000780{
hasso508e53e2004-05-18 18:57:06 +0000781 struct ospf6_neighbor *on;
782 struct ospf6_dbdesc *dbdesc;
783
784 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
785 return;
786
787 on = ospf6_neighbor_lookup (oh->router_id, oi);
788 if (on == NULL)
789 {
790 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
791 zlog_info ("Neighbor not found, ignore");
792 return;
793 }
794
795 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
796 {
797 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
798 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
799 return;
800 }
801
802 dbdesc = (struct ospf6_dbdesc *)
803 ((caddr_t) oh + sizeof (struct ospf6_header));
804
805 /* Interface MTU check */
806 if (ntohs (dbdesc->ifmtu) != oi->ifmtu)
807 {
808 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
809 zlog_info ("I/F MTU mismatch");
810 return;
811 }
812
813 if (dbdesc->reserved1 || dbdesc->reserved2)
814 {
815 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
816 zlog_info ("Non-0 reserved field in %s's DbDesc, correct",
817 on->name);
818 dbdesc->reserved1 = 0;
819 dbdesc->reserved2 = 0;
820 }
821
822 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
823 ospf6_dbdesc_recv_master (oh, on);
824 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
825 ospf6_dbdesc_recv_slave (oh, on);
826 else
827 {
828 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
829 zlog_info ("Can't decide which is master, ignore");
830 }
831}
832
833void
834ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
835 struct ospf6_interface *oi, struct ospf6_header *oh)
836{
837 struct ospf6_neighbor *on;
838 char *p;
839 struct ospf6_lsreq_entry *e;
840 void *scope = NULL;
841 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000842 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000843
hasso508e53e2004-05-18 18:57:06 +0000844 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
845 return;
paul718e3742002-12-13 20:15:29 +0000846
hasso508e53e2004-05-18 18:57:06 +0000847 on = ospf6_neighbor_lookup (oh->router_id, oi);
848 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000849 {
hasso508e53e2004-05-18 18:57:06 +0000850 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
851 zlog_info ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000852 return;
853 }
854
hasso508e53e2004-05-18 18:57:06 +0000855 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +0000856 {
hasso508e53e2004-05-18 18:57:06 +0000857 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
858 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +0000859 return;
860 }
861
hasso508e53e2004-05-18 18:57:06 +0000862 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
863 on->state != OSPF6_NEIGHBOR_LOADING &&
864 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000865 {
hasso508e53e2004-05-18 18:57:06 +0000866 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
867 zlog_info ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000868 return;
869 }
870
hasso508e53e2004-05-18 18:57:06 +0000871 /* Process each request */
872 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
873 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
874 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000875 {
hasso508e53e2004-05-18 18:57:06 +0000876 e = (struct ospf6_lsreq_entry *) p;
877 scope = ospf6_get_lsa_scope (e->type, on);
878 lsdb = ospf6_get_scoped_lsdb (e->type, scope);
paul718e3742002-12-13 20:15:29 +0000879
hasso508e53e2004-05-18 18:57:06 +0000880 /* Find database copy */
881 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
882 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000883 {
hasso508e53e2004-05-18 18:57:06 +0000884 char id[16], adv_router[16];
885 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
886 {
887 inet_ntop (AF_INET, &e->id, id, sizeof (id));
888 inet_ntop (AF_INET, &e->adv_router, adv_router,
889 sizeof (adv_router));
890 zlog_info ("Can't find requested [%s Id:%s Adv:%s]",
891 OSPF6_LSTYPE_NAME (e->type), id, adv_router);
892 }
893 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000894 return;
895 }
896
hasso508e53e2004-05-18 18:57:06 +0000897 if (IS_OSPF6_DEBUG_LSA (DATABASE))
898 zlog_info ("Add copy of %s to lsupdate_list of %s",
899 lsa->name, on->name);
900 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000901 }
902
hasso508e53e2004-05-18 18:57:06 +0000903 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000904 {
hasso508e53e2004-05-18 18:57:06 +0000905 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
906 zlog_info ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000907 }
908
hasso508e53e2004-05-18 18:57:06 +0000909 /* schedule send lsupdate */
910 THREAD_OFF (on->thread_send_lsupdate);
911 on->thread_send_lsupdate =
912 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000913}
914
915void
hasso508e53e2004-05-18 18:57:06 +0000916ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
917 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000918{
hasso508e53e2004-05-18 18:57:06 +0000919 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +0000920 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000921 unsigned long num;
922 char *p;
paul718e3742002-12-13 20:15:29 +0000923
hasso508e53e2004-05-18 18:57:06 +0000924 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
925 return;
paul718e3742002-12-13 20:15:29 +0000926
hasso508e53e2004-05-18 18:57:06 +0000927 on = ospf6_neighbor_lookup (oh->router_id, oi);
928 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000929 {
hasso508e53e2004-05-18 18:57:06 +0000930 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
931 zlog_info ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000932 return;
933 }
934
hasso508e53e2004-05-18 18:57:06 +0000935 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +0000936 {
hasso508e53e2004-05-18 18:57:06 +0000937 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
938 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +0000939 return;
940 }
941
hasso508e53e2004-05-18 18:57:06 +0000942 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
943 on->state != OSPF6_NEIGHBOR_LOADING &&
944 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000945 {
hasso508e53e2004-05-18 18:57:06 +0000946 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
947 zlog_info ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000948 return;
949 }
950
hasso508e53e2004-05-18 18:57:06 +0000951 lsupdate = (struct ospf6_lsupdate *)
952 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000953
hasso508e53e2004-05-18 18:57:06 +0000954 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +0000955
hasso508e53e2004-05-18 18:57:06 +0000956 /* Process LSAs */
957 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
958 p < OSPF6_MESSAGE_END (oh) &&
959 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
960 p += OSPF6_LSA_SIZE (p))
961 {
962 if (num == 0)
963 break;
964 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
965 {
966 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
967 zlog_info ("Malformed LSA length, quit processing");
968 break;
969 }
970
971 ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on);
972 num--;
973 }
974
975 if (num != 0)
976 {
977 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
978 zlog_info ("Malformed LSA number or LSA length");
979 }
980 if (p != OSPF6_MESSAGE_END (oh))
981 {
982 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
983 zlog_info ("Trailing garbage ignored");
984 }
paul718e3742002-12-13 20:15:29 +0000985
986 /* RFC2328 Section 10.9: When the neighbor responds to these requests
987 with the proper Link State Update packet(s), the Link state request
988 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +0000989 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +0000990 can be recognized as a response to our previous LS Request */
991 if (! IN6_IS_ADDR_MULTICAST (dst) &&
992 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
993 on->state == OSPF6_NEIGHBOR_LOADING))
994 {
995 THREAD_OFF (on->thread_send_lsreq);
996 on->thread_send_lsreq =
997 thread_add_event (master, ospf6_lsreq_send, on, 0);
998 }
paul718e3742002-12-13 20:15:29 +0000999}
1000
1001void
hasso508e53e2004-05-18 18:57:06 +00001002ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1003 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001004{
hasso508e53e2004-05-18 18:57:06 +00001005 struct ospf6_neighbor *on;
1006 char *p;
1007 struct ospf6_lsa *his, *mine;
1008 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001009
hasso508e53e2004-05-18 18:57:06 +00001010 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1011 if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
1012 return;
paul718e3742002-12-13 20:15:29 +00001013
hasso508e53e2004-05-18 18:57:06 +00001014 on = ospf6_neighbor_lookup (oh->router_id, oi);
1015 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001016 {
hasso508e53e2004-05-18 18:57:06 +00001017 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1018 zlog_info ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001019 return;
1020 }
1021
hasso508e53e2004-05-18 18:57:06 +00001022 if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
paul718e3742002-12-13 20:15:29 +00001023 {
hasso508e53e2004-05-18 18:57:06 +00001024 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1025 zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
paul718e3742002-12-13 20:15:29 +00001026 return;
1027 }
1028
hasso508e53e2004-05-18 18:57:06 +00001029 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1030 on->state != OSPF6_NEIGHBOR_LOADING &&
1031 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001032 {
hasso508e53e2004-05-18 18:57:06 +00001033 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1034 zlog_info ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001035 return;
1036 }
1037
hasso508e53e2004-05-18 18:57:06 +00001038 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1039 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1040 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001041 {
hasso508e53e2004-05-18 18:57:06 +00001042 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
1043 his->scope = ospf6_get_lsa_scope (his->header->type, on);
1044 lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
paul718e3742002-12-13 20:15:29 +00001045
hasso508e53e2004-05-18 18:57:06 +00001046 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
1047 IS_OSPF6_DEBUG_LSA (SEND))
1048 zlog_info ("%s acknowledged by %s", his->name, on->name);
1049
1050 /* Find database copy */
1051 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1052 his->header->adv_router, lsdb);
1053 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001054 {
hasso508e53e2004-05-18 18:57:06 +00001055 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1056 zlog_info ("No database copy");
1057 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001058 continue;
1059 }
1060
hasso508e53e2004-05-18 18:57:06 +00001061 /* Check if the LSA is on his retrans-list */
1062 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1063 his->header->adv_router, on->retrans_list);
1064 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001065 {
hasso508e53e2004-05-18 18:57:06 +00001066 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1067 zlog_info ("Not on %s's retrans-list", on->name);
1068 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001069 continue;
1070 }
1071
hasso508e53e2004-05-18 18:57:06 +00001072 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001073 {
hasso508e53e2004-05-18 18:57:06 +00001074 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001075 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001076 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1077 zlog_info ("Questionable acknowledgement");
1078 ospf6_lsa_delete (his);
1079 continue;
paul718e3742002-12-13 20:15:29 +00001080 }
1081
hasso508e53e2004-05-18 18:57:06 +00001082 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
1083 IS_OSPF6_DEBUG_LSA (SEND))
1084 zlog_info ("Acknowledged, remove from %s's retrans-list",
1085 on->name);
1086
1087 if (OSPF6_LSA_IS_MAXAGE (mine))
1088 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
1089
1090 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1091 zlog_info ("remove %s from retrans_list of %s",
1092 mine->name, on->name);
1093 ospf6_lsdb_remove (mine, on->retrans_list);
1094 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001095 }
1096
hasso508e53e2004-05-18 18:57:06 +00001097 if (p != OSPF6_MESSAGE_END (oh))
1098 {
1099 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1100 zlog_info ("Trailing garbage ignored");
1101 }
paul718e3742002-12-13 20:15:29 +00001102}
1103
hasso508e53e2004-05-18 18:57:06 +00001104char recvbuf[OSPF6_MESSAGE_BUFSIZ];
1105char sendbuf[OSPF6_MESSAGE_BUFSIZ];
paul718e3742002-12-13 20:15:29 +00001106
1107int
1108ospf6_receive (struct thread *thread)
1109{
hasso508e53e2004-05-18 18:57:06 +00001110 int sockfd, len;
1111 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001112 struct in6_addr src, dst;
1113 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001114 struct iovec iovector[2];
1115 struct ospf6_interface *oi;
1116 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001117
1118 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001119 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001120 thread_add_read (master, ospf6_receive, NULL, sockfd);
1121
1122 /* initialize */
hasso508e53e2004-05-18 18:57:06 +00001123 memset (recvbuf, 0, sizeof (recvbuf));
1124 iovector[0].iov_base = recvbuf;
1125 iovector[0].iov_len = sizeof (recvbuf);
1126 iovector[1].iov_base = NULL;
1127 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001128
1129 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001130 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
1131 if (len > sizeof (recvbuf))
paul718e3742002-12-13 20:15:29 +00001132 {
hasso508e53e2004-05-18 18:57:06 +00001133 zlog_err ("Excess message read");
1134 return 0;
1135 }
1136 else if (len < sizeof (struct ospf6_header))
1137 {
1138 zlog_err ("Deficient message read");
paul718e3742002-12-13 20:15:29 +00001139 return 0;
1140 }
1141
hasso508e53e2004-05-18 18:57:06 +00001142 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1143 if (oi == NULL || oi->area == NULL)
1144 {
1145 zlog_info ("Message received on disabled interface");
1146 return 0;
1147 }
1148
1149 oh = (struct ospf6_header *) recvbuf;
1150
1151 /* Log */
1152 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1153 {
1154 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1155 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
1156 zlog_info ("%s received on %s",
1157 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1158 zlog_info (" src: %s", srcname);
1159 zlog_info (" dst: %s", dstname);
1160 if (len != ntohs (oh->length))
1161 zlog_info ("Message length does not match actually received: %d", len);
1162
1163 switch (oh->type)
1164 {
1165 case OSPF6_MESSAGE_TYPE_HELLO:
1166 ospf6_hello_print (oh);
1167 break;
1168 case OSPF6_MESSAGE_TYPE_DBDESC:
1169 ospf6_dbdesc_print (oh);
1170 break;
1171 case OSPF6_MESSAGE_TYPE_LSREQ:
1172 ospf6_lsreq_print (oh);
1173 break;
1174 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1175 ospf6_lsupdate_print (oh);
1176 break;
1177 case OSPF6_MESSAGE_TYPE_LSACK:
1178 ospf6_lsack_print (oh);
1179 break;
1180 default:
1181 zlog_info ("Unknown message");
1182 break;
1183 }
1184 }
1185
1186 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1187 {
1188 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1189 zlog_info ("Ignore message on passive interface %s",
1190 oi->interface->name);
1191 return 0;
1192 }
1193
1194 switch (oh->type)
1195 {
1196 case OSPF6_MESSAGE_TYPE_HELLO:
1197 ospf6_hello_recv (&src, &dst, oi, oh);
1198 break;
1199
1200 case OSPF6_MESSAGE_TYPE_DBDESC:
1201 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1202 break;
1203
1204 case OSPF6_MESSAGE_TYPE_LSREQ:
1205 ospf6_lsreq_recv (&src, &dst, oi, oh);
1206 break;
1207
1208 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1209 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1210 break;
1211
1212 case OSPF6_MESSAGE_TYPE_LSACK:
1213 ospf6_lsack_recv (&src, &dst, oi, oh);
1214 break;
1215
1216 default:
1217 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1218 zlog_info ("Unknown message");
1219 break;
1220 }
1221
1222 return 0;
1223}
1224
1225void
1226ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1227 struct ospf6_interface *oi, struct ospf6_header *oh)
1228{
1229 int len;
1230 char srcname[64], dstname[64];
1231 struct iovec iovector[2];
1232
1233 /* initialize */
1234 iovector[0].iov_base = (caddr_t) oh;
1235 iovector[0].iov_len = ntohs (oh->length);
1236 iovector[1].iov_base = NULL;
1237 iovector[1].iov_len = 0;
1238
1239 /* fill OSPF header */
1240 oh->version = OSPFV3_VERSION;
1241 /* message type must be set before */
1242 /* message length must be set before */
1243 oh->router_id = oi->area->ospf6->router_id;
1244 oh->area_id = oi->area->area_id;
1245 /* checksum is calculated by kernel */
1246 oh->instance_id = oi->instance_id;
1247 oh->reserved = 0;
1248
1249 /* Log */
1250 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1251 {
1252 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1253 if (src)
1254 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1255 else
1256 memset (srcname, 0, sizeof (srcname));
1257 zlog_info ("%s send on %s",
1258 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
1259 zlog_info (" src: %s", srcname);
1260 zlog_info (" dst: %s", dstname);
1261
1262 switch (oh->type)
1263 {
1264 case OSPF6_MESSAGE_TYPE_HELLO:
1265 ospf6_hello_print (oh);
1266 break;
1267 case OSPF6_MESSAGE_TYPE_DBDESC:
1268 ospf6_dbdesc_print (oh);
1269 break;
1270 case OSPF6_MESSAGE_TYPE_LSREQ:
1271 ospf6_lsreq_print (oh);
1272 break;
1273 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1274 ospf6_lsupdate_print (oh);
1275 break;
1276 case OSPF6_MESSAGE_TYPE_LSACK:
1277 ospf6_lsack_print (oh);
1278 break;
1279 default:
1280 zlog_info ("Unknown message");
1281 assert (0);
1282 break;
1283 }
1284 }
1285
1286 /* send message */
1287 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1288 if (len != ntohs (oh->length))
1289 zlog_err ("Could not send entire message");
1290}
1291
1292int
1293ospf6_hello_send (struct thread *thread)
1294{
1295 struct ospf6_interface *oi;
1296 struct ospf6_header *oh;
1297 struct ospf6_hello *hello;
1298 char *p;
1299 listnode node;
1300 struct ospf6_neighbor *on;
1301
1302 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1303 oi->thread_send_hello = (struct thread *) NULL;
1304
1305 if (oi->state <= OSPF6_INTERFACE_DOWN)
1306 {
1307 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1308 zlog_info ("Unable to send Hello on down interface %s",
1309 oi->interface->name);
1310 return 0;
1311 }
1312
1313 /* set next thread */
1314 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1315 oi, oi->hello_interval);
1316
1317 memset (sendbuf, 0, sizeof (sendbuf));
1318 oh = (struct ospf6_header *) sendbuf;
1319 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1320
1321 hello->interface_id = htonl (oi->interface->ifindex);
1322 hello->priority = oi->priority;
1323 hello->options[0] = oi->area->options[0];
1324 hello->options[1] = oi->area->options[1];
1325 hello->options[2] = oi->area->options[2];
1326 hello->hello_interval = htons (oi->hello_interval);
1327 hello->dead_interval = htons (oi->dead_interval);
1328 hello->drouter = oi->drouter;
1329 hello->bdrouter = oi->bdrouter;
1330
1331 p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello));
1332
1333 for (node = listhead (oi->neighbor_list); node; nextnode (node))
1334 {
1335 on = (struct ospf6_neighbor *) getdata (node);
1336
1337 if (on->state < OSPF6_NEIGHBOR_INIT)
1338 continue;
1339
1340 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1341 {
1342 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
1343 zlog_info ("sending Hello message: exceeds I/F MTU");
1344 break;
1345 }
1346
1347 memcpy (p, &on->router_id, sizeof (u_int32_t));
1348 p += sizeof (u_int32_t);
1349 }
1350
1351 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1352 oh->length = htons (p - sendbuf);
1353
1354 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1355 return 0;
1356}
1357
1358int
1359ospf6_dbdesc_send (struct thread *thread)
1360{
1361 struct ospf6_neighbor *on;
1362 struct ospf6_header *oh;
1363 struct ospf6_dbdesc *dbdesc;
1364 char *p;
1365 struct ospf6_lsa *lsa;
1366
1367 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1368 on->thread_send_dbdesc = (struct thread *) NULL;
1369
1370 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1371 {
1372 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
1373 zlog_info ("Quit to send DbDesc to neighbor %s state %s",
1374 on->name, ospf6_neighbor_state_str[on->state]);
1375 return 0;
1376 }
1377
1378 /* set next thread if master */
1379 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1380 on->thread_send_dbdesc =
1381 thread_add_timer (master, ospf6_dbdesc_send, on,
1382 on->ospf6_if->rxmt_interval);
1383
1384 memset (sendbuf, 0, sizeof (sendbuf));
1385 oh = (struct ospf6_header *) sendbuf;
1386 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1387 sizeof (struct ospf6_header));
1388
1389 /* if this is initial one, initialize sequence number for DbDesc */
1390 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1391 {
1392 struct timeval tv;
1393 if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
1394 tv.tv_sec = 1;
1395 on->dbdesc_seqnum = tv.tv_sec;
1396 }
1397
1398 dbdesc->options[0] = on->ospf6_if->area->options[0];
1399 dbdesc->options[1] = on->ospf6_if->area->options[1];
1400 dbdesc->options[2] = on->ospf6_if->area->options[2];
1401 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1402 dbdesc->bits = on->dbdesc_bits;
1403 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1404
1405 /* if this is not initial one, set LSA headers in dbdesc */
1406 p = (char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
1407 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1408 {
1409 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1410 lsa = ospf6_lsdb_next (lsa))
1411 {
1412 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1413
1414 /* MTU check */
1415 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1416 on->ospf6_if->ifmtu)
1417 {
1418 ospf6_lsa_unlock (lsa);
1419 break;
1420 }
1421 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1422 p += sizeof (struct ospf6_lsa_header);
1423 }
1424 }
1425
1426 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1427 oh->length = htons (p - sendbuf);
1428
1429 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1430 on->ospf6_if, oh);
1431 return 0;
1432}
1433
1434int
1435ospf6_dbdesc_send_newone (struct thread *thread)
1436{
1437 struct ospf6_neighbor *on;
1438 struct ospf6_lsa *lsa;
1439 unsigned int size = 0;
1440
1441 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1442 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1443 zlog_info ("Remove entire dbdesc_list of %s: sending newone", on->name);
1444 ospf6_lsdb_remove_all (on->dbdesc_list);
1445
1446 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1447 so that ospf6_send_dbdesc () can send those LSAs */
1448 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1449 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1450 lsa = ospf6_lsdb_next (lsa))
1451 {
1452 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1453 {
1454 ospf6_lsa_unlock (lsa);
1455 break;
1456 }
1457
1458 if (IS_OSPF6_DEBUG_LSA (DATABASE))
1459 zlog_info ("Move %s from summary_list to dbdesc_list of %s",
1460 lsa->name, on->name);
1461 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1462 ospf6_lsdb_remove (lsa, on->summary_list);
1463 size += sizeof (struct ospf6_lsa_header);
1464 }
1465
1466 if (on->summary_list->count == 0)
1467 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1468
1469 /* If slave, More bit check must be done here */
1470 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1471 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1472 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1473 thread_add_event (master, exchange_done, on, 0);
1474
1475 thread_execute (master, ospf6_dbdesc_send, on, 0);
1476 return 0;
1477}
1478
1479int
1480ospf6_lsreq_send (struct thread *thread)
1481{
1482 struct ospf6_neighbor *on;
1483 struct ospf6_header *oh;
1484 struct ospf6_lsreq_entry *e;
1485 char *p;
1486 struct ospf6_lsa *lsa;
1487
1488 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1489 on->thread_send_lsreq = (struct thread *) NULL;
1490
1491 /* LSReq will be sent only in ExStart or Loading */
1492 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1493 on->state != OSPF6_NEIGHBOR_LOADING)
1494 {
1495 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
1496 zlog_info ("Quit to send LSReq to neighbor %s state %s",
1497 on->name, ospf6_neighbor_state_str[on->state]);
1498 return 0;
1499 }
1500
1501 /* schedule loading_done if request list is empty */
1502 if (on->request_list->count == 0)
1503 {
1504 thread_add_event (master, loading_done, on, 0);
1505 return 0;
1506 }
1507
1508 /* set next thread */
1509 on->thread_send_lsreq =
1510 thread_add_timer (master, ospf6_lsreq_send, on,
1511 on->ospf6_if->rxmt_interval);
1512
1513 memset (sendbuf, 0, sizeof (sendbuf));
1514 oh = (struct ospf6_header *) sendbuf;
1515
1516 /* set Request entries in lsreq */
1517 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1518 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1519 lsa = ospf6_lsdb_next (lsa))
1520 {
1521 /* MTU check */
1522 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
1523 {
1524 ospf6_lsa_unlock (lsa);
1525 break;
1526 }
1527
1528 e = (struct ospf6_lsreq_entry *) p;
1529 e->type = lsa->header->type;
1530 e->id = lsa->header->id;
1531 e->adv_router = lsa->header->adv_router;
1532 p += sizeof (struct ospf6_lsreq_entry);
1533 }
1534
1535 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1536 oh->length = htons (p - sendbuf);
1537
1538 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1539 on->ospf6_if, oh);
1540 return 0;
1541}
1542
1543int
1544ospf6_lsupdate_send_neighbor (struct thread *thread)
1545{
1546 struct ospf6_neighbor *on;
1547 struct ospf6_header *oh;
1548 struct ospf6_lsupdate *lsupdate;
1549 char *p;
1550 int num;
1551 struct ospf6_lsa *lsa;
1552
1553 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1554 on->thread_send_lsupdate = (struct thread *) NULL;
1555
1556 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1557 {
1558 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1559 zlog_info ("Quit to send LSUpdate to neighbor %s state %s",
1560 on->name, ospf6_neighbor_state_str[on->state]);
1561 return 0;
1562 }
1563
1564 /* if we have nothing to send, return */
1565 if (on->lsupdate_list->count == 0 &&
1566 on->retrans_list->count == 0)
1567 return 0;
1568
1569 if (IS_OSPF6_DEBUG_LSA (SEND))
1570 zlog_info ("LSA Send to %s", on->name);
1571
1572 memset (sendbuf, 0, sizeof (sendbuf));
1573 oh = (struct ospf6_header *) sendbuf;
1574 lsupdate = (struct ospf6_lsupdate *)
1575 ((caddr_t) oh + sizeof (struct ospf6_header));
1576
1577 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1578 num = 0;
1579
1580 /* lsupdate_list lists those LSA which doesn't need to be
1581 retransmitted. remove those from the list */
1582 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1583 lsa = ospf6_lsdb_next (lsa))
1584 {
1585 /* MTU check */
1586 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1587 {
1588 ospf6_lsa_unlock (lsa);
1589 break;
1590 }
1591
1592 if (IS_OSPF6_DEBUG_LSA (SEND))
1593 ospf6_lsa_header_print (lsa);
1594
1595 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1596 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1597 p += OSPF6_LSA_SIZE (lsa->header);
1598 num++;
1599
1600 assert (lsa->lock == 2);
1601 ospf6_lsdb_remove (lsa, on->lsupdate_list);
1602 }
1603
1604 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
1605 lsa = ospf6_lsdb_next (lsa))
1606 {
1607 /* MTU check */
1608 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
1609 {
1610 ospf6_lsa_unlock (lsa);
1611 break;
1612 }
1613
1614 if (IS_OSPF6_DEBUG_LSA (SEND))
1615 ospf6_lsa_header_print (lsa);
1616
1617 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1618 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1619 p += OSPF6_LSA_SIZE (lsa->header);
1620 num++;
1621 }
1622
1623 lsupdate->lsa_number = htonl (num);
1624
1625 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1626 oh->length = htons (p - sendbuf);
1627
1628 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1629 on->ospf6_if, oh);
1630
1631 if (on->lsupdate_list->count != 0 ||
1632 on->retrans_list->count != 0)
1633 {
1634 if (on->lsupdate_list->count != 0)
1635 on->thread_send_lsupdate =
1636 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
1637 else
1638 on->thread_send_lsupdate =
1639 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
1640 on->ospf6_if->rxmt_interval);
1641 }
1642
1643 return 0;
1644}
1645
1646int
1647ospf6_lsupdate_send_interface (struct thread *thread)
1648{
1649 struct ospf6_interface *oi;
1650 struct ospf6_header *oh;
1651 struct ospf6_lsupdate *lsupdate;
1652 char *p;
1653 int num;
1654 struct ospf6_lsa *lsa;
1655
1656 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1657 oi->thread_send_lsupdate = (struct thread *) NULL;
1658
1659 if (oi->state <= OSPF6_INTERFACE_WAITING)
1660 {
1661 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
1662 zlog_info ("Quit to send LSUpdate to interface %s state %s",
1663 oi->interface->name, ospf6_interface_state_str[oi->state]);
1664 return 0;
1665 }
1666
1667 /* if we have nothing to send, return */
1668 if (oi->lsupdate_list->count == 0)
1669 return 0;
1670
1671 if (IS_OSPF6_DEBUG_LSA (SEND))
1672 zlog_info ("LSA Send to %s", oi->interface->name);
1673
1674 memset (sendbuf, 0, sizeof (sendbuf));
1675 oh = (struct ospf6_header *) sendbuf;
1676 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
1677 sizeof (struct ospf6_header));
1678
1679 p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1680 num = 0;
1681
1682 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
1683 lsa = ospf6_lsdb_next (lsa))
1684 {
1685 /* MTU check */
1686 if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > oi->ifmtu)
1687 {
1688 ospf6_lsa_unlock (lsa);
1689 break;
1690 }
1691
1692 if (IS_OSPF6_DEBUG_LSA (SEND))
1693 ospf6_lsa_header_print (lsa);
1694
1695 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1696 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1697 p += OSPF6_LSA_SIZE (lsa->header);
1698 num++;
1699
1700 assert (lsa->lock == 2);
1701 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
1702 }
1703
1704 lsupdate->lsa_number = htonl (num);
1705
1706 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1707 oh->length = htons (p - sendbuf);
1708
1709 if (oi->state == OSPF6_INTERFACE_DR ||
1710 oi->state == OSPF6_INTERFACE_BDR)
1711 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1712 else
1713 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1714
1715 if (oi->lsupdate_list->count > 0)
1716 {
1717 oi->thread_send_lsupdate =
1718 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
1719 }
1720
1721 return 0;
1722}
1723
1724int
1725ospf6_lsack_send_neighbor (struct thread *thread)
1726{
1727 struct ospf6_neighbor *on;
1728 struct ospf6_header *oh;
1729 char *p;
1730 struct ospf6_lsa *lsa;
1731
1732 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1733 on->thread_send_lsack = (struct thread *) NULL;
1734
1735 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1736 {
1737 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1738 zlog_info ("Quit to send LSAck to neighbor %s state %s",
1739 on->name, ospf6_neighbor_state_str[on->state]);
1740 return 0;
1741 }
1742
1743 /* if we have nothing to send, return */
1744 if (on->lsack_list->count == 0)
1745 return 0;
1746
1747 memset (sendbuf, 0, sizeof (sendbuf));
1748 oh = (struct ospf6_header *) sendbuf;
1749
1750 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1751
1752 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
1753 lsa = ospf6_lsdb_next (lsa))
1754 {
1755 /* MTU check */
1756 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1757 {
1758 /* if we run out of packet size/space here,
1759 better to try again soon. */
1760 THREAD_OFF (on->thread_send_lsack);
1761 on->thread_send_lsack =
1762 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
1763
1764 ospf6_lsa_unlock (lsa);
1765 break;
1766 }
1767
1768 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1769 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1770 p += sizeof (struct ospf6_lsa_header);
1771
1772 assert (lsa->lock == 2);
1773 ospf6_lsdb_remove (lsa, on->lsack_list);
1774 }
1775
1776 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1777 oh->length = htons (p - sendbuf);
1778
1779 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1780 on->ospf6_if, oh);
1781 return 0;
1782}
1783
1784int
1785ospf6_lsack_send_interface (struct thread *thread)
1786{
1787 struct ospf6_interface *oi;
1788 struct ospf6_header *oh;
1789 char *p;
1790 struct ospf6_lsa *lsa;
1791
1792 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1793 oi->thread_send_lsack = (struct thread *) NULL;
1794
1795 if (oi->state <= OSPF6_INTERFACE_WAITING)
1796 {
1797 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
1798 zlog_info ("Quit to send LSAck to interface %s state %s",
1799 oi->interface->name, ospf6_interface_state_str[oi->state]);
1800 return 0;
1801 }
1802
1803 /* if we have nothing to send, return */
1804 if (oi->lsack_list->count == 0)
1805 return 0;
1806
1807 memset (sendbuf, 0, sizeof (sendbuf));
1808 oh = (struct ospf6_header *) sendbuf;
1809
1810 p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
1811
1812 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
1813 lsa = ospf6_lsdb_next (lsa))
1814 {
1815 /* MTU check */
1816 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
1817 {
1818 /* if we run out of packet size/space here,
1819 better to try again soon. */
1820 THREAD_OFF (oi->thread_send_lsack);
1821 oi->thread_send_lsack =
1822 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1823
1824 ospf6_lsa_unlock (lsa);
1825 break;
1826 }
1827
1828 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
1829 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1830 p += sizeof (struct ospf6_lsa_header);
1831
1832 assert (lsa->lock == 2);
1833 ospf6_lsdb_remove (lsa, oi->lsack_list);
1834 }
1835
1836 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
1837 oh->length = htons (p - sendbuf);
1838
1839 if (oi->state == OSPF6_INTERFACE_DR ||
1840 oi->state == OSPF6_INTERFACE_BDR)
1841 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1842 else
1843 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
1844
1845 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
1846 {
1847 oi->thread_send_lsack =
1848 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
1849 }
paul718e3742002-12-13 20:15:29 +00001850
1851 return 0;
1852}
1853
1854
hasso508e53e2004-05-18 18:57:06 +00001855/* Commands */
1856DEFUN (debug_ospf6_message,
1857 debug_ospf6_message_cmd,
1858 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1859 DEBUG_STR
1860 OSPF6_STR
1861 "Debug OSPFv3 message\n"
1862 "Debug Unknown message\n"
1863 "Debug Hello message\n"
1864 "Debug Database Description message\n"
1865 "Debug Link State Request message\n"
1866 "Debug Link State Update message\n"
1867 "Debug Link State Acknowledgement message\n"
1868 "Debug All message\n"
1869 )
paul718e3742002-12-13 20:15:29 +00001870{
hasso508e53e2004-05-18 18:57:06 +00001871 unsigned char level = 0;
1872 int type = 0;
paul718e3742002-12-13 20:15:29 +00001873 int i;
1874
hasso508e53e2004-05-18 18:57:06 +00001875 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00001876
hasso508e53e2004-05-18 18:57:06 +00001877 /* check type */
1878 if (! strncmp (argv[0], "u", 1))
1879 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1880 else if (! strncmp (argv[0], "h", 1))
1881 type = OSPF6_MESSAGE_TYPE_HELLO;
1882 else if (! strncmp (argv[0], "d", 1))
1883 type = OSPF6_MESSAGE_TYPE_DBDESC;
1884 else if (! strncmp (argv[0], "lsr", 3))
1885 type = OSPF6_MESSAGE_TYPE_LSREQ;
1886 else if (! strncmp (argv[0], "lsu", 3))
1887 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1888 else if (! strncmp (argv[0], "lsa", 3))
1889 type = OSPF6_MESSAGE_TYPE_LSACK;
1890 else if (! strncmp (argv[0], "a", 1))
1891 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00001892
hasso508e53e2004-05-18 18:57:06 +00001893 if (argc == 1)
1894 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1895 else if (! strncmp (argv[1], "s", 1))
1896 level = OSPF6_DEBUG_MESSAGE_SEND;
1897 else if (! strncmp (argv[1], "r", 1))
1898 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00001899
hasso508e53e2004-05-18 18:57:06 +00001900 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00001901 {
hasso508e53e2004-05-18 18:57:06 +00001902 for (i = 0; i < 6; i++)
1903 OSPF6_DEBUG_MESSAGE_ON (i, level);
1904 }
1905 else
1906 OSPF6_DEBUG_MESSAGE_ON (type, level);
1907
1908 return CMD_SUCCESS;
1909}
1910
1911ALIAS (debug_ospf6_message,
1912 debug_ospf6_message_sendrecv_cmd,
1913 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1914 DEBUG_STR
1915 OSPF6_STR
1916 "Debug OSPFv3 message\n"
1917 "Debug Unknown message\n"
1918 "Debug Hello message\n"
1919 "Debug Database Description message\n"
1920 "Debug Link State Request message\n"
1921 "Debug Link State Update message\n"
1922 "Debug Link State Acknowledgement message\n"
1923 "Debug All message\n"
1924 "Debug only sending message\n"
1925 "Debug only receiving message\n"
1926 );
1927
1928
1929DEFUN (no_debug_ospf6_message,
1930 no_debug_ospf6_message_cmd,
1931 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
1932 NO_STR
1933 DEBUG_STR
1934 OSPF6_STR
1935 "Debug OSPFv3 message\n"
1936 "Debug Unknown message\n"
1937 "Debug Hello message\n"
1938 "Debug Database Description message\n"
1939 "Debug Link State Request message\n"
1940 "Debug Link State Update message\n"
1941 "Debug Link State Acknowledgement message\n"
1942 "Debug All message\n"
1943 )
1944{
1945 unsigned char level = 0;
1946 int type = 0;
1947 int i;
1948
1949 assert (argc > 0);
1950
1951 /* check type */
1952 if (! strncmp (argv[0], "u", 1))
1953 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1954 else if (! strncmp (argv[0], "h", 1))
1955 type = OSPF6_MESSAGE_TYPE_HELLO;
1956 else if (! strncmp (argv[0], "d", 1))
1957 type = OSPF6_MESSAGE_TYPE_DBDESC;
1958 else if (! strncmp (argv[0], "lsr", 3))
1959 type = OSPF6_MESSAGE_TYPE_LSREQ;
1960 else if (! strncmp (argv[0], "lsu", 3))
1961 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
1962 else if (! strncmp (argv[0], "lsa", 3))
1963 type = OSPF6_MESSAGE_TYPE_LSACK;
1964 else if (! strncmp (argv[0], "a", 1))
1965 type = OSPF6_MESSAGE_TYPE_ALL;
1966
1967 if (argc == 1)
1968 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1969 else if (! strncmp (argv[1], "s", 1))
1970 level = OSPF6_DEBUG_MESSAGE_SEND;
1971 else if (! strncmp (argv[1], "r", 1))
1972 level = OSPF6_DEBUG_MESSAGE_RECV;
1973
1974 if (type == OSPF6_MESSAGE_TYPE_ALL)
1975 {
1976 for (i = 0; i < 6; i++)
1977 OSPF6_DEBUG_MESSAGE_OFF (i, level);
1978 }
1979 else
1980 OSPF6_DEBUG_MESSAGE_OFF (type, level);
1981
1982 return CMD_SUCCESS;
1983}
1984
1985ALIAS (no_debug_ospf6_message,
1986 no_debug_ospf6_message_sendrecv_cmd,
1987 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
1988 NO_STR
1989 DEBUG_STR
1990 OSPF6_STR
1991 "Debug OSPFv3 message\n"
1992 "Debug Unknown message\n"
1993 "Debug Hello message\n"
1994 "Debug Database Description message\n"
1995 "Debug Link State Request message\n"
1996 "Debug Link State Update message\n"
1997 "Debug Link State Acknowledgement message\n"
1998 "Debug All message\n"
1999 "Debug only sending message\n"
2000 "Debug only receiving message\n"
2001 );
2002
2003int
2004config_write_ospf6_debug_message (struct vty *vty)
2005{
2006 char *type_str[] = {"unknown", "hello", "dbdesc",
2007 "lsreq", "lsupdate", "lsack"};
2008 unsigned char s = 0, r = 0;
2009 int i;
2010
2011 for (i = 0; i < 6; i++)
2012 {
2013 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2014 s |= 1 << i;
2015 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2016 r |= 1 << i;
2017 }
2018
2019 if (s == 0x3f && r == 0x3f)
2020 {
2021 vty_out (vty, "debug ospf6 message all%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002022 return 0;
2023 }
2024
hasso508e53e2004-05-18 18:57:06 +00002025 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002026 {
hasso508e53e2004-05-18 18:57:06 +00002027 vty_out (vty, "debug ospf6 message all send%s", VTY_NEWLINE);
2028 return 0;
2029 }
2030 else if (s == 0 && r == 0x3f)
2031 {
2032 vty_out (vty, "debug ospf6 message all recv%s", VTY_NEWLINE);
2033 return 0;
paul718e3742002-12-13 20:15:29 +00002034 }
2035
hasso508e53e2004-05-18 18:57:06 +00002036 /* Unknown message is logged by default */
2037 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2038 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2039 vty_out (vty, "no debug ospf6 message unknown%s", VTY_NEWLINE);
2040 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
2041 vty_out (vty, "no debug ospf6 message unknown send%s", VTY_NEWLINE);
2042 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2043 vty_out (vty, "no debug ospf6 message unknown recv%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002044
hasso508e53e2004-05-18 18:57:06 +00002045 for (i = 1; i < 6; i++)
2046 {
2047 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2048 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2049 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VTY_NEWLINE);
2050 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2051 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
2052 VTY_NEWLINE);
2053 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2054 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
2055 VTY_NEWLINE);
2056 }
paul718e3742002-12-13 20:15:29 +00002057
2058 return 0;
2059}
2060
paul718e3742002-12-13 20:15:29 +00002061void
hasso508e53e2004-05-18 18:57:06 +00002062install_element_ospf6_debug_message ()
paul718e3742002-12-13 20:15:29 +00002063{
hasso508e53e2004-05-18 18:57:06 +00002064 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2065 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2066 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2067 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2068 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2069 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2070 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2071 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002072}
2073
paul718e3742002-12-13 20:15:29 +00002074