blob: 5fb5a216476ef40f6072da406ba5ab51ba5510ab [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
hasso3b4cd3a2004-05-18 19:28:32 +000024#include "memory.h"
hasso508e53e2004-05-18 18:57:06 +000025#include "log.h"
26#include "vty.h"
27#include "command.h"
28#include "thread.h"
29#include "linklist.h"
30
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
34#include "ospf6_network.h"
35#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000036
hasso508e53e2004-05-18 18:57:06 +000037#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_neighbor.h"
40#include "ospf6_interface.h"
41
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040042/* for structures and macros ospf6_lsa_examin() needs */
43#include "ospf6_abr.h"
44#include "ospf6_asbr.h"
45#include "ospf6_intra.h"
46
hasso508e53e2004-05-18 18:57:06 +000047#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000048#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000049
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +040050#include <netinet/ip6.h>
51
hasso508e53e2004-05-18 18:57:06 +000052unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
Denis Ovsienko5031ed12011-10-14 21:59:58 +040053static const struct message ospf6_message_type_str [] =
54{
55 { OSPF6_MESSAGE_TYPE_HELLO, "Hello" },
56 { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" },
57 { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" },
58 { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" },
59 { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" },
60};
Balaji.G837d16c2012-09-26 14:09:10 +053061static const size_t ospf6_message_type_str_max = array_size(ospf6_message_type_str);
hasso508e53e2004-05-18 18:57:06 +000062
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040063/* Minimum (besides the standard OSPF packet header) lengths for OSPF
64 packets of particular types, offset is the "type" field. */
65const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
66{
67 0,
68 OSPF6_HELLO_MIN_SIZE,
69 OSPF6_DB_DESC_MIN_SIZE,
70 OSPF6_LS_REQ_MIN_SIZE,
71 OSPF6_LS_UPD_MIN_SIZE,
72 OSPF6_LS_ACK_MIN_SIZE
73};
74
75/* Minimum (besides the standard LSA header) lengths for LSAs of particular
76 types, offset is the "LSA function code" portion of "LSA type" field. */
77const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
78{
79 0,
80 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
81 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
82 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
83 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
84 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
85 /* 0x2006 */ 0,
86 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
87 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
88 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
89};
90
hasso508e53e2004-05-18 18:57:06 +000091/* print functions */
92
93static void
94ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000095{
hasso508e53e2004-05-18 18:57:06 +000096 char router_id[16], area_id[16];
97 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
98 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000099
hassoc6487d62004-12-24 06:00:11 +0000100 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +0000101 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +0000102 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +0000103 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +0000104}
paul718e3742002-12-13 20:15:29 +0000105
106void
hasso508e53e2004-05-18 18:57:06 +0000107ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000108{
paul718e3742002-12-13 20:15:29 +0000109 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000110 char options[16];
111 char drouter[16], bdrouter[16], neighbor[16];
112 char *p;
paul718e3742002-12-13 20:15:29 +0000113
hasso508e53e2004-05-18 18:57:06 +0000114 ospf6_header_print (oh);
115 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000116
hasso508e53e2004-05-18 18:57:06 +0000117 hello = (struct ospf6_hello *)
118 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000119
hasso508e53e2004-05-18 18:57:06 +0000120 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
121 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
122 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000123
hassoc6487d62004-12-24 06:00:11 +0000124 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000125 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000126 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000127 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000128 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000129
hasso508e53e2004-05-18 18:57:06 +0000130 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
131 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
132 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000133 {
hasso508e53e2004-05-18 18:57:06 +0000134 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000135 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000136 }
hasso508e53e2004-05-18 18:57:06 +0000137
Denis Ovsienkofa079662011-10-08 17:22:45 +0400138 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000139}
140
hasso508e53e2004-05-18 18:57:06 +0000141void
142ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000143{
paul718e3742002-12-13 20:15:29 +0000144 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000145 char options[16];
146 char *p;
paul718e3742002-12-13 20:15:29 +0000147
hasso508e53e2004-05-18 18:57:06 +0000148 ospf6_header_print (oh);
149 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000150
hasso508e53e2004-05-18 18:57:06 +0000151 dbdesc = (struct ospf6_dbdesc *)
152 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000153
hasso508e53e2004-05-18 18:57:06 +0000154 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000155
hassoc6487d62004-12-24 06:00:11 +0000156 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000157 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000158 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000159 dbdesc->reserved2,
160 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
161 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
162 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
163 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000164
hasso508e53e2004-05-18 18:57:06 +0000165 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
166 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
167 p += sizeof (struct ospf6_lsa_header))
168 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
169
Denis Ovsienkofa079662011-10-08 17:22:45 +0400170 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000171}
172
hasso508e53e2004-05-18 18:57:06 +0000173void
174ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000175{
hasso508e53e2004-05-18 18:57:06 +0000176 char id[16], adv_router[16];
177 char *p;
paul718e3742002-12-13 20:15:29 +0000178
hasso508e53e2004-05-18 18:57:06 +0000179 ospf6_header_print (oh);
180 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000181
hasso508e53e2004-05-18 18:57:06 +0000182 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
183 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
184 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000185 {
hasso508e53e2004-05-18 18:57:06 +0000186 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
187 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
188 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000189 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000190 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000191 }
hasso508e53e2004-05-18 18:57:06 +0000192
Denis Ovsienkofa079662011-10-08 17:22:45 +0400193 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000194}
195
hasso508e53e2004-05-18 18:57:06 +0000196void
197ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000198{
paul718e3742002-12-13 20:15:29 +0000199 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000200 u_long num;
201 char *p;
paul718e3742002-12-13 20:15:29 +0000202
hasso508e53e2004-05-18 18:57:06 +0000203 ospf6_header_print (oh);
204 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000205
hasso508e53e2004-05-18 18:57:06 +0000206 lsupdate = (struct ospf6_lsupdate *)
207 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000208
hasso508e53e2004-05-18 18:57:06 +0000209 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000210 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000211
hasso508e53e2004-05-18 18:57:06 +0000212 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
213 p < OSPF6_MESSAGE_END (oh) &&
214 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
215 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000216 {
hasso508e53e2004-05-18 18:57:06 +0000217 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000218 }
paul718e3742002-12-13 20:15:29 +0000219
Denis Ovsienkofa079662011-10-08 17:22:45 +0400220 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000221}
222
hasso508e53e2004-05-18 18:57:06 +0000223void
224ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000225{
hasso508e53e2004-05-18 18:57:06 +0000226 char *p;
paul718e3742002-12-13 20:15:29 +0000227
hasso508e53e2004-05-18 18:57:06 +0000228 ospf6_header_print (oh);
229 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000230
hasso508e53e2004-05-18 18:57:06 +0000231 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
232 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
233 p += sizeof (struct ospf6_lsa_header))
234 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
235
Denis Ovsienkofa079662011-10-08 17:22:45 +0400236 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000237}
238
Paul Jakma6ac29a52008-08-15 13:45:30 +0100239static void
hasso508e53e2004-05-18 18:57:06 +0000240ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
241 struct ospf6_interface *oi, struct ospf6_header *oh)
242{
243 struct ospf6_hello *hello;
244 struct ospf6_neighbor *on;
245 char *p;
246 int twoway = 0;
247 int neighborchange = 0;
248 int backupseen = 0;
249
hasso508e53e2004-05-18 18:57:06 +0000250 hello = (struct ospf6_hello *)
251 ((caddr_t) oh + sizeof (struct ospf6_header));
252
paul718e3742002-12-13 20:15:29 +0000253 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000254 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000255 {
hasso508e53e2004-05-18 18:57:06 +0000256 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000257 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000258 return;
259 }
260
261 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000262 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000263 {
hasso508e53e2004-05-18 18:57:06 +0000264 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000265 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000266 return;
267 }
268
hasso508e53e2004-05-18 18:57:06 +0000269 /* E-bit check */
270 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
271 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000272 {
hasso508e53e2004-05-18 18:57:06 +0000273 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000274 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000275 return;
276 }
277
hasso508e53e2004-05-18 18:57:06 +0000278 /* Find neighbor, create if not exist */
279 on = ospf6_neighbor_lookup (oh->router_id, oi);
280 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000281 {
hasso508e53e2004-05-18 18:57:06 +0000282 on = ospf6_neighbor_create (oh->router_id, oi);
283 on->prev_drouter = on->drouter = hello->drouter;
284 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
285 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000286 }
287
hasso7b6ae022005-06-24 08:17:51 +0000288 /* always override neighbor's source address and ifindex */
289 on->ifindex = ntohl (hello->interface_id);
290 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
291
paul718e3742002-12-13 20:15:29 +0000292 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000293 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
294 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
295 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000296 {
hasso508e53e2004-05-18 18:57:06 +0000297 u_int32_t *router_id = (u_int32_t *) p;
298
299 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000300 twoway++;
paul718e3742002-12-13 20:15:29 +0000301 }
302
Denis Ovsienkofa079662011-10-08 17:22:45 +0400303 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000304
305 /* RouterPriority check */
306 if (on->priority != hello->priority)
307 {
308 on->priority = hello->priority;
309 neighborchange++;
310 }
311
312 /* DR check */
313 if (on->drouter != hello->drouter)
314 {
315 on->prev_drouter = on->drouter;
316 on->drouter = hello->drouter;
317 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
318 neighborchange++;
319 }
320
321 /* BDR check */
322 if (on->bdrouter != hello->bdrouter)
323 {
324 on->prev_bdrouter = on->bdrouter;
325 on->bdrouter = hello->bdrouter;
326 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
327 neighborchange++;
328 }
paul718e3742002-12-13 20:15:29 +0000329
330 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000331 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000332 {
hasso508e53e2004-05-18 18:57:06 +0000333 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000334 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000335 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000336 backupseen++;
337 }
338
hasso508e53e2004-05-18 18:57:06 +0000339 /* Execute neighbor events */
340 thread_execute (master, hello_received, on, 0);
341 if (twoway)
342 thread_execute (master, twoway_received, on, 0);
343 else
344 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000345
hasso508e53e2004-05-18 18:57:06 +0000346 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000347 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000348 thread_add_event (master, backup_seen, oi, 0);
349 if (neighborchange)
350 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000351}
352
hasso508e53e2004-05-18 18:57:06 +0000353static void
354ospf6_dbdesc_recv_master (struct ospf6_header *oh,
355 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000356{
paul718e3742002-12-13 20:15:29 +0000357 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000358 char *p;
paul718e3742002-12-13 20:15:29 +0000359
hasso508e53e2004-05-18 18:57:06 +0000360 dbdesc = (struct ospf6_dbdesc *)
361 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000362
hasso508e53e2004-05-18 18:57:06 +0000363 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000364 {
hasso508e53e2004-05-18 18:57:06 +0000365 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000366 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000367 return;
368 }
369
hasso508e53e2004-05-18 18:57:06 +0000370 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000371 {
hasso508e53e2004-05-18 18:57:06 +0000372 case OSPF6_NEIGHBOR_TWOWAY:
373 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000374 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000375 return;
376
377 case OSPF6_NEIGHBOR_INIT:
378 thread_execute (master, twoway_received, on, 0);
379 if (on->state != OSPF6_NEIGHBOR_EXSTART)
380 {
381 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000382 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000383 return;
384 }
385 /* else fall through to ExStart */
386
387 case OSPF6_NEIGHBOR_EXSTART:
388 /* if neighbor obeys us as our slave, schedule negotiation_done
389 and process LSA Headers. Otherwise, ignore this message */
390 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
391 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
392 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
393 {
394 /* execute NegotiationDone */
395 thread_execute (master, negotiation_done, on, 0);
396
397 /* Record neighbor options */
398 memcpy (on->options, dbdesc->options, sizeof (on->options));
399 }
400 else
401 {
402 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000403 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000404 return;
405 }
406 /* fall through to exchange */
407
408 case OSPF6_NEIGHBOR_EXCHANGE:
409 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
410 {
411 /* Duplicated DatabaseDescription is dropped by master */
412 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000413 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000414 return;
415 }
416
417 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
418 {
419 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000420 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000421 thread_add_event (master, seqnumber_mismatch, on, 0);
422 return;
423 }
424
425 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
426 {
427 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000428 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000429 thread_add_event (master, seqnumber_mismatch, on, 0);
430 return;
431 }
432
433 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
434 {
435 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000436 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000437 thread_add_event (master, seqnumber_mismatch, on, 0);
438 return;
439 }
440
441 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
442 {
443 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000444 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000445 (u_long) on->dbdesc_seqnum);
446 thread_add_event (master, seqnumber_mismatch, on, 0);
447 return;
448 }
449 break;
450
451 case OSPF6_NEIGHBOR_LOADING:
452 case OSPF6_NEIGHBOR_FULL:
453 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
454 {
455 /* Duplicated DatabaseDescription is dropped by master */
456 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000457 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000458 return;
459 }
460
461 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000462 zlog_debug ("Not duplicate dbdesc in state %s",
463 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000464 thread_add_event (master, seqnumber_mismatch, on, 0);
465 return;
466
467 default:
468 assert (0);
469 break;
470 }
471
472 /* Process LSA headers */
473 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
474 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
475 p += sizeof (struct ospf6_lsa_header))
476 {
477 struct ospf6_lsa *his, *mine;
478 struct ospf6_lsdb *lsdb = NULL;
479
480 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000481
482 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000483 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000484
485 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000486 {
hasso6452df02004-08-15 05:52:07 +0000487 case OSPF6_SCOPE_LINKLOCAL:
488 lsdb = on->ospf6_if->lsdb;
489 break;
490 case OSPF6_SCOPE_AREA:
491 lsdb = on->ospf6_if->area->lsdb;
492 break;
493 case OSPF6_SCOPE_AS:
494 lsdb = on->ospf6_if->area->ospf6->lsdb;
495 break;
496 case OSPF6_SCOPE_RESERVED:
497 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000498 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000499 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000500 continue;
501 break;
hasso508e53e2004-05-18 18:57:06 +0000502 }
503
504 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000505 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000506 {
507 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000508 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000509 ospf6_lsa_delete (his);
510 thread_add_event (master, seqnumber_mismatch, on, 0);
511 return;
512 }
513
514 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
515 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000516 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000517 {
hasso6452df02004-08-15 05:52:07 +0000518 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000519 zlog_debug ("Add request (No database copy)");
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000520 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso6452df02004-08-15 05:52:07 +0000521 }
522 else if (ospf6_lsa_compare (his, mine) < 0)
523 {
524 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000525 zlog_debug ("Add request (Received MoreRecent)");
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000526 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso508e53e2004-05-18 18:57:06 +0000527 }
528 else
hasso6452df02004-08-15 05:52:07 +0000529 {
530 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000531 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000532 }
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000533 ospf6_lsa_delete (his);
hasso508e53e2004-05-18 18:57:06 +0000534 }
535
Denis Ovsienkofa079662011-10-08 17:22:45 +0400536 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000537
538 /* Increment sequence number */
539 on->dbdesc_seqnum ++;
540
541 /* schedule send lsreq */
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000542 if (on->request_list->count && (on->thread_send_lsreq == NULL))
hasso508e53e2004-05-18 18:57:06 +0000543 on->thread_send_lsreq =
544 thread_add_event (master, ospf6_lsreq_send, on, 0);
545
546 THREAD_OFF (on->thread_send_dbdesc);
547
548 /* More bit check */
549 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
550 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
551 thread_add_event (master, exchange_done, on, 0);
552 else
553 on->thread_send_dbdesc =
554 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
555
556 /* save last received dbdesc */
557 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
558}
559
560static void
561ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
562 struct ospf6_neighbor *on)
563{
564 struct ospf6_dbdesc *dbdesc;
565 char *p;
566
567 dbdesc = (struct ospf6_dbdesc *)
568 ((caddr_t) oh + sizeof (struct ospf6_header));
569
570 if (on->state < OSPF6_NEIGHBOR_INIT)
571 {
572 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000573 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000574 return;
575 }
576
hasso508e53e2004-05-18 18:57:06 +0000577 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000578 {
hasso508e53e2004-05-18 18:57:06 +0000579 case OSPF6_NEIGHBOR_TWOWAY:
580 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000581 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000582 return;
583
584 case OSPF6_NEIGHBOR_INIT:
585 thread_execute (master, twoway_received, on, 0);
586 if (on->state != OSPF6_NEIGHBOR_EXSTART)
587 {
588 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000589 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000590 return;
591 }
592 /* else fall through to ExStart */
593
594 case OSPF6_NEIGHBOR_EXSTART:
595 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
596 and process LSA Headers. Otherwise, ignore this message */
597 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
598 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
599 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
600 ntohs (oh->length) == sizeof (struct ospf6_header) +
601 sizeof (struct ospf6_dbdesc))
602 {
603 /* set the master/slave bit to slave */
604 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
605
606 /* set the DD sequence number to one specified by master */
607 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
608
609 /* schedule NegotiationDone */
610 thread_execute (master, negotiation_done, on, 0);
611
612 /* Record neighbor options */
613 memcpy (on->options, dbdesc->options, sizeof (on->options));
614 }
615 else
616 {
617 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000618 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000619 return;
620 }
621 break;
622
623 case OSPF6_NEIGHBOR_EXCHANGE:
624 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
625 {
626 /* Duplicated DatabaseDescription causes slave to retransmit */
627 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000628 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000629 THREAD_OFF (on->thread_send_dbdesc);
630 on->thread_send_dbdesc =
631 thread_add_event (master, ospf6_dbdesc_send, on, 0);
632 return;
633 }
634
635 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
636 {
637 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000638 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000639 thread_add_event (master, seqnumber_mismatch, on, 0);
640 return;
641 }
642
643 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
644 {
645 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000646 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000647 thread_add_event (master, seqnumber_mismatch, on, 0);
648 return;
649 }
650
651 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
652 {
653 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000654 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000655 thread_add_event (master, seqnumber_mismatch, on, 0);
656 return;
657 }
658
659 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
660 {
661 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000662 zlog_debug ("Sequence number mismatch (%#lx expected)",
663 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000664 thread_add_event (master, seqnumber_mismatch, on, 0);
665 return;
666 }
667 break;
668
669 case OSPF6_NEIGHBOR_LOADING:
670 case OSPF6_NEIGHBOR_FULL:
671 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
672 {
673 /* Duplicated DatabaseDescription causes slave to retransmit */
674 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000675 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000676 THREAD_OFF (on->thread_send_dbdesc);
677 on->thread_send_dbdesc =
678 thread_add_event (master, ospf6_dbdesc_send, on, 0);
679 return;
680 }
681
682 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000683 zlog_debug ("Not duplicate dbdesc in state %s",
684 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000685 thread_add_event (master, seqnumber_mismatch, on, 0);
686 return;
687
688 default:
689 assert (0);
690 break;
paul718e3742002-12-13 20:15:29 +0000691 }
692
hasso508e53e2004-05-18 18:57:06 +0000693 /* Process LSA headers */
694 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
695 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
696 p += sizeof (struct ospf6_lsa_header))
697 {
698 struct ospf6_lsa *his, *mine;
699 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000700
hasso508e53e2004-05-18 18:57:06 +0000701 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000702
703 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000704 {
hasso6452df02004-08-15 05:52:07 +0000705 case OSPF6_SCOPE_LINKLOCAL:
706 lsdb = on->ospf6_if->lsdb;
707 break;
708 case OSPF6_SCOPE_AREA:
709 lsdb = on->ospf6_if->area->lsdb;
710 break;
711 case OSPF6_SCOPE_AS:
712 lsdb = on->ospf6_if->area->ospf6->lsdb;
713 break;
714 case OSPF6_SCOPE_RESERVED:
715 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000716 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000717 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000718 continue;
719 break;
hasso508e53e2004-05-18 18:57:06 +0000720 }
721
hasso6452df02004-08-15 05:52:07 +0000722 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
723 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000724 {
725 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000726 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000727 ospf6_lsa_delete (his);
728 thread_add_event (master, seqnumber_mismatch, on, 0);
729 return;
730 }
731
732 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
733 his->header->adv_router, lsdb);
734 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
735 {
hasso6452df02004-08-15 05:52:07 +0000736 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000737 zlog_debug ("Add request-list: %s", his->name);
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000738 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
hasso508e53e2004-05-18 18:57:06 +0000739 }
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000740 ospf6_lsa_delete (his);
hasso508e53e2004-05-18 18:57:06 +0000741 }
742
Denis Ovsienkofa079662011-10-08 17:22:45 +0400743 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000744
745 /* Set sequence number to Master's */
746 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
747
748 /* schedule send lsreq */
Dinesh Dutteb82e9e2013-08-24 07:55:07 +0000749 if ((on->thread_send_lsreq == NULL) &&
750 (on->request_list->count))
hasso508e53e2004-05-18 18:57:06 +0000751 on->thread_send_lsreq =
752 thread_add_event (master, ospf6_lsreq_send, on, 0);
753
754 THREAD_OFF (on->thread_send_dbdesc);
755 on->thread_send_dbdesc =
756 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
757
758 /* save last received dbdesc */
759 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000760}
761
Paul Jakma6ac29a52008-08-15 13:45:30 +0100762static void
hasso508e53e2004-05-18 18:57:06 +0000763ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
764 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000765{
hasso508e53e2004-05-18 18:57:06 +0000766 struct ospf6_neighbor *on;
767 struct ospf6_dbdesc *dbdesc;
768
hasso508e53e2004-05-18 18:57:06 +0000769 on = ospf6_neighbor_lookup (oh->router_id, oi);
770 if (on == NULL)
771 {
772 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000773 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000774 return;
775 }
776
hasso508e53e2004-05-18 18:57:06 +0000777 dbdesc = (struct ospf6_dbdesc *)
778 ((caddr_t) oh + sizeof (struct ospf6_header));
779
780 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400781 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000782 {
783 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000784 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000785 return;
786 }
787
788 if (dbdesc->reserved1 || dbdesc->reserved2)
789 {
790 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000791 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
792 on->name);
hasso508e53e2004-05-18 18:57:06 +0000793 dbdesc->reserved1 = 0;
794 dbdesc->reserved2 = 0;
795 }
796
797 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
798 ospf6_dbdesc_recv_master (oh, on);
799 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
800 ospf6_dbdesc_recv_slave (oh, on);
801 else
802 {
803 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000804 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000805 }
806}
807
Paul Jakma6ac29a52008-08-15 13:45:30 +0100808static void
hasso508e53e2004-05-18 18:57:06 +0000809ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
810 struct ospf6_interface *oi, struct ospf6_header *oh)
811{
812 struct ospf6_neighbor *on;
813 char *p;
814 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000815 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000816 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000817
hasso508e53e2004-05-18 18:57:06 +0000818 on = ospf6_neighbor_lookup (oh->router_id, oi);
819 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000820 {
hasso508e53e2004-05-18 18:57:06 +0000821 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000822 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000823 return;
824 }
825
hasso508e53e2004-05-18 18:57:06 +0000826 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
827 on->state != OSPF6_NEIGHBOR_LOADING &&
828 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000829 {
hasso508e53e2004-05-18 18:57:06 +0000830 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000831 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000832 return;
833 }
834
hasso508e53e2004-05-18 18:57:06 +0000835 /* Process each request */
836 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
837 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
838 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000839 {
hasso508e53e2004-05-18 18:57:06 +0000840 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000841
842 switch (OSPF6_LSA_SCOPE (e->type))
843 {
844 case OSPF6_SCOPE_LINKLOCAL:
845 lsdb = on->ospf6_if->lsdb;
846 break;
847 case OSPF6_SCOPE_AREA:
848 lsdb = on->ospf6_if->area->lsdb;
849 break;
850 case OSPF6_SCOPE_AS:
851 lsdb = on->ospf6_if->area->ospf6->lsdb;
852 break;
853 default:
854 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000855 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000856 continue;
857 break;
858 }
paul718e3742002-12-13 20:15:29 +0000859
hasso508e53e2004-05-18 18:57:06 +0000860 /* Find database copy */
861 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
862 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000863 {
hasso508e53e2004-05-18 18:57:06 +0000864 char id[16], adv_router[16];
865 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
866 {
867 inet_ntop (AF_INET, &e->id, id, sizeof (id));
868 inet_ntop (AF_INET, &e->adv_router, adv_router,
869 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000870 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
871 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000872 }
873 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000874 return;
875 }
876
hasso508e53e2004-05-18 18:57:06 +0000877 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000878 }
879
Denis Ovsienkofa079662011-10-08 17:22:45 +0400880 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000881
hasso508e53e2004-05-18 18:57:06 +0000882 /* schedule send lsupdate */
883 THREAD_OFF (on->thread_send_lsupdate);
884 on->thread_send_lsupdate =
885 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000886}
887
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400888/* Verify, that the specified memory area contains exactly N valid IPv6
889 prefixes as specified by RFC5340, A.4.1. */
890static unsigned
891ospf6_prefixes_examin
892(
893 struct ospf6_prefix *current, /* start of buffer */
894 unsigned length,
895 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
896)
897{
898 u_char requested_pfx_bytes;
899 u_int32_t real_num_pfxs = 0;
900
901 while (length)
902 {
903 if (length < OSPF6_PREFIX_MIN_SIZE)
904 {
905 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
906 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
907 return MSG_NG;
908 }
909 /* safe to look deeper */
910 if (current->prefix_length > IPV6_MAX_BITLEN)
911 {
912 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
913 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
914 return MSG_NG;
915 }
916 /* covers both fixed- and variable-sized fields */
917 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
918 if (requested_pfx_bytes > length)
919 {
920 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
921 zlog_debug ("%s: undersized IPv6 prefix", __func__);
922 return MSG_NG;
923 }
924 /* next prefix */
925 length -= requested_pfx_bytes;
926 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
927 real_num_pfxs++;
928 }
929 if (real_num_pfxs != req_num_pfxs)
930 {
931 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
932 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
933 __func__, req_num_pfxs, real_num_pfxs);
934 return MSG_NG;
935 }
936 return MSG_OK;
937}
938
939/* Verify an LSA to have a valid length and dispatch further (where
940 appropriate) to check if the contents, including nested IPv6 prefixes,
941 is properly sized/aligned within the LSA. Note that this function gets
942 LSA type in network byte order, uses in host byte order and passes to
943 ospf6_lstype_name() in network byte order again. */
944static unsigned
945ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
946{
947 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
948 struct ospf6_as_external_lsa *as_external_lsa;
949 struct ospf6_link_lsa *link_lsa;
950 unsigned exp_length;
951 u_int8_t ltindex;
952 u_int16_t lsatype;
953
954 /* In case an additional minimum length constraint is defined for current
955 LSA type, make sure that this constraint is met. */
956 lsatype = ntohs (lsah->type);
957 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
958 if
959 (
960 ltindex < OSPF6_LSTYPE_SIZE &&
961 ospf6_lsa_minlen[ltindex] &&
962 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
963 )
964 {
965 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
966 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
967 return MSG_NG;
968 }
969 switch (lsatype)
970 {
971 case OSPF6_LSTYPE_ROUTER:
972 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
973 by N>=0 interface descriptions. */
974 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
975 {
976 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
977 zlog_debug ("%s: interface description alignment error", __func__);
978 return MSG_NG;
979 }
980 break;
981 case OSPF6_LSTYPE_NETWORK:
982 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
983 followed by N>=0 attached router descriptions. */
984 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
985 {
986 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
987 zlog_debug ("%s: router description alignment error", __func__);
988 return MSG_NG;
989 }
990 break;
991 case OSPF6_LSTYPE_INTER_PREFIX:
992 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
993 followed by 3-4 fields of a single IPv6 prefix. */
994 if (headeronly)
995 break;
996 return ospf6_prefixes_examin
997 (
998 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
999 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1000 1
1001 );
1002 case OSPF6_LSTYPE_INTER_ROUTER:
1003 /* RFC5340 A.4.6, fixed-size LSA. */
1004 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1005 {
1006 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1007 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1008 return MSG_NG;
1009 }
1010 break;
1011 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1012 case OSPF6_LSTYPE_TYPE_7:
1013 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1014 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1015 16 bytes of forwarding address, 4 bytes of external route tag,
1016 4 bytes of referenced link state ID. */
1017 if (headeronly)
1018 break;
1019 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1020 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1021 /* To find out if the last optional field (Referenced Link State ID) is
1022 assumed in this LSA, we need to access fixed fields of the IPv6
1023 prefix before ospf6_prefix_examin() confirms its sizing. */
1024 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1025 {
1026 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1027 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1028 return MSG_NG;
1029 }
1030 /* forwarding address */
1031 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1032 exp_length += 16;
1033 /* external route tag */
1034 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1035 exp_length += 4;
1036 /* referenced link state ID */
1037 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1038 exp_length += 4;
1039 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1040 this check does not include any IPv6 prefix fields. */
1041 if (exp_length > lsalen)
1042 {
1043 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1044 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1045 return MSG_NG;
1046 }
1047 /* The last call completely covers the remainder (IPv6 prefix). */
1048 return ospf6_prefixes_examin
1049 (
1050 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1051 lsalen - exp_length,
1052 1
1053 );
1054 case OSPF6_LSTYPE_LINK:
1055 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1056 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1057 if (headeronly)
1058 break;
1059 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1060 return ospf6_prefixes_examin
1061 (
1062 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1063 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1064 ntohl (link_lsa->prefix_num) /* 32 bits */
1065 );
1066 case OSPF6_LSTYPE_INTRA_PREFIX:
1067 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1068 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1069 if (headeronly)
1070 break;
1071 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1072 return ospf6_prefixes_examin
1073 (
1074 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1075 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1076 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1077 );
1078 }
1079 /* No additional validation is possible for unknown LSA types, which are
1080 themselves valid in OPSFv3, hence the default decision is to accept. */
1081 return MSG_OK;
1082}
1083
1084/* Verify if the provided input buffer is a valid sequence of LSAs. This
1085 includes verification of LSA blocks length/alignment and dispatching
1086 of deeper-level checks. */
1087static unsigned
1088ospf6_lsaseq_examin
1089(
1090 struct ospf6_lsa_header *lsah, /* start of buffered data */
1091 size_t length,
1092 const u_char headeronly,
1093 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1094 and treat the difference as an error. */
1095 const u_int32_t declared_num_lsas
1096)
1097{
1098 u_int32_t counted_lsas = 0;
1099
1100 while (length)
1101 {
1102 u_int16_t lsalen;
1103 if (length < OSPF6_LSA_HEADER_SIZE)
1104 {
1105 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001106 zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001107 __func__, length, counted_lsas);
1108 return MSG_NG;
1109 }
1110 /* save on ntohs() calls here and in the LSA validator */
1111 lsalen = OSPF6_LSA_SIZE (lsah);
1112 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1113 {
1114 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1115 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1116 __func__, counted_lsas, lsalen);
1117 return MSG_NG;
1118 }
1119 if (headeronly)
1120 {
1121 /* less checks here and in ospf6_lsa_examin() */
1122 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1123 {
1124 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1125 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1126 ospf6_lstype_name (lsah->type), counted_lsas);
1127 return MSG_NG;
1128 }
1129 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1130 length -= OSPF6_LSA_HEADER_SIZE;
1131 }
1132 else
1133 {
1134 /* make sure the input buffer is deep enough before further checks */
1135 if (lsalen > length)
1136 {
1137 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001138 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001139 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1140 return MSG_NG;
1141 }
1142 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1143 {
1144 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1145 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1146 ospf6_lstype_name (lsah->type), counted_lsas);
1147 return MSG_NG;
1148 }
1149 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1150 length -= lsalen;
1151 }
1152 counted_lsas++;
1153 }
1154
1155 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1156 {
1157 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1158 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1159 __func__, declared_num_lsas, counted_lsas);
1160 return MSG_NG;
1161 }
1162 return MSG_OK;
1163}
1164
1165/* Verify a complete OSPF packet for proper sizing/alignment. */
1166static unsigned
1167ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1168{
1169 struct ospf6_lsupdate *lsupd;
1170 unsigned test;
1171
1172 /* length, 1st approximation */
1173 if (bytesonwire < OSPF6_HEADER_SIZE)
1174 {
1175 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1176 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1177 return MSG_NG;
1178 }
1179 /* Now it is safe to access header fields. */
1180 if (bytesonwire != ntohs (oh->length))
1181 {
1182 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1183 zlog_debug ("%s: packet length error (%u real, %u declared)",
1184 __func__, bytesonwire, ntohs (oh->length));
1185 return MSG_NG;
1186 }
1187 /* version check */
1188 if (oh->version != OSPFV3_VERSION)
1189 {
1190 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1191 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1192 return MSG_NG;
1193 }
1194 /* length, 2nd approximation */
1195 if
1196 (
1197 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1198 ospf6_packet_minlen[oh->type] &&
1199 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1200 )
1201 {
1202 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1203 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001204 bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001205 return MSG_NG;
1206 }
1207 /* type-specific deeper validation */
1208 switch (oh->type)
1209 {
1210 case OSPF6_MESSAGE_TYPE_HELLO:
1211 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1212 by N>=0 router-IDs. */
1213 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1214 return MSG_OK;
1215 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1216 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001217 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001218 return MSG_NG;
1219 case OSPF6_MESSAGE_TYPE_DBDESC:
1220 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1221 by N>=0 header-only LSAs. */
1222 test = ospf6_lsaseq_examin
1223 (
1224 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1225 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1226 1,
1227 0
1228 );
1229 break;
1230 case OSPF6_MESSAGE_TYPE_LSREQ:
1231 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1232 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1233 return MSG_OK;
1234 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1235 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001236 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001237 return MSG_NG;
1238 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1239 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1240 by N>=0 full LSAs (with N declared beforehand). */
1241 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1242 test = ospf6_lsaseq_examin
1243 (
1244 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1245 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1246 0,
1247 ntohl (lsupd->lsa_number) /* 32 bits */
1248 );
1249 break;
1250 case OSPF6_MESSAGE_TYPE_LSACK:
1251 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1252 test = ospf6_lsaseq_examin
1253 (
1254 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1255 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1256 1,
1257 0
1258 );
1259 break;
1260 default:
1261 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1262 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1263 return MSG_NG;
1264 }
1265 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001266 zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001267 return test;
1268}
1269
1270/* Verify particular fields of otherwise correct received OSPF packet to
1271 meet the requirements of RFC. */
1272static int
1273ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1274{
1275 char buf[2][INET_ADDRSTRLEN];
1276
1277 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1278 return MSG_NG;
1279
1280 /* Area-ID check */
1281 if (oh->area_id != oi->area->area_id)
1282 {
1283 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1284 {
Dinesh Dutt8551e6d2013-10-22 17:42:18 -07001285 if (oh->area_id == OSPF_AREA_BACKBONE)
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001286 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1287 else
1288 zlog_debug
1289 (
1290 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1291 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1292 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1293 );
1294 }
1295 return MSG_NG;
1296 }
1297
1298 /* Instance-ID check */
1299 if (oh->instance_id != oi->instance_id)
1300 {
1301 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1302 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1303 return MSG_NG;
1304 }
1305
1306 /* Router-ID check */
1307 if (oh->router_id == oi->area->ospf6->router_id)
1308 {
1309 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1310 return MSG_NG;
1311 }
1312 return MSG_OK;
1313}
1314
Paul Jakma6ac29a52008-08-15 13:45:30 +01001315static void
hasso508e53e2004-05-18 18:57:06 +00001316ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1317 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001318{
hasso508e53e2004-05-18 18:57:06 +00001319 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001320 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001321 char *p;
paul718e3742002-12-13 20:15:29 +00001322
hasso508e53e2004-05-18 18:57:06 +00001323 on = ospf6_neighbor_lookup (oh->router_id, oi);
1324 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001325 {
hasso508e53e2004-05-18 18:57:06 +00001326 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001327 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001328 return;
1329 }
1330
hasso508e53e2004-05-18 18:57:06 +00001331 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1332 on->state != OSPF6_NEIGHBOR_LOADING &&
1333 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001334 {
hasso508e53e2004-05-18 18:57:06 +00001335 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001336 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001337 return;
1338 }
1339
hasso508e53e2004-05-18 18:57:06 +00001340 lsupdate = (struct ospf6_lsupdate *)
1341 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001342
hasso508e53e2004-05-18 18:57:06 +00001343 /* Process LSAs */
1344 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1345 p < OSPF6_MESSAGE_END (oh) &&
1346 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1347 p += OSPF6_LSA_SIZE (p))
1348 {
hasso6452df02004-08-15 05:52:07 +00001349 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001350 }
1351
Denis Ovsienkofa079662011-10-08 17:22:45 +04001352 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001353
paul718e3742002-12-13 20:15:29 +00001354}
1355
Paul Jakma6ac29a52008-08-15 13:45:30 +01001356static void
hasso508e53e2004-05-18 18:57:06 +00001357ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1358 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001359{
hasso508e53e2004-05-18 18:57:06 +00001360 struct ospf6_neighbor *on;
1361 char *p;
1362 struct ospf6_lsa *his, *mine;
1363 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001364
hasso508e53e2004-05-18 18:57:06 +00001365 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001366
hasso508e53e2004-05-18 18:57:06 +00001367 on = ospf6_neighbor_lookup (oh->router_id, oi);
1368 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001369 {
hasso508e53e2004-05-18 18:57:06 +00001370 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001371 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001372 return;
1373 }
1374
hasso508e53e2004-05-18 18:57:06 +00001375 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1376 on->state != OSPF6_NEIGHBOR_LOADING &&
1377 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001378 {
hasso508e53e2004-05-18 18:57:06 +00001379 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001380 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001381 return;
1382 }
1383
hasso508e53e2004-05-18 18:57:06 +00001384 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1385 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1386 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001387 {
hasso508e53e2004-05-18 18:57:06 +00001388 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001389
hasso6452df02004-08-15 05:52:07 +00001390 switch (OSPF6_LSA_SCOPE (his->header->type))
1391 {
1392 case OSPF6_SCOPE_LINKLOCAL:
1393 lsdb = on->ospf6_if->lsdb;
1394 break;
1395 case OSPF6_SCOPE_AREA:
1396 lsdb = on->ospf6_if->area->lsdb;
1397 break;
1398 case OSPF6_SCOPE_AS:
1399 lsdb = on->ospf6_if->area->ospf6->lsdb;
1400 break;
1401 case OSPF6_SCOPE_RESERVED:
1402 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001403 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001404 ospf6_lsa_delete (his);
1405 continue;
1406 break;
1407 }
1408
1409 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001410 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001411
1412 /* Find database copy */
1413 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1414 his->header->adv_router, lsdb);
1415 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001416 {
hasso508e53e2004-05-18 18:57:06 +00001417 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001418 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001419 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001420 continue;
1421 }
1422
hasso508e53e2004-05-18 18:57:06 +00001423 /* Check if the LSA is on his retrans-list */
1424 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1425 his->header->adv_router, on->retrans_list);
1426 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001427 {
hasso508e53e2004-05-18 18:57:06 +00001428 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001429 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001430 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001431 continue;
1432 }
1433
hasso508e53e2004-05-18 18:57:06 +00001434 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001435 {
hasso508e53e2004-05-18 18:57:06 +00001436 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001437 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001438 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001439 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001440 ospf6_lsa_delete (his);
1441 continue;
paul718e3742002-12-13 20:15:29 +00001442 }
1443
hasso6452df02004-08-15 05:52:07 +00001444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001445 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1446 on->name);
hasso508e53e2004-05-18 18:57:06 +00001447
Paul Jakma932bf192006-05-15 10:42:24 +00001448 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001449 if (OSPF6_LSA_IS_MAXAGE (mine))
1450 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001451 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001452 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001453 }
1454
Denis Ovsienkofa079662011-10-08 17:22:45 +04001455 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001456}
1457
Paul Jakma6ac29a52008-08-15 13:45:30 +01001458static u_char *recvbuf = NULL;
1459static u_char *sendbuf = NULL;
1460static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001461
1462int
paul0c083ee2004-10-10 12:54:58 +00001463ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001464{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001465 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001466
1467 if (size <= iobuflen)
1468 return iobuflen;
1469
1470 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1471 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1472 if (recvnew == NULL || sendnew == NULL)
1473 {
hassob596c712004-07-09 18:33:43 +00001474 if (recvnew)
1475 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1476 if (sendnew)
1477 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001478 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001479 return iobuflen;
1480 }
1481
1482 if (recvbuf)
1483 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1484 if (sendbuf)
1485 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1486 recvbuf = recvnew;
1487 sendbuf = sendnew;
1488 iobuflen = size;
1489
1490 return iobuflen;
1491}
paul718e3742002-12-13 20:15:29 +00001492
Tom Goffae2254a2010-11-10 13:01:41 -08001493void
1494ospf6_message_terminate (void)
1495{
1496 if (recvbuf)
1497 {
1498 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1499 recvbuf = NULL;
1500 }
1501
1502 if (sendbuf)
1503 {
1504 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1505 sendbuf = NULL;
1506 }
1507
1508 iobuflen = 0;
1509}
1510
paul718e3742002-12-13 20:15:29 +00001511int
1512ospf6_receive (struct thread *thread)
1513{
paul0c083ee2004-10-10 12:54:58 +00001514 int sockfd;
1515 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001516 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001517 struct in6_addr src, dst;
1518 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001519 struct iovec iovector[2];
1520 struct ospf6_interface *oi;
1521 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001522
1523 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001524 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001525 thread_add_read (master, ospf6_receive, NULL, sockfd);
1526
1527 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001528 memset (&src, 0, sizeof (src));
1529 memset (&dst, 0, sizeof (dst));
1530 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001531 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001532 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001533 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001534 iovector[1].iov_base = NULL;
1535 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001536
1537 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001538 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001539 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001540 {
hasso508e53e2004-05-18 18:57:06 +00001541 zlog_err ("Excess message read");
1542 return 0;
1543 }
paul718e3742002-12-13 20:15:29 +00001544
hasso508e53e2004-05-18 18:57:06 +00001545 oi = ospf6_interface_lookup_by_ifindex (ifindex);
Christian Franked9628722013-03-08 21:47:35 +01001546 if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
hasso508e53e2004-05-18 18:57:06 +00001547 {
hassoc6487d62004-12-24 06:00:11 +00001548 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001549 return 0;
1550 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001551 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1552 {
1553 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1554 zlog_debug ("%s: Ignore message on passive interface %s",
1555 __func__, oi->interface->name);
1556 return 0;
1557 }
hasso508e53e2004-05-18 18:57:06 +00001558
1559 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001560 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1561 return 0;
1562
1563 /* Being here means, that no sizing/alignment issues were detected in
1564 the input packet. This renders the additional checks performed below
1565 and also in the type-specific dispatching functions a dead code,
1566 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001567
1568 /* Log */
1569 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1570 {
1571 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1572 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001573 zlog_debug ("%s received on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001574 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001575 zlog_debug (" src: %s", srcname);
1576 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001577
1578 switch (oh->type)
1579 {
1580 case OSPF6_MESSAGE_TYPE_HELLO:
1581 ospf6_hello_print (oh);
1582 break;
1583 case OSPF6_MESSAGE_TYPE_DBDESC:
1584 ospf6_dbdesc_print (oh);
1585 break;
1586 case OSPF6_MESSAGE_TYPE_LSREQ:
1587 ospf6_lsreq_print (oh);
1588 break;
1589 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1590 ospf6_lsupdate_print (oh);
1591 break;
1592 case OSPF6_MESSAGE_TYPE_LSACK:
1593 ospf6_lsack_print (oh);
1594 break;
1595 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001596 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001597 }
1598 }
1599
hasso508e53e2004-05-18 18:57:06 +00001600 switch (oh->type)
1601 {
1602 case OSPF6_MESSAGE_TYPE_HELLO:
1603 ospf6_hello_recv (&src, &dst, oi, oh);
1604 break;
1605
1606 case OSPF6_MESSAGE_TYPE_DBDESC:
1607 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1608 break;
1609
1610 case OSPF6_MESSAGE_TYPE_LSREQ:
1611 ospf6_lsreq_recv (&src, &dst, oi, oh);
1612 break;
1613
1614 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1615 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1616 break;
1617
1618 case OSPF6_MESSAGE_TYPE_LSACK:
1619 ospf6_lsack_recv (&src, &dst, oi, oh);
1620 break;
1621
1622 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001623 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001624 }
1625
1626 return 0;
1627}
1628
Paul Jakma6ac29a52008-08-15 13:45:30 +01001629static void
hasso508e53e2004-05-18 18:57:06 +00001630ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1631 struct ospf6_interface *oi, struct ospf6_header *oh)
1632{
1633 int len;
1634 char srcname[64], dstname[64];
1635 struct iovec iovector[2];
1636
1637 /* initialize */
1638 iovector[0].iov_base = (caddr_t) oh;
1639 iovector[0].iov_len = ntohs (oh->length);
1640 iovector[1].iov_base = NULL;
1641 iovector[1].iov_len = 0;
1642
1643 /* fill OSPF header */
1644 oh->version = OSPFV3_VERSION;
1645 /* message type must be set before */
1646 /* message length must be set before */
1647 oh->router_id = oi->area->ospf6->router_id;
1648 oh->area_id = oi->area->area_id;
1649 /* checksum is calculated by kernel */
1650 oh->instance_id = oi->instance_id;
1651 oh->reserved = 0;
1652
1653 /* Log */
1654 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1655 {
1656 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1657 if (src)
1658 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1659 else
1660 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001661 zlog_debug ("%s send on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001662 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001663 zlog_debug (" src: %s", srcname);
1664 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001665
1666 switch (oh->type)
1667 {
1668 case OSPF6_MESSAGE_TYPE_HELLO:
1669 ospf6_hello_print (oh);
1670 break;
1671 case OSPF6_MESSAGE_TYPE_DBDESC:
1672 ospf6_dbdesc_print (oh);
1673 break;
1674 case OSPF6_MESSAGE_TYPE_LSREQ:
1675 ospf6_lsreq_print (oh);
1676 break;
1677 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1678 ospf6_lsupdate_print (oh);
1679 break;
1680 case OSPF6_MESSAGE_TYPE_LSACK:
1681 ospf6_lsack_print (oh);
1682 break;
1683 default:
hassoc6487d62004-12-24 06:00:11 +00001684 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001685 assert (0);
1686 break;
1687 }
1688 }
1689
1690 /* send message */
1691 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1692 if (len != ntohs (oh->length))
1693 zlog_err ("Could not send entire message");
1694}
1695
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001696static uint32_t
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001697ospf6_packet_max(struct ospf6_interface *oi)
1698{
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001699 assert (oi->ifmtu > sizeof (struct ip6_hdr));
1700 return oi->ifmtu - (sizeof (struct ip6_hdr));
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001701}
1702
hasso508e53e2004-05-18 18:57:06 +00001703int
1704ospf6_hello_send (struct thread *thread)
1705{
1706 struct ospf6_interface *oi;
1707 struct ospf6_header *oh;
1708 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001709 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001710 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001711 struct ospf6_neighbor *on;
1712
1713 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1714 oi->thread_send_hello = (struct thread *) NULL;
1715
1716 if (oi->state <= OSPF6_INTERFACE_DOWN)
1717 {
1718 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001719 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001720 oi->interface->name);
1721 return 0;
1722 }
1723
1724 /* set next thread */
1725 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1726 oi, oi->hello_interval);
1727
hasso3b4cd3a2004-05-18 19:28:32 +00001728 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001729 oh = (struct ospf6_header *) sendbuf;
1730 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1731
1732 hello->interface_id = htonl (oi->interface->ifindex);
1733 hello->priority = oi->priority;
1734 hello->options[0] = oi->area->options[0];
1735 hello->options[1] = oi->area->options[1];
1736 hello->options[2] = oi->area->options[2];
1737 hello->hello_interval = htons (oi->hello_interval);
1738 hello->dead_interval = htons (oi->dead_interval);
1739 hello->drouter = oi->drouter;
1740 hello->bdrouter = oi->bdrouter;
1741
Paul Jakma6ac29a52008-08-15 13:45:30 +01001742 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001743
paul1eb8ef22005-04-07 07:30:20 +00001744 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001745 {
hasso508e53e2004-05-18 18:57:06 +00001746 if (on->state < OSPF6_NEIGHBOR_INIT)
1747 continue;
1748
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001749 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001750 {
1751 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001752 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001753 break;
1754 }
1755
1756 memcpy (p, &on->router_id, sizeof (u_int32_t));
1757 p += sizeof (u_int32_t);
1758 }
1759
1760 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1761 oh->length = htons (p - sendbuf);
1762
1763 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1764 return 0;
1765}
1766
1767int
1768ospf6_dbdesc_send (struct thread *thread)
1769{
1770 struct ospf6_neighbor *on;
1771 struct ospf6_header *oh;
1772 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001773 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001774 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00001775 struct in6_addr *dst;
hasso508e53e2004-05-18 18:57:06 +00001776
1777 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1778 on->thread_send_dbdesc = (struct thread *) NULL;
1779
1780 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1781 {
1782 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001783 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1784 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001785 return 0;
1786 }
1787
1788 /* set next thread if master */
1789 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1790 on->thread_send_dbdesc =
1791 thread_add_timer (master, ospf6_dbdesc_send, on,
1792 on->ospf6_if->rxmt_interval);
1793
hasso3b4cd3a2004-05-18 19:28:32 +00001794 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001795 oh = (struct ospf6_header *) sendbuf;
1796 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1797 sizeof (struct ospf6_header));
1798
1799 /* if this is initial one, initialize sequence number for DbDesc */
Dinesh Dutt7a10a352013-08-25 03:03:07 +00001800 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
1801 (on->dbdesc_seqnum == 0))
hasso508e53e2004-05-18 18:57:06 +00001802 {
1803 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001804 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001805 tv.tv_sec = 1;
1806 on->dbdesc_seqnum = tv.tv_sec;
1807 }
1808
1809 dbdesc->options[0] = on->ospf6_if->area->options[0];
1810 dbdesc->options[1] = on->ospf6_if->area->options[1];
1811 dbdesc->options[2] = on->ospf6_if->area->options[2];
1812 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1813 dbdesc->bits = on->dbdesc_bits;
1814 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1815
1816 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001817 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001818 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1819 {
1820 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1821 lsa = ospf6_lsdb_next (lsa))
1822 {
1823 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1824
1825 /* MTU check */
1826 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001827 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001828 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001829 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001830 break;
1831 }
1832 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1833 p += sizeof (struct ospf6_lsa_header);
1834 }
1835 }
1836
1837 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1838 oh->length = htons (p - sendbuf);
1839
Dinesh Duttc5926a92013-08-24 07:55:00 +00001840
1841 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1842 dst = &allspfrouters6;
1843 else
1844 dst = &on->linklocal_addr;
1845
1846 ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
1847
hasso508e53e2004-05-18 18:57:06 +00001848 return 0;
1849}
1850
1851int
1852ospf6_dbdesc_send_newone (struct thread *thread)
1853{
1854 struct ospf6_neighbor *on;
1855 struct ospf6_lsa *lsa;
1856 unsigned int size = 0;
1857
1858 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001859 ospf6_lsdb_remove_all (on->dbdesc_list);
1860
1861 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1862 so that ospf6_send_dbdesc () can send those LSAs */
1863 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1864 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1865 lsa = ospf6_lsdb_next (lsa))
1866 {
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001867 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001868 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001869 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001870 break;
1871 }
1872
hasso508e53e2004-05-18 18:57:06 +00001873 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1874 ospf6_lsdb_remove (lsa, on->summary_list);
1875 size += sizeof (struct ospf6_lsa_header);
1876 }
1877
1878 if (on->summary_list->count == 0)
1879 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1880
1881 /* If slave, More bit check must be done here */
1882 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1883 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1884 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1885 thread_add_event (master, exchange_done, on, 0);
1886
1887 thread_execute (master, ospf6_dbdesc_send, on, 0);
1888 return 0;
1889}
1890
1891int
1892ospf6_lsreq_send (struct thread *thread)
1893{
1894 struct ospf6_neighbor *on;
1895 struct ospf6_header *oh;
1896 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001897 u_char *p;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001898 struct ospf6_lsa *lsa, *last_req;
hasso508e53e2004-05-18 18:57:06 +00001899
1900 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1901 on->thread_send_lsreq = (struct thread *) NULL;
1902
1903 /* LSReq will be sent only in ExStart or Loading */
1904 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1905 on->state != OSPF6_NEIGHBOR_LOADING)
1906 {
1907 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001908 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1909 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001910 return 0;
1911 }
1912
1913 /* schedule loading_done if request list is empty */
1914 if (on->request_list->count == 0)
1915 {
1916 thread_add_event (master, loading_done, on, 0);
1917 return 0;
1918 }
1919
hasso3b4cd3a2004-05-18 19:28:32 +00001920 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001921 oh = (struct ospf6_header *) sendbuf;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001922 last_req = NULL;
hasso508e53e2004-05-18 18:57:06 +00001923
1924 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001925 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001926 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1927 lsa = ospf6_lsdb_next (lsa))
1928 {
1929 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001930 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001931 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001932 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001933 break;
1934 }
1935
1936 e = (struct ospf6_lsreq_entry *) p;
1937 e->type = lsa->header->type;
1938 e->id = lsa->header->id;
1939 e->adv_router = lsa->header->adv_router;
1940 p += sizeof (struct ospf6_lsreq_entry);
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001941 last_req = lsa;
1942 }
1943
1944 if (last_req != NULL)
1945 {
1946 if (on->last_ls_req != NULL)
1947 {
1948 ospf6_lsa_unlock (on->last_ls_req);
1949 }
1950 ospf6_lsa_lock (last_req);
1951 on->last_ls_req = last_req;
hasso508e53e2004-05-18 18:57:06 +00001952 }
1953
1954 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1955 oh->length = htons (p - sendbuf);
1956
Dinesh Duttc5926a92013-08-24 07:55:00 +00001957 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1958 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
hasso508e53e2004-05-18 18:57:06 +00001959 on->ospf6_if, oh);
Dinesh Duttc5926a92013-08-24 07:55:00 +00001960 else
1961 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1962 on->ospf6_if, oh);
1963
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001964 /* set next thread */
1965 if (on->request_list->count != 0)
1966 {
1967 on->thread_send_lsreq =
1968 thread_add_timer (master, ospf6_lsreq_send, on,
1969 on->ospf6_if->rxmt_interval);
1970 }
1971
hasso508e53e2004-05-18 18:57:06 +00001972 return 0;
1973}
1974
1975int
1976ospf6_lsupdate_send_neighbor (struct thread *thread)
1977{
1978 struct ospf6_neighbor *on;
1979 struct ospf6_header *oh;
1980 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001981 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00001982 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00001983 struct ospf6_lsa *lsa;
1984
1985 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1986 on->thread_send_lsupdate = (struct thread *) NULL;
1987
hasso6452df02004-08-15 05:52:07 +00001988 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001989 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001990
hasso508e53e2004-05-18 18:57:06 +00001991 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1992 {
1993 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001994 zlog_debug ("Quit to send (neighbor state %s)",
1995 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001996 return 0;
1997 }
1998
hasso3b4cd3a2004-05-18 19:28:32 +00001999 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002000 oh = (struct ospf6_header *) sendbuf;
2001 lsupdate = (struct ospf6_lsupdate *)
2002 ((caddr_t) oh + sizeof (struct ospf6_header));
2003
Paul Jakma6ac29a52008-08-15 13:45:30 +01002004 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002005 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002006
2007 /* lsupdate_list lists those LSA which doesn't need to be
2008 retransmitted. remove those from the list */
2009 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2010 lsa = ospf6_lsdb_next (lsa))
2011 {
2012 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002013 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002014 > ospf6_packet_max(on->ospf6_if))
2015 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002016 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002017 break;
2018 }
hasso508e53e2004-05-18 18:57:06 +00002019
hasso508e53e2004-05-18 18:57:06 +00002020 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2021 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2022 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002023 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002024
2025 assert (lsa->lock == 2);
2026 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2027 }
2028
Dinesh Duttc5926a92013-08-24 07:55:00 +00002029 if (lsa_cnt)
2030 {
2031 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2032 oh->length = htons (p - sendbuf);
2033 lsupdate->lsa_number = htonl (lsa_cnt);
2034
2035 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2036 (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
2037 (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
2038 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2039 on->ospf6_if, oh);
2040 else
2041 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2042 on->ospf6_if, oh);
2043 }
2044
2045 /* The addresses used for retransmissions are different from those sent the
2046 first time and so we need to separate them here.
2047 */
2048 memset (sendbuf, 0, iobuflen);
2049 oh = (struct ospf6_header *) sendbuf;
2050 lsupdate = (struct ospf6_lsupdate *)
2051 ((caddr_t) oh + sizeof (struct ospf6_header));
2052 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
2053 lsa_cnt = 0;
2054
hasso508e53e2004-05-18 18:57:06 +00002055 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2056 lsa = ospf6_lsdb_next (lsa))
2057 {
2058 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002059 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002060 > ospf6_packet_max(on->ospf6_if))
2061 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002062 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002063 break;
2064 }
hasso508e53e2004-05-18 18:57:06 +00002065
hasso508e53e2004-05-18 18:57:06 +00002066 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2067 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2068 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002069 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002070 }
2071
Dinesh Duttc5926a92013-08-24 07:55:00 +00002072 if (lsa_cnt)
hasso508e53e2004-05-18 18:57:06 +00002073 {
Dinesh Duttc5926a92013-08-24 07:55:00 +00002074 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2075 oh->length = htons (p - sendbuf);
2076 lsupdate->lsa_number = htonl (lsa_cnt);
2077
2078 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2079 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2080 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002081 else
Dinesh Duttc5926a92013-08-24 07:55:00 +00002082 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2083 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002084 }
2085
Dinesh Duttc5926a92013-08-24 07:55:00 +00002086 if (on->lsupdate_list->count != 0)
2087 on->thread_send_lsupdate =
2088 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2089 else if (on->retrans_list->count != 0)
2090 on->thread_send_lsupdate =
2091 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2092 on->ospf6_if->rxmt_interval);
hasso508e53e2004-05-18 18:57:06 +00002093 return 0;
2094}
2095
2096int
2097ospf6_lsupdate_send_interface (struct thread *thread)
2098{
2099 struct ospf6_interface *oi;
2100 struct ospf6_header *oh;
2101 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002102 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002103 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00002104 struct ospf6_lsa *lsa;
2105
2106 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2107 oi->thread_send_lsupdate = (struct thread *) NULL;
2108
2109 if (oi->state <= OSPF6_INTERFACE_WAITING)
2110 {
2111 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002112 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2113 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002114 return 0;
2115 }
2116
2117 /* if we have nothing to send, return */
2118 if (oi->lsupdate_list->count == 0)
2119 return 0;
2120
hasso3b4cd3a2004-05-18 19:28:32 +00002121 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002122 oh = (struct ospf6_header *) sendbuf;
2123 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
Dinesh Duttc5926a92013-08-24 07:55:00 +00002124 sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002125
Paul Jakma6ac29a52008-08-15 13:45:30 +01002126 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002127 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002128
2129 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2130 lsa = ospf6_lsdb_next (lsa))
2131 {
2132 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002133 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002134 > ospf6_packet_max(oi))
2135 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002136 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002137 break;
2138 }
hasso508e53e2004-05-18 18:57:06 +00002139
hasso508e53e2004-05-18 18:57:06 +00002140 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2141 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2142 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002143 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002144
2145 assert (lsa->lock == 2);
2146 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2147 }
2148
Dinesh Duttc5926a92013-08-24 07:55:00 +00002149 if (lsa_cnt)
2150 {
2151 lsupdate->lsa_number = htonl (lsa_cnt);
hasso508e53e2004-05-18 18:57:06 +00002152
Dinesh Duttc5926a92013-08-24 07:55:00 +00002153 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2154 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002155
Dinesh Duttc5926a92013-08-24 07:55:00 +00002156 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2157 (oi->state == OSPF6_INTERFACE_DR) ||
2158 (oi->state == OSPF6_INTERFACE_BDR))
2159 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2160 else
2161 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2162
2163 }
hasso508e53e2004-05-18 18:57:06 +00002164
2165 if (oi->lsupdate_list->count > 0)
2166 {
2167 oi->thread_send_lsupdate =
2168 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2169 }
2170
2171 return 0;
2172}
2173
2174int
2175ospf6_lsack_send_neighbor (struct thread *thread)
2176{
2177 struct ospf6_neighbor *on;
2178 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002179 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002180 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002181 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002182
2183 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2184 on->thread_send_lsack = (struct thread *) NULL;
2185
2186 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2187 {
2188 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002189 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2190 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002191 return 0;
2192 }
2193
2194 /* if we have nothing to send, return */
2195 if (on->lsack_list->count == 0)
2196 return 0;
2197
hasso3b4cd3a2004-05-18 19:28:32 +00002198 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002199 oh = (struct ospf6_header *) sendbuf;
2200
Paul Jakma6ac29a52008-08-15 13:45:30 +01002201 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002202
2203 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2204 lsa = ospf6_lsdb_next (lsa))
2205 {
2206 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002207 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002208 {
2209 /* if we run out of packet size/space here,
2210 better to try again soon. */
2211 THREAD_OFF (on->thread_send_lsack);
2212 on->thread_send_lsack =
2213 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
hasso508e53e2004-05-18 18:57:06 +00002214
Dinesh Dutta765eb92013-08-24 07:55:14 +00002215 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002216 break;
2217 }
hasso508e53e2004-05-18 18:57:06 +00002218
2219 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2220 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2221 p += sizeof (struct ospf6_lsa_header);
2222
2223 assert (lsa->lock == 2);
2224 ospf6_lsdb_remove (lsa, on->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002225 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002226 }
2227
Dinesh Duttc5926a92013-08-24 07:55:00 +00002228 if (lsa_cnt)
2229 {
2230 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2231 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002232
Dinesh Duttc5926a92013-08-24 07:55:00 +00002233 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2234 on->ospf6_if, oh);
2235 }
2236
2237 if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
2238 {
2239 on->thread_send_lsack =
2240 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2241 }
2242
hasso508e53e2004-05-18 18:57:06 +00002243 return 0;
2244}
2245
2246int
2247ospf6_lsack_send_interface (struct thread *thread)
2248{
2249 struct ospf6_interface *oi;
2250 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002251 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002252 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002253 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002254
2255 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2256 oi->thread_send_lsack = (struct thread *) NULL;
2257
2258 if (oi->state <= OSPF6_INTERFACE_WAITING)
2259 {
2260 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002261 zlog_debug ("Quit to send LSAck to interface %s state %s",
2262 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002263 return 0;
2264 }
2265
2266 /* if we have nothing to send, return */
2267 if (oi->lsack_list->count == 0)
2268 return 0;
2269
hasso3b4cd3a2004-05-18 19:28:32 +00002270 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002271 oh = (struct ospf6_header *) sendbuf;
2272
Paul Jakma6ac29a52008-08-15 13:45:30 +01002273 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002274
2275 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2276 lsa = ospf6_lsdb_next (lsa))
2277 {
2278 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002279 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002280 {
2281 /* if we run out of packet size/space here,
2282 better to try again soon. */
2283 THREAD_OFF (oi->thread_send_lsack);
2284 oi->thread_send_lsack =
2285 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
hasso508e53e2004-05-18 18:57:06 +00002286
Dinesh Dutta765eb92013-08-24 07:55:14 +00002287 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002288 break;
2289 }
hasso508e53e2004-05-18 18:57:06 +00002290
2291 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2292 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2293 p += sizeof (struct ospf6_lsa_header);
2294
2295 assert (lsa->lock == 2);
2296 ospf6_lsdb_remove (lsa, oi->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002297 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002298 }
2299
Dinesh Duttc5926a92013-08-24 07:55:00 +00002300 if (lsa_cnt)
2301 {
2302 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2303 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002304
Dinesh Duttc5926a92013-08-24 07:55:00 +00002305 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2306 (oi->state == OSPF6_INTERFACE_DR) ||
2307 (oi->state == OSPF6_INTERFACE_BDR))
2308 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2309 else
2310 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2311 }
hasso508e53e2004-05-18 18:57:06 +00002312
2313 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2314 {
2315 oi->thread_send_lsack =
2316 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2317 }
paul718e3742002-12-13 20:15:29 +00002318
2319 return 0;
2320}
2321
2322
hasso508e53e2004-05-18 18:57:06 +00002323/* Commands */
2324DEFUN (debug_ospf6_message,
2325 debug_ospf6_message_cmd,
2326 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2327 DEBUG_STR
2328 OSPF6_STR
2329 "Debug OSPFv3 message\n"
2330 "Debug Unknown message\n"
2331 "Debug Hello message\n"
2332 "Debug Database Description message\n"
2333 "Debug Link State Request message\n"
2334 "Debug Link State Update message\n"
2335 "Debug Link State Acknowledgement message\n"
2336 "Debug All message\n"
2337 )
paul718e3742002-12-13 20:15:29 +00002338{
hasso508e53e2004-05-18 18:57:06 +00002339 unsigned char level = 0;
2340 int type = 0;
paul718e3742002-12-13 20:15:29 +00002341 int i;
2342
hasso508e53e2004-05-18 18:57:06 +00002343 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002344
hasso508e53e2004-05-18 18:57:06 +00002345 /* check type */
2346 if (! strncmp (argv[0], "u", 1))
2347 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2348 else if (! strncmp (argv[0], "h", 1))
2349 type = OSPF6_MESSAGE_TYPE_HELLO;
2350 else if (! strncmp (argv[0], "d", 1))
2351 type = OSPF6_MESSAGE_TYPE_DBDESC;
2352 else if (! strncmp (argv[0], "lsr", 3))
2353 type = OSPF6_MESSAGE_TYPE_LSREQ;
2354 else if (! strncmp (argv[0], "lsu", 3))
2355 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2356 else if (! strncmp (argv[0], "lsa", 3))
2357 type = OSPF6_MESSAGE_TYPE_LSACK;
2358 else if (! strncmp (argv[0], "a", 1))
2359 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002360
hasso508e53e2004-05-18 18:57:06 +00002361 if (argc == 1)
2362 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2363 else if (! strncmp (argv[1], "s", 1))
2364 level = OSPF6_DEBUG_MESSAGE_SEND;
2365 else if (! strncmp (argv[1], "r", 1))
2366 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002367
hasso508e53e2004-05-18 18:57:06 +00002368 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002369 {
hasso508e53e2004-05-18 18:57:06 +00002370 for (i = 0; i < 6; i++)
2371 OSPF6_DEBUG_MESSAGE_ON (i, level);
2372 }
2373 else
2374 OSPF6_DEBUG_MESSAGE_ON (type, level);
2375
2376 return CMD_SUCCESS;
2377}
2378
2379ALIAS (debug_ospf6_message,
2380 debug_ospf6_message_sendrecv_cmd,
2381 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2382 DEBUG_STR
2383 OSPF6_STR
2384 "Debug OSPFv3 message\n"
2385 "Debug Unknown message\n"
2386 "Debug Hello message\n"
2387 "Debug Database Description message\n"
2388 "Debug Link State Request message\n"
2389 "Debug Link State Update message\n"
2390 "Debug Link State Acknowledgement message\n"
2391 "Debug All message\n"
2392 "Debug only sending message\n"
2393 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002394 )
hasso508e53e2004-05-18 18:57:06 +00002395
2396
2397DEFUN (no_debug_ospf6_message,
2398 no_debug_ospf6_message_cmd,
2399 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2400 NO_STR
2401 DEBUG_STR
2402 OSPF6_STR
2403 "Debug OSPFv3 message\n"
2404 "Debug Unknown message\n"
2405 "Debug Hello message\n"
2406 "Debug Database Description message\n"
2407 "Debug Link State Request message\n"
2408 "Debug Link State Update message\n"
2409 "Debug Link State Acknowledgement message\n"
2410 "Debug All message\n"
2411 )
2412{
2413 unsigned char level = 0;
2414 int type = 0;
2415 int i;
2416
2417 assert (argc > 0);
2418
2419 /* check type */
2420 if (! strncmp (argv[0], "u", 1))
2421 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2422 else if (! strncmp (argv[0], "h", 1))
2423 type = OSPF6_MESSAGE_TYPE_HELLO;
2424 else if (! strncmp (argv[0], "d", 1))
2425 type = OSPF6_MESSAGE_TYPE_DBDESC;
2426 else if (! strncmp (argv[0], "lsr", 3))
2427 type = OSPF6_MESSAGE_TYPE_LSREQ;
2428 else if (! strncmp (argv[0], "lsu", 3))
2429 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2430 else if (! strncmp (argv[0], "lsa", 3))
2431 type = OSPF6_MESSAGE_TYPE_LSACK;
2432 else if (! strncmp (argv[0], "a", 1))
2433 type = OSPF6_MESSAGE_TYPE_ALL;
2434
2435 if (argc == 1)
2436 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2437 else if (! strncmp (argv[1], "s", 1))
2438 level = OSPF6_DEBUG_MESSAGE_SEND;
2439 else if (! strncmp (argv[1], "r", 1))
2440 level = OSPF6_DEBUG_MESSAGE_RECV;
2441
2442 if (type == OSPF6_MESSAGE_TYPE_ALL)
2443 {
2444 for (i = 0; i < 6; i++)
2445 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2446 }
2447 else
2448 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2449
2450 return CMD_SUCCESS;
2451}
2452
2453ALIAS (no_debug_ospf6_message,
2454 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002455 "no debug ospf6 message "
2456 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002457 NO_STR
2458 DEBUG_STR
2459 OSPF6_STR
2460 "Debug OSPFv3 message\n"
2461 "Debug Unknown message\n"
2462 "Debug Hello message\n"
2463 "Debug Database Description message\n"
2464 "Debug Link State Request message\n"
2465 "Debug Link State Update message\n"
2466 "Debug Link State Acknowledgement message\n"
2467 "Debug All message\n"
2468 "Debug only sending message\n"
2469 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002470 )
hasso508e53e2004-05-18 18:57:06 +00002471
2472int
2473config_write_ospf6_debug_message (struct vty *vty)
2474{
paul0c083ee2004-10-10 12:54:58 +00002475 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002476 "lsreq", "lsupdate", "lsack"};
2477 unsigned char s = 0, r = 0;
2478 int i;
2479
2480 for (i = 0; i < 6; i++)
2481 {
2482 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2483 s |= 1 << i;
2484 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2485 r |= 1 << i;
2486 }
2487
2488 if (s == 0x3f && r == 0x3f)
2489 {
hasso049207c2004-08-04 20:02:13 +00002490 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002491 return 0;
2492 }
2493
hasso508e53e2004-05-18 18:57:06 +00002494 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002495 {
hasso049207c2004-08-04 20:02:13 +00002496 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002497 return 0;
2498 }
2499 else if (s == 0 && r == 0x3f)
2500 {
hasso049207c2004-08-04 20:02:13 +00002501 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002502 return 0;
paul718e3742002-12-13 20:15:29 +00002503 }
2504
hasso508e53e2004-05-18 18:57:06 +00002505 /* Unknown message is logged by default */
2506 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2507 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002508 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002509 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002510 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002511 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002512 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002513
hasso508e53e2004-05-18 18:57:06 +00002514 for (i = 1; i < 6; i++)
2515 {
2516 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2517 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002518 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002519 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2520 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002521 VNL);
hasso508e53e2004-05-18 18:57:06 +00002522 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2523 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002524 VNL);
hasso508e53e2004-05-18 18:57:06 +00002525 }
paul718e3742002-12-13 20:15:29 +00002526
2527 return 0;
2528}
2529
paul718e3742002-12-13 20:15:29 +00002530void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002531install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002532{
hasso508e53e2004-05-18 18:57:06 +00002533 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2534 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2535 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2536 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2537 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2538 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2539 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2540 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002541}
2542
paul718e3742002-12-13 20:15:29 +00002543