blob: 0756ef34c94be912ed4472cac270eb8c59a53888 [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
Ingo Flaschberger1db65fa2011-04-17 18:28:20 +00001724 if (iobuflen == 0)
1725 {
1726 zlog_debug ("Unable to send Hello on interface %s iobuflen is 0",
1727 oi->interface->name);
1728 return 0;
1729 }
1730
hasso508e53e2004-05-18 18:57:06 +00001731 /* set next thread */
1732 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1733 oi, oi->hello_interval);
1734
hasso3b4cd3a2004-05-18 19:28:32 +00001735 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001736 oh = (struct ospf6_header *) sendbuf;
1737 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1738
1739 hello->interface_id = htonl (oi->interface->ifindex);
1740 hello->priority = oi->priority;
1741 hello->options[0] = oi->area->options[0];
1742 hello->options[1] = oi->area->options[1];
1743 hello->options[2] = oi->area->options[2];
1744 hello->hello_interval = htons (oi->hello_interval);
1745 hello->dead_interval = htons (oi->dead_interval);
1746 hello->drouter = oi->drouter;
1747 hello->bdrouter = oi->bdrouter;
1748
Paul Jakma6ac29a52008-08-15 13:45:30 +01001749 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001750
paul1eb8ef22005-04-07 07:30:20 +00001751 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001752 {
hasso508e53e2004-05-18 18:57:06 +00001753 if (on->state < OSPF6_NEIGHBOR_INIT)
1754 continue;
1755
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001756 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001757 {
1758 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001759 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001760 break;
1761 }
1762
1763 memcpy (p, &on->router_id, sizeof (u_int32_t));
1764 p += sizeof (u_int32_t);
1765 }
1766
1767 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1768 oh->length = htons (p - sendbuf);
1769
1770 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1771 return 0;
1772}
1773
1774int
1775ospf6_dbdesc_send (struct thread *thread)
1776{
1777 struct ospf6_neighbor *on;
1778 struct ospf6_header *oh;
1779 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001780 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001781 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00001782 struct in6_addr *dst;
hasso508e53e2004-05-18 18:57:06 +00001783
1784 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1785 on->thread_send_dbdesc = (struct thread *) NULL;
1786
1787 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1788 {
1789 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001790 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1791 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001792 return 0;
1793 }
1794
1795 /* set next thread if master */
1796 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1797 on->thread_send_dbdesc =
1798 thread_add_timer (master, ospf6_dbdesc_send, on,
1799 on->ospf6_if->rxmt_interval);
1800
hasso3b4cd3a2004-05-18 19:28:32 +00001801 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001802 oh = (struct ospf6_header *) sendbuf;
1803 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1804 sizeof (struct ospf6_header));
1805
1806 /* if this is initial one, initialize sequence number for DbDesc */
Dinesh Dutt7a10a352013-08-25 03:03:07 +00001807 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
1808 (on->dbdesc_seqnum == 0))
hasso508e53e2004-05-18 18:57:06 +00001809 {
1810 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001811 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001812 tv.tv_sec = 1;
1813 on->dbdesc_seqnum = tv.tv_sec;
1814 }
1815
1816 dbdesc->options[0] = on->ospf6_if->area->options[0];
1817 dbdesc->options[1] = on->ospf6_if->area->options[1];
1818 dbdesc->options[2] = on->ospf6_if->area->options[2];
1819 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1820 dbdesc->bits = on->dbdesc_bits;
1821 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1822
1823 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001824 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001825 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1826 {
1827 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1828 lsa = ospf6_lsdb_next (lsa))
1829 {
1830 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1831
1832 /* MTU check */
1833 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001834 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001835 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001836 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001837 break;
1838 }
1839 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1840 p += sizeof (struct ospf6_lsa_header);
1841 }
1842 }
1843
1844 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1845 oh->length = htons (p - sendbuf);
1846
Dinesh Duttc5926a92013-08-24 07:55:00 +00001847
1848 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1849 dst = &allspfrouters6;
1850 else
1851 dst = &on->linklocal_addr;
1852
1853 ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
1854
hasso508e53e2004-05-18 18:57:06 +00001855 return 0;
1856}
1857
1858int
1859ospf6_dbdesc_send_newone (struct thread *thread)
1860{
1861 struct ospf6_neighbor *on;
1862 struct ospf6_lsa *lsa;
1863 unsigned int size = 0;
1864
1865 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001866 ospf6_lsdb_remove_all (on->dbdesc_list);
1867
1868 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1869 so that ospf6_send_dbdesc () can send those LSAs */
1870 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1871 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1872 lsa = ospf6_lsdb_next (lsa))
1873 {
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001874 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001875 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001876 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001877 break;
1878 }
1879
hasso508e53e2004-05-18 18:57:06 +00001880 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1881 ospf6_lsdb_remove (lsa, on->summary_list);
1882 size += sizeof (struct ospf6_lsa_header);
1883 }
1884
1885 if (on->summary_list->count == 0)
1886 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1887
1888 /* If slave, More bit check must be done here */
1889 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1890 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1891 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1892 thread_add_event (master, exchange_done, on, 0);
1893
1894 thread_execute (master, ospf6_dbdesc_send, on, 0);
1895 return 0;
1896}
1897
1898int
1899ospf6_lsreq_send (struct thread *thread)
1900{
1901 struct ospf6_neighbor *on;
1902 struct ospf6_header *oh;
1903 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001904 u_char *p;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001905 struct ospf6_lsa *lsa, *last_req;
hasso508e53e2004-05-18 18:57:06 +00001906
1907 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1908 on->thread_send_lsreq = (struct thread *) NULL;
1909
1910 /* LSReq will be sent only in ExStart or Loading */
1911 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1912 on->state != OSPF6_NEIGHBOR_LOADING)
1913 {
1914 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001915 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1916 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001917 return 0;
1918 }
1919
1920 /* schedule loading_done if request list is empty */
1921 if (on->request_list->count == 0)
1922 {
1923 thread_add_event (master, loading_done, on, 0);
1924 return 0;
1925 }
1926
hasso3b4cd3a2004-05-18 19:28:32 +00001927 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001928 oh = (struct ospf6_header *) sendbuf;
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001929 last_req = NULL;
hasso508e53e2004-05-18 18:57:06 +00001930
1931 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001932 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001933 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1934 lsa = ospf6_lsdb_next (lsa))
1935 {
1936 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001937 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001938 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00001939 ospf6_lsdb_lsa_unlock (lsa);
hasso508e53e2004-05-18 18:57:06 +00001940 break;
1941 }
1942
1943 e = (struct ospf6_lsreq_entry *) p;
1944 e->type = lsa->header->type;
1945 e->id = lsa->header->id;
1946 e->adv_router = lsa->header->adv_router;
1947 p += sizeof (struct ospf6_lsreq_entry);
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001948 last_req = lsa;
1949 }
1950
1951 if (last_req != NULL)
1952 {
1953 if (on->last_ls_req != NULL)
1954 {
1955 ospf6_lsa_unlock (on->last_ls_req);
1956 }
1957 ospf6_lsa_lock (last_req);
1958 on->last_ls_req = last_req;
hasso508e53e2004-05-18 18:57:06 +00001959 }
1960
1961 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1962 oh->length = htons (p - sendbuf);
1963
Dinesh Duttc5926a92013-08-24 07:55:00 +00001964 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1965 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
hasso508e53e2004-05-18 18:57:06 +00001966 on->ospf6_if, oh);
Dinesh Duttc5926a92013-08-24 07:55:00 +00001967 else
1968 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1969 on->ospf6_if, oh);
1970
Dinesh Dutteb82e9e2013-08-24 07:55:07 +00001971 /* set next thread */
1972 if (on->request_list->count != 0)
1973 {
1974 on->thread_send_lsreq =
1975 thread_add_timer (master, ospf6_lsreq_send, on,
1976 on->ospf6_if->rxmt_interval);
1977 }
1978
hasso508e53e2004-05-18 18:57:06 +00001979 return 0;
1980}
1981
1982int
1983ospf6_lsupdate_send_neighbor (struct thread *thread)
1984{
1985 struct ospf6_neighbor *on;
1986 struct ospf6_header *oh;
1987 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001988 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00001989 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00001990 struct ospf6_lsa *lsa;
1991
1992 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1993 on->thread_send_lsupdate = (struct thread *) NULL;
1994
hasso6452df02004-08-15 05:52:07 +00001995 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001996 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001997
hasso508e53e2004-05-18 18:57:06 +00001998 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1999 {
2000 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002001 zlog_debug ("Quit to send (neighbor state %s)",
2002 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002003 return 0;
2004 }
2005
hasso3b4cd3a2004-05-18 19:28:32 +00002006 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002007 oh = (struct ospf6_header *) sendbuf;
2008 lsupdate = (struct ospf6_lsupdate *)
2009 ((caddr_t) oh + sizeof (struct ospf6_header));
2010
Paul Jakma6ac29a52008-08-15 13:45:30 +01002011 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002012 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002013
2014 /* lsupdate_list lists those LSA which doesn't need to be
2015 retransmitted. remove those from the list */
2016 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2017 lsa = ospf6_lsdb_next (lsa))
2018 {
2019 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002020 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002021 > ospf6_packet_max(on->ospf6_if))
2022 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002023 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002024 break;
2025 }
hasso508e53e2004-05-18 18:57:06 +00002026
hasso508e53e2004-05-18 18:57:06 +00002027 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2028 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2029 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002030 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002031
2032 assert (lsa->lock == 2);
2033 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2034 }
2035
Dinesh Duttc5926a92013-08-24 07:55:00 +00002036 if (lsa_cnt)
2037 {
2038 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2039 oh->length = htons (p - sendbuf);
2040 lsupdate->lsa_number = htonl (lsa_cnt);
2041
2042 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2043 (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
2044 (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
2045 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2046 on->ospf6_if, oh);
2047 else
2048 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2049 on->ospf6_if, oh);
2050 }
2051
2052 /* The addresses used for retransmissions are different from those sent the
2053 first time and so we need to separate them here.
2054 */
2055 memset (sendbuf, 0, iobuflen);
2056 oh = (struct ospf6_header *) sendbuf;
2057 lsupdate = (struct ospf6_lsupdate *)
2058 ((caddr_t) oh + sizeof (struct ospf6_header));
2059 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
2060 lsa_cnt = 0;
2061
hasso508e53e2004-05-18 18:57:06 +00002062 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2063 lsa = ospf6_lsdb_next (lsa))
2064 {
2065 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002066 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002067 > ospf6_packet_max(on->ospf6_if))
2068 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002069 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002070 break;
2071 }
hasso508e53e2004-05-18 18:57:06 +00002072
hasso508e53e2004-05-18 18:57:06 +00002073 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2074 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2075 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002076 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002077 }
2078
Dinesh Duttc5926a92013-08-24 07:55:00 +00002079 if (lsa_cnt)
hasso508e53e2004-05-18 18:57:06 +00002080 {
Dinesh Duttc5926a92013-08-24 07:55:00 +00002081 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2082 oh->length = htons (p - sendbuf);
2083 lsupdate->lsa_number = htonl (lsa_cnt);
2084
2085 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2086 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2087 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002088 else
Dinesh Duttc5926a92013-08-24 07:55:00 +00002089 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2090 on->ospf6_if, oh);
hasso508e53e2004-05-18 18:57:06 +00002091 }
2092
Dinesh Duttc5926a92013-08-24 07:55:00 +00002093 if (on->lsupdate_list->count != 0)
2094 on->thread_send_lsupdate =
2095 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2096 else if (on->retrans_list->count != 0)
2097 on->thread_send_lsupdate =
2098 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2099 on->ospf6_if->rxmt_interval);
hasso508e53e2004-05-18 18:57:06 +00002100 return 0;
2101}
2102
2103int
2104ospf6_lsupdate_send_interface (struct thread *thread)
2105{
2106 struct ospf6_interface *oi;
2107 struct ospf6_header *oh;
2108 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002109 u_char *p;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002110 int lsa_cnt;
hasso508e53e2004-05-18 18:57:06 +00002111 struct ospf6_lsa *lsa;
2112
2113 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2114 oi->thread_send_lsupdate = (struct thread *) NULL;
2115
2116 if (oi->state <= OSPF6_INTERFACE_WAITING)
2117 {
2118 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002119 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2120 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002121 return 0;
2122 }
2123
2124 /* if we have nothing to send, return */
2125 if (oi->lsupdate_list->count == 0)
2126 return 0;
2127
hasso3b4cd3a2004-05-18 19:28:32 +00002128 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002129 oh = (struct ospf6_header *) sendbuf;
2130 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
Dinesh Duttc5926a92013-08-24 07:55:00 +00002131 sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002132
Paul Jakma6ac29a52008-08-15 13:45:30 +01002133 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
Dinesh Duttc5926a92013-08-24 07:55:00 +00002134 lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002135
2136 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2137 lsa = ospf6_lsdb_next (lsa))
2138 {
2139 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002140 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002141 > ospf6_packet_max(oi))
2142 {
Dinesh Dutta765eb92013-08-24 07:55:14 +00002143 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002144 break;
2145 }
hasso508e53e2004-05-18 18:57:06 +00002146
hasso508e53e2004-05-18 18:57:06 +00002147 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2148 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2149 p += OSPF6_LSA_SIZE (lsa->header);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002150 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002151
2152 assert (lsa->lock == 2);
2153 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2154 }
2155
Dinesh Duttc5926a92013-08-24 07:55:00 +00002156 if (lsa_cnt)
2157 {
2158 lsupdate->lsa_number = htonl (lsa_cnt);
hasso508e53e2004-05-18 18:57:06 +00002159
Dinesh Duttc5926a92013-08-24 07:55:00 +00002160 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2161 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002162
Dinesh Duttc5926a92013-08-24 07:55:00 +00002163 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2164 (oi->state == OSPF6_INTERFACE_DR) ||
2165 (oi->state == OSPF6_INTERFACE_BDR))
2166 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2167 else
2168 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2169
2170 }
hasso508e53e2004-05-18 18:57:06 +00002171
2172 if (oi->lsupdate_list->count > 0)
2173 {
2174 oi->thread_send_lsupdate =
2175 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2176 }
2177
2178 return 0;
2179}
2180
2181int
2182ospf6_lsack_send_neighbor (struct thread *thread)
2183{
2184 struct ospf6_neighbor *on;
2185 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002186 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002187 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002188 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002189
2190 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2191 on->thread_send_lsack = (struct thread *) NULL;
2192
2193 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2194 {
2195 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002196 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2197 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002198 return 0;
2199 }
2200
2201 /* if we have nothing to send, return */
2202 if (on->lsack_list->count == 0)
2203 return 0;
2204
hasso3b4cd3a2004-05-18 19:28:32 +00002205 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002206 oh = (struct ospf6_header *) sendbuf;
2207
Paul Jakma6ac29a52008-08-15 13:45:30 +01002208 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002209
2210 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2211 lsa = ospf6_lsdb_next (lsa))
2212 {
2213 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002214 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002215 {
2216 /* if we run out of packet size/space here,
2217 better to try again soon. */
2218 THREAD_OFF (on->thread_send_lsack);
2219 on->thread_send_lsack =
2220 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
hasso508e53e2004-05-18 18:57:06 +00002221
Dinesh Dutta765eb92013-08-24 07:55:14 +00002222 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002223 break;
2224 }
hasso508e53e2004-05-18 18:57:06 +00002225
2226 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2227 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2228 p += sizeof (struct ospf6_lsa_header);
2229
2230 assert (lsa->lock == 2);
2231 ospf6_lsdb_remove (lsa, on->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002232 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002233 }
2234
Dinesh Duttc5926a92013-08-24 07:55:00 +00002235 if (lsa_cnt)
2236 {
2237 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2238 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002239
Dinesh Duttc5926a92013-08-24 07:55:00 +00002240 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2241 on->ospf6_if, oh);
2242 }
2243
2244 if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
2245 {
2246 on->thread_send_lsack =
2247 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2248 }
2249
hasso508e53e2004-05-18 18:57:06 +00002250 return 0;
2251}
2252
2253int
2254ospf6_lsack_send_interface (struct thread *thread)
2255{
2256 struct ospf6_interface *oi;
2257 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002258 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002259 struct ospf6_lsa *lsa;
Dinesh Duttc5926a92013-08-24 07:55:00 +00002260 int lsa_cnt = 0;
hasso508e53e2004-05-18 18:57:06 +00002261
2262 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2263 oi->thread_send_lsack = (struct thread *) NULL;
2264
2265 if (oi->state <= OSPF6_INTERFACE_WAITING)
2266 {
2267 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002268 zlog_debug ("Quit to send LSAck to interface %s state %s",
2269 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002270 return 0;
2271 }
2272
2273 /* if we have nothing to send, return */
2274 if (oi->lsack_list->count == 0)
2275 return 0;
2276
hasso3b4cd3a2004-05-18 19:28:32 +00002277 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002278 oh = (struct ospf6_header *) sendbuf;
2279
Paul Jakma6ac29a52008-08-15 13:45:30 +01002280 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002281
2282 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2283 lsa = ospf6_lsdb_next (lsa))
2284 {
2285 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002286 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
Dinesh Duttc5926a92013-08-24 07:55:00 +00002287 {
2288 /* if we run out of packet size/space here,
2289 better to try again soon. */
2290 THREAD_OFF (oi->thread_send_lsack);
2291 oi->thread_send_lsack =
2292 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
hasso508e53e2004-05-18 18:57:06 +00002293
Dinesh Dutta765eb92013-08-24 07:55:14 +00002294 ospf6_lsdb_lsa_unlock (lsa);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002295 break;
2296 }
hasso508e53e2004-05-18 18:57:06 +00002297
2298 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2299 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2300 p += sizeof (struct ospf6_lsa_header);
2301
2302 assert (lsa->lock == 2);
2303 ospf6_lsdb_remove (lsa, oi->lsack_list);
Dinesh Duttc5926a92013-08-24 07:55:00 +00002304 lsa_cnt++;
hasso508e53e2004-05-18 18:57:06 +00002305 }
2306
Dinesh Duttc5926a92013-08-24 07:55:00 +00002307 if (lsa_cnt)
2308 {
2309 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2310 oh->length = htons (p - sendbuf);
hasso508e53e2004-05-18 18:57:06 +00002311
Dinesh Duttc5926a92013-08-24 07:55:00 +00002312 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2313 (oi->state == OSPF6_INTERFACE_DR) ||
2314 (oi->state == OSPF6_INTERFACE_BDR))
2315 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2316 else
2317 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2318 }
hasso508e53e2004-05-18 18:57:06 +00002319
2320 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2321 {
2322 oi->thread_send_lsack =
2323 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2324 }
paul718e3742002-12-13 20:15:29 +00002325
2326 return 0;
2327}
2328
2329
hasso508e53e2004-05-18 18:57:06 +00002330/* Commands */
2331DEFUN (debug_ospf6_message,
2332 debug_ospf6_message_cmd,
2333 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2334 DEBUG_STR
2335 OSPF6_STR
2336 "Debug OSPFv3 message\n"
2337 "Debug Unknown message\n"
2338 "Debug Hello message\n"
2339 "Debug Database Description message\n"
2340 "Debug Link State Request message\n"
2341 "Debug Link State Update message\n"
2342 "Debug Link State Acknowledgement message\n"
2343 "Debug All message\n"
2344 )
paul718e3742002-12-13 20:15:29 +00002345{
hasso508e53e2004-05-18 18:57:06 +00002346 unsigned char level = 0;
2347 int type = 0;
paul718e3742002-12-13 20:15:29 +00002348 int i;
2349
hasso508e53e2004-05-18 18:57:06 +00002350 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002351
hasso508e53e2004-05-18 18:57:06 +00002352 /* check type */
2353 if (! strncmp (argv[0], "u", 1))
2354 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2355 else if (! strncmp (argv[0], "h", 1))
2356 type = OSPF6_MESSAGE_TYPE_HELLO;
2357 else if (! strncmp (argv[0], "d", 1))
2358 type = OSPF6_MESSAGE_TYPE_DBDESC;
2359 else if (! strncmp (argv[0], "lsr", 3))
2360 type = OSPF6_MESSAGE_TYPE_LSREQ;
2361 else if (! strncmp (argv[0], "lsu", 3))
2362 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2363 else if (! strncmp (argv[0], "lsa", 3))
2364 type = OSPF6_MESSAGE_TYPE_LSACK;
2365 else if (! strncmp (argv[0], "a", 1))
2366 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002367
hasso508e53e2004-05-18 18:57:06 +00002368 if (argc == 1)
2369 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2370 else if (! strncmp (argv[1], "s", 1))
2371 level = OSPF6_DEBUG_MESSAGE_SEND;
2372 else if (! strncmp (argv[1], "r", 1))
2373 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002374
hasso508e53e2004-05-18 18:57:06 +00002375 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002376 {
hasso508e53e2004-05-18 18:57:06 +00002377 for (i = 0; i < 6; i++)
2378 OSPF6_DEBUG_MESSAGE_ON (i, level);
2379 }
2380 else
2381 OSPF6_DEBUG_MESSAGE_ON (type, level);
2382
2383 return CMD_SUCCESS;
2384}
2385
2386ALIAS (debug_ospf6_message,
2387 debug_ospf6_message_sendrecv_cmd,
2388 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2389 DEBUG_STR
2390 OSPF6_STR
2391 "Debug OSPFv3 message\n"
2392 "Debug Unknown message\n"
2393 "Debug Hello message\n"
2394 "Debug Database Description message\n"
2395 "Debug Link State Request message\n"
2396 "Debug Link State Update message\n"
2397 "Debug Link State Acknowledgement message\n"
2398 "Debug All message\n"
2399 "Debug only sending message\n"
2400 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002401 )
hasso508e53e2004-05-18 18:57:06 +00002402
2403
2404DEFUN (no_debug_ospf6_message,
2405 no_debug_ospf6_message_cmd,
2406 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2407 NO_STR
2408 DEBUG_STR
2409 OSPF6_STR
2410 "Debug OSPFv3 message\n"
2411 "Debug Unknown message\n"
2412 "Debug Hello message\n"
2413 "Debug Database Description message\n"
2414 "Debug Link State Request message\n"
2415 "Debug Link State Update message\n"
2416 "Debug Link State Acknowledgement message\n"
2417 "Debug All message\n"
2418 )
2419{
2420 unsigned char level = 0;
2421 int type = 0;
2422 int i;
2423
2424 assert (argc > 0);
2425
2426 /* check type */
2427 if (! strncmp (argv[0], "u", 1))
2428 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2429 else if (! strncmp (argv[0], "h", 1))
2430 type = OSPF6_MESSAGE_TYPE_HELLO;
2431 else if (! strncmp (argv[0], "d", 1))
2432 type = OSPF6_MESSAGE_TYPE_DBDESC;
2433 else if (! strncmp (argv[0], "lsr", 3))
2434 type = OSPF6_MESSAGE_TYPE_LSREQ;
2435 else if (! strncmp (argv[0], "lsu", 3))
2436 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2437 else if (! strncmp (argv[0], "lsa", 3))
2438 type = OSPF6_MESSAGE_TYPE_LSACK;
2439 else if (! strncmp (argv[0], "a", 1))
2440 type = OSPF6_MESSAGE_TYPE_ALL;
2441
2442 if (argc == 1)
2443 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2444 else if (! strncmp (argv[1], "s", 1))
2445 level = OSPF6_DEBUG_MESSAGE_SEND;
2446 else if (! strncmp (argv[1], "r", 1))
2447 level = OSPF6_DEBUG_MESSAGE_RECV;
2448
2449 if (type == OSPF6_MESSAGE_TYPE_ALL)
2450 {
2451 for (i = 0; i < 6; i++)
2452 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2453 }
2454 else
2455 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2456
2457 return CMD_SUCCESS;
2458}
2459
2460ALIAS (no_debug_ospf6_message,
2461 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002462 "no debug ospf6 message "
2463 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002464 NO_STR
2465 DEBUG_STR
2466 OSPF6_STR
2467 "Debug OSPFv3 message\n"
2468 "Debug Unknown message\n"
2469 "Debug Hello message\n"
2470 "Debug Database Description message\n"
2471 "Debug Link State Request message\n"
2472 "Debug Link State Update message\n"
2473 "Debug Link State Acknowledgement message\n"
2474 "Debug All message\n"
2475 "Debug only sending message\n"
2476 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002477 )
hasso508e53e2004-05-18 18:57:06 +00002478
2479int
2480config_write_ospf6_debug_message (struct vty *vty)
2481{
paul0c083ee2004-10-10 12:54:58 +00002482 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002483 "lsreq", "lsupdate", "lsack"};
2484 unsigned char s = 0, r = 0;
2485 int i;
2486
2487 for (i = 0; i < 6; i++)
2488 {
2489 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2490 s |= 1 << i;
2491 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2492 r |= 1 << i;
2493 }
2494
2495 if (s == 0x3f && r == 0x3f)
2496 {
hasso049207c2004-08-04 20:02:13 +00002497 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002498 return 0;
2499 }
2500
hasso508e53e2004-05-18 18:57:06 +00002501 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002502 {
hasso049207c2004-08-04 20:02:13 +00002503 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002504 return 0;
2505 }
2506 else if (s == 0 && r == 0x3f)
2507 {
hasso049207c2004-08-04 20:02:13 +00002508 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002509 return 0;
paul718e3742002-12-13 20:15:29 +00002510 }
2511
hasso508e53e2004-05-18 18:57:06 +00002512 /* Unknown message is logged by default */
2513 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2514 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002515 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002516 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002517 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002518 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002519 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002520
hasso508e53e2004-05-18 18:57:06 +00002521 for (i = 1; i < 6; i++)
2522 {
2523 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2524 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002525 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002526 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2527 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002528 VNL);
hasso508e53e2004-05-18 18:57:06 +00002529 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2530 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002531 VNL);
hasso508e53e2004-05-18 18:57:06 +00002532 }
paul718e3742002-12-13 20:15:29 +00002533
2534 return 0;
2535}
2536
paul718e3742002-12-13 20:15:29 +00002537void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002538install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002539{
hasso508e53e2004-05-18 18:57:06 +00002540 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2541 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2542 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2543 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2544 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2545 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2546 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2547 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002548}
2549
paul718e3742002-12-13 20:15:29 +00002550