blob: aaee4d20214132523e375a781061f8fb6b5819d8 [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 Ovsienko552563a2011-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 Tejblum82a963a2011-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 Ovsienkoed721562011-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};
61static const size_t ospf6_message_type_str_max =
62 sizeof (ospf6_message_type_str) / sizeof (ospf6_message_type_str[0]);
hasso508e53e2004-05-18 18:57:06 +000063
Denis Ovsienko552563a2011-09-26 13:18:51 +040064/* Minimum (besides the standard OSPF packet header) lengths for OSPF
65 packets of particular types, offset is the "type" field. */
66const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
67{
68 0,
69 OSPF6_HELLO_MIN_SIZE,
70 OSPF6_DB_DESC_MIN_SIZE,
71 OSPF6_LS_REQ_MIN_SIZE,
72 OSPF6_LS_UPD_MIN_SIZE,
73 OSPF6_LS_ACK_MIN_SIZE
74};
75
76/* Minimum (besides the standard LSA header) lengths for LSAs of particular
77 types, offset is the "LSA function code" portion of "LSA type" field. */
78const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
79{
80 0,
81 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
82 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
83 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
84 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
85 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
86 /* 0x2006 */ 0,
87 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
88 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
89 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
90};
91
hasso508e53e2004-05-18 18:57:06 +000092/* print functions */
93
94static void
95ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000096{
hasso508e53e2004-05-18 18:57:06 +000097 char router_id[16], area_id[16];
98 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
99 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +0000100
hassoc6487d62004-12-24 06:00:11 +0000101 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +0000102 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +0000103 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +0000104 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +0000105}
paul718e3742002-12-13 20:15:29 +0000106
107void
hasso508e53e2004-05-18 18:57:06 +0000108ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000109{
paul718e3742002-12-13 20:15:29 +0000110 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000111 char options[16];
112 char drouter[16], bdrouter[16], neighbor[16];
113 char *p;
paul718e3742002-12-13 20:15:29 +0000114
hasso508e53e2004-05-18 18:57:06 +0000115 ospf6_header_print (oh);
116 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000117
hasso508e53e2004-05-18 18:57:06 +0000118 hello = (struct ospf6_hello *)
119 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000120
hasso508e53e2004-05-18 18:57:06 +0000121 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
122 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
123 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000124
hassoc6487d62004-12-24 06:00:11 +0000125 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000126 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000127 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000128 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000129 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000130
hasso508e53e2004-05-18 18:57:06 +0000131 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
132 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
133 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000134 {
hasso508e53e2004-05-18 18:57:06 +0000135 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000136 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000137 }
hasso508e53e2004-05-18 18:57:06 +0000138
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400139 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000140}
141
hasso508e53e2004-05-18 18:57:06 +0000142void
143ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000144{
paul718e3742002-12-13 20:15:29 +0000145 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000146 char options[16];
147 char *p;
paul718e3742002-12-13 20:15:29 +0000148
hasso508e53e2004-05-18 18:57:06 +0000149 ospf6_header_print (oh);
150 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000151
hasso508e53e2004-05-18 18:57:06 +0000152 dbdesc = (struct ospf6_dbdesc *)
153 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000154
hasso508e53e2004-05-18 18:57:06 +0000155 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000156
hassoc6487d62004-12-24 06:00:11 +0000157 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000158 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000159 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000160 dbdesc->reserved2,
161 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
162 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
163 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
164 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000165
hasso508e53e2004-05-18 18:57:06 +0000166 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
167 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
168 p += sizeof (struct ospf6_lsa_header))
169 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
170
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400171 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000172}
173
hasso508e53e2004-05-18 18:57:06 +0000174void
175ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000176{
hasso508e53e2004-05-18 18:57:06 +0000177 char id[16], adv_router[16];
178 char *p;
paul718e3742002-12-13 20:15:29 +0000179
hasso508e53e2004-05-18 18:57:06 +0000180 ospf6_header_print (oh);
181 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000182
hasso508e53e2004-05-18 18:57:06 +0000183 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
184 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
185 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000186 {
hasso508e53e2004-05-18 18:57:06 +0000187 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
188 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
189 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000190 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000191 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000192 }
hasso508e53e2004-05-18 18:57:06 +0000193
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400194 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000195}
196
hasso508e53e2004-05-18 18:57:06 +0000197void
198ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000199{
paul718e3742002-12-13 20:15:29 +0000200 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000201 u_long num;
202 char *p;
paul718e3742002-12-13 20:15:29 +0000203
hasso508e53e2004-05-18 18:57:06 +0000204 ospf6_header_print (oh);
205 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000206
hasso508e53e2004-05-18 18:57:06 +0000207 lsupdate = (struct ospf6_lsupdate *)
208 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000209
hasso508e53e2004-05-18 18:57:06 +0000210 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000211 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000212
hasso508e53e2004-05-18 18:57:06 +0000213 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
214 p < OSPF6_MESSAGE_END (oh) &&
215 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
216 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000217 {
hasso508e53e2004-05-18 18:57:06 +0000218 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000219 }
paul718e3742002-12-13 20:15:29 +0000220
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400221 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000222}
223
hasso508e53e2004-05-18 18:57:06 +0000224void
225ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000226{
hasso508e53e2004-05-18 18:57:06 +0000227 char *p;
paul718e3742002-12-13 20:15:29 +0000228
hasso508e53e2004-05-18 18:57:06 +0000229 ospf6_header_print (oh);
230 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000231
hasso508e53e2004-05-18 18:57:06 +0000232 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
233 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
234 p += sizeof (struct ospf6_lsa_header))
235 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
236
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400237 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000238}
239
Paul Jakma6ac29a52008-08-15 13:45:30 +0100240static void
hasso508e53e2004-05-18 18:57:06 +0000241ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
242 struct ospf6_interface *oi, struct ospf6_header *oh)
243{
244 struct ospf6_hello *hello;
245 struct ospf6_neighbor *on;
246 char *p;
247 int twoway = 0;
248 int neighborchange = 0;
249 int backupseen = 0;
250
hasso508e53e2004-05-18 18:57:06 +0000251 hello = (struct ospf6_hello *)
252 ((caddr_t) oh + sizeof (struct ospf6_header));
253
paul718e3742002-12-13 20:15:29 +0000254 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000255 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000256 {
hasso508e53e2004-05-18 18:57:06 +0000257 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000258 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000259 return;
260 }
261
262 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000263 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000264 {
hasso508e53e2004-05-18 18:57:06 +0000265 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000266 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000267 return;
268 }
269
hasso508e53e2004-05-18 18:57:06 +0000270 /* E-bit check */
271 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
272 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000273 {
hasso508e53e2004-05-18 18:57:06 +0000274 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000275 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000276 return;
277 }
278
hasso508e53e2004-05-18 18:57:06 +0000279 /* Find neighbor, create if not exist */
280 on = ospf6_neighbor_lookup (oh->router_id, oi);
281 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000282 {
hasso508e53e2004-05-18 18:57:06 +0000283 on = ospf6_neighbor_create (oh->router_id, oi);
284 on->prev_drouter = on->drouter = hello->drouter;
285 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
286 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000287 }
288
hasso7b6ae022005-06-24 08:17:51 +0000289 /* always override neighbor's source address and ifindex */
290 on->ifindex = ntohl (hello->interface_id);
291 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
292
paul718e3742002-12-13 20:15:29 +0000293 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000294 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
295 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
296 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000297 {
hasso508e53e2004-05-18 18:57:06 +0000298 u_int32_t *router_id = (u_int32_t *) p;
299
300 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000301 twoway++;
paul718e3742002-12-13 20:15:29 +0000302 }
303
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400304 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000305
306 /* RouterPriority check */
307 if (on->priority != hello->priority)
308 {
309 on->priority = hello->priority;
310 neighborchange++;
311 }
312
313 /* DR check */
314 if (on->drouter != hello->drouter)
315 {
316 on->prev_drouter = on->drouter;
317 on->drouter = hello->drouter;
318 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
319 neighborchange++;
320 }
321
322 /* BDR check */
323 if (on->bdrouter != hello->bdrouter)
324 {
325 on->prev_bdrouter = on->bdrouter;
326 on->bdrouter = hello->bdrouter;
327 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
328 neighborchange++;
329 }
paul718e3742002-12-13 20:15:29 +0000330
331 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000332 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000333 {
hasso508e53e2004-05-18 18:57:06 +0000334 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000335 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000336 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000337 backupseen++;
338 }
339
hasso508e53e2004-05-18 18:57:06 +0000340 /* Execute neighbor events */
341 thread_execute (master, hello_received, on, 0);
342 if (twoway)
343 thread_execute (master, twoway_received, on, 0);
344 else
345 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000346
hasso508e53e2004-05-18 18:57:06 +0000347 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000348 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000349 thread_add_event (master, backup_seen, oi, 0);
350 if (neighborchange)
351 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000352}
353
hasso508e53e2004-05-18 18:57:06 +0000354static void
355ospf6_dbdesc_recv_master (struct ospf6_header *oh,
356 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000357{
paul718e3742002-12-13 20:15:29 +0000358 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000359 char *p;
paul718e3742002-12-13 20:15:29 +0000360
hasso508e53e2004-05-18 18:57:06 +0000361 dbdesc = (struct ospf6_dbdesc *)
362 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000363
hasso508e53e2004-05-18 18:57:06 +0000364 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000365 {
hasso508e53e2004-05-18 18:57:06 +0000366 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000367 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000368 return;
369 }
370
hasso508e53e2004-05-18 18:57:06 +0000371 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000372 {
hasso508e53e2004-05-18 18:57:06 +0000373 case OSPF6_NEIGHBOR_TWOWAY:
374 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000375 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000376 return;
377
378 case OSPF6_NEIGHBOR_INIT:
379 thread_execute (master, twoway_received, on, 0);
380 if (on->state != OSPF6_NEIGHBOR_EXSTART)
381 {
382 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000383 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000384 return;
385 }
386 /* else fall through to ExStart */
387
388 case OSPF6_NEIGHBOR_EXSTART:
389 /* if neighbor obeys us as our slave, schedule negotiation_done
390 and process LSA Headers. Otherwise, ignore this message */
391 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
392 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
393 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
394 {
395 /* execute NegotiationDone */
396 thread_execute (master, negotiation_done, on, 0);
397
398 /* Record neighbor options */
399 memcpy (on->options, dbdesc->options, sizeof (on->options));
400 }
401 else
402 {
403 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000404 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000405 return;
406 }
407 /* fall through to exchange */
408
409 case OSPF6_NEIGHBOR_EXCHANGE:
410 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
411 {
412 /* Duplicated DatabaseDescription is dropped by master */
413 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000414 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000415 return;
416 }
417
418 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
419 {
420 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000421 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000422 thread_add_event (master, seqnumber_mismatch, on, 0);
423 return;
424 }
425
426 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
427 {
428 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000429 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000430 thread_add_event (master, seqnumber_mismatch, on, 0);
431 return;
432 }
433
434 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
435 {
436 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000437 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000438 thread_add_event (master, seqnumber_mismatch, on, 0);
439 return;
440 }
441
442 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
443 {
444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000445 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000446 (u_long) on->dbdesc_seqnum);
447 thread_add_event (master, seqnumber_mismatch, on, 0);
448 return;
449 }
450 break;
451
452 case OSPF6_NEIGHBOR_LOADING:
453 case OSPF6_NEIGHBOR_FULL:
454 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
455 {
456 /* Duplicated DatabaseDescription is dropped by master */
457 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000458 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000459 return;
460 }
461
462 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000463 zlog_debug ("Not duplicate dbdesc in state %s",
464 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000465 thread_add_event (master, seqnumber_mismatch, on, 0);
466 return;
467
468 default:
469 assert (0);
470 break;
471 }
472
473 /* Process LSA headers */
474 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
475 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
476 p += sizeof (struct ospf6_lsa_header))
477 {
478 struct ospf6_lsa *his, *mine;
479 struct ospf6_lsdb *lsdb = NULL;
480
481 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000482
483 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000484 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000485
486 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000487 {
hasso6452df02004-08-15 05:52:07 +0000488 case OSPF6_SCOPE_LINKLOCAL:
489 lsdb = on->ospf6_if->lsdb;
490 break;
491 case OSPF6_SCOPE_AREA:
492 lsdb = on->ospf6_if->area->lsdb;
493 break;
494 case OSPF6_SCOPE_AS:
495 lsdb = on->ospf6_if->area->ospf6->lsdb;
496 break;
497 case OSPF6_SCOPE_RESERVED:
498 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000499 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000500 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000501 continue;
502 break;
hasso508e53e2004-05-18 18:57:06 +0000503 }
504
505 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000506 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000507 {
508 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000509 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000510 ospf6_lsa_delete (his);
511 thread_add_event (master, seqnumber_mismatch, on, 0);
512 return;
513 }
514
515 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
516 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000517 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000518 {
hasso6452df02004-08-15 05:52:07 +0000519 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000520 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000521 ospf6_lsdb_add (his, on->request_list);
522 }
523 else if (ospf6_lsa_compare (his, mine) < 0)
524 {
525 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000526 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000527 ospf6_lsdb_add (his, on->request_list);
528 }
529 else
hasso6452df02004-08-15 05:52:07 +0000530 {
531 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000532 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000533 ospf6_lsa_delete (his);
534 }
hasso508e53e2004-05-18 18:57:06 +0000535 }
536
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400537 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000538
539 /* Increment sequence number */
540 on->dbdesc_seqnum ++;
541
542 /* schedule send lsreq */
543 if (on->thread_send_lsreq == NULL)
544 on->thread_send_lsreq =
545 thread_add_event (master, ospf6_lsreq_send, on, 0);
546
547 THREAD_OFF (on->thread_send_dbdesc);
548
549 /* More bit check */
550 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
551 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
552 thread_add_event (master, exchange_done, on, 0);
553 else
554 on->thread_send_dbdesc =
555 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
556
557 /* save last received dbdesc */
558 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
559}
560
561static void
562ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
563 struct ospf6_neighbor *on)
564{
565 struct ospf6_dbdesc *dbdesc;
566 char *p;
567
568 dbdesc = (struct ospf6_dbdesc *)
569 ((caddr_t) oh + sizeof (struct ospf6_header));
570
571 if (on->state < OSPF6_NEIGHBOR_INIT)
572 {
573 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000574 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000575 return;
576 }
577
hasso508e53e2004-05-18 18:57:06 +0000578 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000579 {
hasso508e53e2004-05-18 18:57:06 +0000580 case OSPF6_NEIGHBOR_TWOWAY:
581 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000582 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000583 return;
584
585 case OSPF6_NEIGHBOR_INIT:
586 thread_execute (master, twoway_received, on, 0);
587 if (on->state != OSPF6_NEIGHBOR_EXSTART)
588 {
589 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000590 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000591 return;
592 }
593 /* else fall through to ExStart */
594
595 case OSPF6_NEIGHBOR_EXSTART:
596 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
597 and process LSA Headers. Otherwise, ignore this message */
598 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
599 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
600 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
601 ntohs (oh->length) == sizeof (struct ospf6_header) +
602 sizeof (struct ospf6_dbdesc))
603 {
604 /* set the master/slave bit to slave */
605 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
606
607 /* set the DD sequence number to one specified by master */
608 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
609
610 /* schedule NegotiationDone */
611 thread_execute (master, negotiation_done, on, 0);
612
613 /* Record neighbor options */
614 memcpy (on->options, dbdesc->options, sizeof (on->options));
615 }
616 else
617 {
618 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000619 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000620 return;
621 }
622 break;
623
624 case OSPF6_NEIGHBOR_EXCHANGE:
625 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
626 {
627 /* Duplicated DatabaseDescription causes slave to retransmit */
628 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000629 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000630 THREAD_OFF (on->thread_send_dbdesc);
631 on->thread_send_dbdesc =
632 thread_add_event (master, ospf6_dbdesc_send, on, 0);
633 return;
634 }
635
636 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
637 {
638 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000639 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000640 thread_add_event (master, seqnumber_mismatch, on, 0);
641 return;
642 }
643
644 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
645 {
646 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000647 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000648 thread_add_event (master, seqnumber_mismatch, on, 0);
649 return;
650 }
651
652 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
653 {
654 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000655 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000656 thread_add_event (master, seqnumber_mismatch, on, 0);
657 return;
658 }
659
660 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
661 {
662 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000663 zlog_debug ("Sequence number mismatch (%#lx expected)",
664 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000665 thread_add_event (master, seqnumber_mismatch, on, 0);
666 return;
667 }
668 break;
669
670 case OSPF6_NEIGHBOR_LOADING:
671 case OSPF6_NEIGHBOR_FULL:
672 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
673 {
674 /* Duplicated DatabaseDescription causes slave to retransmit */
675 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000676 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000677 THREAD_OFF (on->thread_send_dbdesc);
678 on->thread_send_dbdesc =
679 thread_add_event (master, ospf6_dbdesc_send, on, 0);
680 return;
681 }
682
683 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000684 zlog_debug ("Not duplicate dbdesc in state %s",
685 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000686 thread_add_event (master, seqnumber_mismatch, on, 0);
687 return;
688
689 default:
690 assert (0);
691 break;
paul718e3742002-12-13 20:15:29 +0000692 }
693
hasso508e53e2004-05-18 18:57:06 +0000694 /* Process LSA headers */
695 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
696 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
697 p += sizeof (struct ospf6_lsa_header))
698 {
699 struct ospf6_lsa *his, *mine;
700 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000701
hasso508e53e2004-05-18 18:57:06 +0000702 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000703
704 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000705 {
hasso6452df02004-08-15 05:52:07 +0000706 case OSPF6_SCOPE_LINKLOCAL:
707 lsdb = on->ospf6_if->lsdb;
708 break;
709 case OSPF6_SCOPE_AREA:
710 lsdb = on->ospf6_if->area->lsdb;
711 break;
712 case OSPF6_SCOPE_AS:
713 lsdb = on->ospf6_if->area->ospf6->lsdb;
714 break;
715 case OSPF6_SCOPE_RESERVED:
716 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000717 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000718 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000719 continue;
720 break;
hasso508e53e2004-05-18 18:57:06 +0000721 }
722
hasso6452df02004-08-15 05:52:07 +0000723 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
724 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000725 {
726 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000727 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000728 ospf6_lsa_delete (his);
729 thread_add_event (master, seqnumber_mismatch, on, 0);
730 return;
731 }
732
733 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
734 his->header->adv_router, lsdb);
735 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
736 {
hasso6452df02004-08-15 05:52:07 +0000737 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000738 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000739 ospf6_lsdb_add (his, on->request_list);
740 }
741 else
742 ospf6_lsa_delete (his);
743 }
744
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400745 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000746
747 /* Set sequence number to Master's */
748 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
749
750 /* schedule send lsreq */
751 if (on->thread_send_lsreq == NULL)
752 on->thread_send_lsreq =
753 thread_add_event (master, ospf6_lsreq_send, on, 0);
754
755 THREAD_OFF (on->thread_send_dbdesc);
756 on->thread_send_dbdesc =
757 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
758
759 /* save last received dbdesc */
760 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000761}
762
Paul Jakma6ac29a52008-08-15 13:45:30 +0100763static void
hasso508e53e2004-05-18 18:57:06 +0000764ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
765 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000766{
hasso508e53e2004-05-18 18:57:06 +0000767 struct ospf6_neighbor *on;
768 struct ospf6_dbdesc *dbdesc;
769
hasso508e53e2004-05-18 18:57:06 +0000770 on = ospf6_neighbor_lookup (oh->router_id, oi);
771 if (on == NULL)
772 {
773 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000774 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000775 return;
776 }
777
hasso508e53e2004-05-18 18:57:06 +0000778 dbdesc = (struct ospf6_dbdesc *)
779 ((caddr_t) oh + sizeof (struct ospf6_header));
780
781 /* Interface MTU check */
Dmitrij Tejblumab1be8a2011-04-22 19:27:54 +0400782 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000783 {
784 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000785 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000786 return;
787 }
788
789 if (dbdesc->reserved1 || dbdesc->reserved2)
790 {
791 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000792 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
793 on->name);
hasso508e53e2004-05-18 18:57:06 +0000794 dbdesc->reserved1 = 0;
795 dbdesc->reserved2 = 0;
796 }
797
798 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
799 ospf6_dbdesc_recv_master (oh, on);
800 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
801 ospf6_dbdesc_recv_slave (oh, on);
802 else
803 {
804 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000805 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000806 }
807}
808
Paul Jakma6ac29a52008-08-15 13:45:30 +0100809static void
hasso508e53e2004-05-18 18:57:06 +0000810ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
811 struct ospf6_interface *oi, struct ospf6_header *oh)
812{
813 struct ospf6_neighbor *on;
814 char *p;
815 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000816 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000817 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000818
hasso508e53e2004-05-18 18:57:06 +0000819 on = ospf6_neighbor_lookup (oh->router_id, oi);
820 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000821 {
hasso508e53e2004-05-18 18:57:06 +0000822 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000823 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000824 return;
825 }
826
hasso508e53e2004-05-18 18:57:06 +0000827 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
828 on->state != OSPF6_NEIGHBOR_LOADING &&
829 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000830 {
hasso508e53e2004-05-18 18:57:06 +0000831 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000832 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000833 return;
834 }
835
hasso508e53e2004-05-18 18:57:06 +0000836 /* Process each request */
837 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
838 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
839 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000840 {
hasso508e53e2004-05-18 18:57:06 +0000841 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000842
843 switch (OSPF6_LSA_SCOPE (e->type))
844 {
845 case OSPF6_SCOPE_LINKLOCAL:
846 lsdb = on->ospf6_if->lsdb;
847 break;
848 case OSPF6_SCOPE_AREA:
849 lsdb = on->ospf6_if->area->lsdb;
850 break;
851 case OSPF6_SCOPE_AS:
852 lsdb = on->ospf6_if->area->ospf6->lsdb;
853 break;
854 default:
855 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000856 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000857 continue;
858 break;
859 }
paul718e3742002-12-13 20:15:29 +0000860
hasso508e53e2004-05-18 18:57:06 +0000861 /* Find database copy */
862 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
863 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000864 {
hasso508e53e2004-05-18 18:57:06 +0000865 char id[16], adv_router[16];
866 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
867 {
868 inet_ntop (AF_INET, &e->id, id, sizeof (id));
869 inet_ntop (AF_INET, &e->adv_router, adv_router,
870 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000871 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
872 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000873 }
874 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000875 return;
876 }
877
hasso508e53e2004-05-18 18:57:06 +0000878 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000879 }
880
Denis Ovsienko484af2c2011-10-08 17:22:45 +0400881 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000882
hasso508e53e2004-05-18 18:57:06 +0000883 /* schedule send lsupdate */
884 THREAD_OFF (on->thread_send_lsupdate);
885 on->thread_send_lsupdate =
886 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000887}
888
Denis Ovsienko552563a2011-09-26 13:18:51 +0400889/* Verify, that the specified memory area contains exactly N valid IPv6
890 prefixes as specified by RFC5340, A.4.1. */
891static unsigned
892ospf6_prefixes_examin
893(
894 struct ospf6_prefix *current, /* start of buffer */
895 unsigned length,
896 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
897)
898{
899 u_char requested_pfx_bytes;
900 u_int32_t real_num_pfxs = 0;
901
902 while (length)
903 {
904 if (length < OSPF6_PREFIX_MIN_SIZE)
905 {
906 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
907 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
908 return MSG_NG;
909 }
910 /* safe to look deeper */
911 if (current->prefix_length > IPV6_MAX_BITLEN)
912 {
913 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
914 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
915 return MSG_NG;
916 }
917 /* covers both fixed- and variable-sized fields */
918 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
919 if (requested_pfx_bytes > length)
920 {
921 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
922 zlog_debug ("%s: undersized IPv6 prefix", __func__);
923 return MSG_NG;
924 }
925 /* next prefix */
926 length -= requested_pfx_bytes;
927 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
928 real_num_pfxs++;
929 }
930 if (real_num_pfxs != req_num_pfxs)
931 {
932 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
933 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
934 __func__, req_num_pfxs, real_num_pfxs);
935 return MSG_NG;
936 }
937 return MSG_OK;
938}
939
940/* Verify an LSA to have a valid length and dispatch further (where
941 appropriate) to check if the contents, including nested IPv6 prefixes,
942 is properly sized/aligned within the LSA. Note that this function gets
943 LSA type in network byte order, uses in host byte order and passes to
944 ospf6_lstype_name() in network byte order again. */
945static unsigned
946ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
947{
948 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
949 struct ospf6_as_external_lsa *as_external_lsa;
950 struct ospf6_link_lsa *link_lsa;
951 unsigned exp_length;
952 u_int8_t ltindex;
953 u_int16_t lsatype;
954
955 /* In case an additional minimum length constraint is defined for current
956 LSA type, make sure that this constraint is met. */
957 lsatype = ntohs (lsah->type);
958 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
959 if
960 (
961 ltindex < OSPF6_LSTYPE_SIZE &&
962 ospf6_lsa_minlen[ltindex] &&
963 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
964 )
965 {
966 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
967 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
968 return MSG_NG;
969 }
970 switch (lsatype)
971 {
972 case OSPF6_LSTYPE_ROUTER:
973 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
974 by N>=0 interface descriptions. */
975 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
976 {
977 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
978 zlog_debug ("%s: interface description alignment error", __func__);
979 return MSG_NG;
980 }
981 break;
982 case OSPF6_LSTYPE_NETWORK:
983 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
984 followed by N>=0 attached router descriptions. */
985 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
986 {
987 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
988 zlog_debug ("%s: router description alignment error", __func__);
989 return MSG_NG;
990 }
991 break;
992 case OSPF6_LSTYPE_INTER_PREFIX:
993 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
994 followed by 3-4 fields of a single IPv6 prefix. */
995 if (headeronly)
996 break;
997 return ospf6_prefixes_examin
998 (
999 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1000 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1001 1
1002 );
1003 case OSPF6_LSTYPE_INTER_ROUTER:
1004 /* RFC5340 A.4.6, fixed-size LSA. */
1005 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1006 {
1007 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1008 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1009 return MSG_NG;
1010 }
1011 break;
1012 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1013 case OSPF6_LSTYPE_TYPE_7:
1014 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1015 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1016 16 bytes of forwarding address, 4 bytes of external route tag,
1017 4 bytes of referenced link state ID. */
1018 if (headeronly)
1019 break;
1020 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1021 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1022 /* To find out if the last optional field (Referenced Link State ID) is
1023 assumed in this LSA, we need to access fixed fields of the IPv6
1024 prefix before ospf6_prefix_examin() confirms its sizing. */
1025 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1026 {
1027 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1028 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1029 return MSG_NG;
1030 }
1031 /* forwarding address */
1032 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1033 exp_length += 16;
1034 /* external route tag */
1035 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1036 exp_length += 4;
1037 /* referenced link state ID */
1038 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1039 exp_length += 4;
1040 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1041 this check does not include any IPv6 prefix fields. */
1042 if (exp_length > lsalen)
1043 {
1044 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1045 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1046 return MSG_NG;
1047 }
1048 /* The last call completely covers the remainder (IPv6 prefix). */
1049 return ospf6_prefixes_examin
1050 (
1051 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1052 lsalen - exp_length,
1053 1
1054 );
1055 case OSPF6_LSTYPE_LINK:
1056 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1057 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1058 if (headeronly)
1059 break;
1060 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1061 return ospf6_prefixes_examin
1062 (
1063 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1064 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1065 ntohl (link_lsa->prefix_num) /* 32 bits */
1066 );
1067 case OSPF6_LSTYPE_INTRA_PREFIX:
1068 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1069 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1070 if (headeronly)
1071 break;
1072 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1073 return ospf6_prefixes_examin
1074 (
1075 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1076 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1077 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1078 );
1079 }
1080 /* No additional validation is possible for unknown LSA types, which are
1081 themselves valid in OPSFv3, hence the default decision is to accept. */
1082 return MSG_OK;
1083}
1084
1085/* Verify if the provided input buffer is a valid sequence of LSAs. This
1086 includes verification of LSA blocks length/alignment and dispatching
1087 of deeper-level checks. */
1088static unsigned
1089ospf6_lsaseq_examin
1090(
1091 struct ospf6_lsa_header *lsah, /* start of buffered data */
1092 size_t length,
1093 const u_char headeronly,
1094 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1095 and treat the difference as an error. */
1096 const u_int32_t declared_num_lsas
1097)
1098{
1099 u_int32_t counted_lsas = 0;
1100
1101 while (length)
1102 {
1103 u_int16_t lsalen;
1104 if (length < OSPF6_LSA_HEADER_SIZE)
1105 {
1106 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1107 zlog_debug ("%s: undersized (%u B) trailing (#%u) LSA header",
1108 __func__, length, counted_lsas);
1109 return MSG_NG;
1110 }
1111 /* save on ntohs() calls here and in the LSA validator */
1112 lsalen = OSPF6_LSA_SIZE (lsah);
1113 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1114 {
1115 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1116 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1117 __func__, counted_lsas, lsalen);
1118 return MSG_NG;
1119 }
1120 if (headeronly)
1121 {
1122 /* less checks here and in ospf6_lsa_examin() */
1123 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1124 {
1125 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1126 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1127 ospf6_lstype_name (lsah->type), counted_lsas);
1128 return MSG_NG;
1129 }
1130 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1131 length -= OSPF6_LSA_HEADER_SIZE;
1132 }
1133 else
1134 {
1135 /* make sure the input buffer is deep enough before further checks */
1136 if (lsalen > length)
1137 {
1138 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1139 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %u B",
1140 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1141 return MSG_NG;
1142 }
1143 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1144 {
1145 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1146 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1147 ospf6_lstype_name (lsah->type), counted_lsas);
1148 return MSG_NG;
1149 }
1150 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1151 length -= lsalen;
1152 }
1153 counted_lsas++;
1154 }
1155
1156 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1157 {
1158 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1159 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1160 __func__, declared_num_lsas, counted_lsas);
1161 return MSG_NG;
1162 }
1163 return MSG_OK;
1164}
1165
1166/* Verify a complete OSPF packet for proper sizing/alignment. */
1167static unsigned
1168ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1169{
1170 struct ospf6_lsupdate *lsupd;
1171 unsigned test;
1172
1173 /* length, 1st approximation */
1174 if (bytesonwire < OSPF6_HEADER_SIZE)
1175 {
1176 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1177 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1178 return MSG_NG;
1179 }
1180 /* Now it is safe to access header fields. */
1181 if (bytesonwire != ntohs (oh->length))
1182 {
1183 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1184 zlog_debug ("%s: packet length error (%u real, %u declared)",
1185 __func__, bytesonwire, ntohs (oh->length));
1186 return MSG_NG;
1187 }
1188 /* version check */
1189 if (oh->version != OSPFV3_VERSION)
1190 {
1191 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1192 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1193 return MSG_NG;
1194 }
1195 /* length, 2nd approximation */
1196 if
1197 (
1198 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1199 ospf6_packet_minlen[oh->type] &&
1200 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1201 )
1202 {
1203 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1204 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
Denis Ovsienkoed721562011-10-14 21:59:58 +04001205 bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-09-26 13:18:51 +04001206 return MSG_NG;
1207 }
1208 /* type-specific deeper validation */
1209 switch (oh->type)
1210 {
1211 case OSPF6_MESSAGE_TYPE_HELLO:
1212 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1213 by N>=0 router-IDs. */
1214 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1215 return MSG_OK;
1216 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1217 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienkoed721562011-10-14 21:59:58 +04001218 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-09-26 13:18:51 +04001219 return MSG_NG;
1220 case OSPF6_MESSAGE_TYPE_DBDESC:
1221 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1222 by N>=0 header-only LSAs. */
1223 test = ospf6_lsaseq_examin
1224 (
1225 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1226 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1227 1,
1228 0
1229 );
1230 break;
1231 case OSPF6_MESSAGE_TYPE_LSREQ:
1232 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1233 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1234 return MSG_OK;
1235 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1236 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienkoed721562011-10-14 21:59:58 +04001237 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-09-26 13:18:51 +04001238 return MSG_NG;
1239 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1240 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1241 by N>=0 full LSAs (with N declared beforehand). */
1242 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1243 test = ospf6_lsaseq_examin
1244 (
1245 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1246 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1247 0,
1248 ntohl (lsupd->lsa_number) /* 32 bits */
1249 );
1250 break;
1251 case OSPF6_MESSAGE_TYPE_LSACK:
1252 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1253 test = ospf6_lsaseq_examin
1254 (
1255 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1256 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1257 1,
1258 0
1259 );
1260 break;
1261 default:
1262 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1263 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1264 return MSG_NG;
1265 }
1266 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Denis Ovsienkoed721562011-10-14 21:59:58 +04001267 zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-09-26 13:18:51 +04001268 return test;
1269}
1270
1271/* Verify particular fields of otherwise correct received OSPF packet to
1272 meet the requirements of RFC. */
1273static int
1274ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1275{
1276 char buf[2][INET_ADDRSTRLEN];
1277
1278 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1279 return MSG_NG;
1280
1281 /* Area-ID check */
1282 if (oh->area_id != oi->area->area_id)
1283 {
1284 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1285 {
1286 if (oh->area_id == BACKBONE_AREA_ID)
1287 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1288 else
1289 zlog_debug
1290 (
1291 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1292 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1293 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1294 );
1295 }
1296 return MSG_NG;
1297 }
1298
1299 /* Instance-ID check */
1300 if (oh->instance_id != oi->instance_id)
1301 {
1302 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1303 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1304 return MSG_NG;
1305 }
1306
1307 /* Router-ID check */
1308 if (oh->router_id == oi->area->ospf6->router_id)
1309 {
1310 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1311 return MSG_NG;
1312 }
1313 return MSG_OK;
1314}
1315
Paul Jakma6ac29a52008-08-15 13:45:30 +01001316static void
hasso508e53e2004-05-18 18:57:06 +00001317ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1318 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001319{
hasso508e53e2004-05-18 18:57:06 +00001320 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001321 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001322 char *p;
paul718e3742002-12-13 20:15:29 +00001323
hasso508e53e2004-05-18 18:57:06 +00001324 on = ospf6_neighbor_lookup (oh->router_id, oi);
1325 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001326 {
hasso508e53e2004-05-18 18:57:06 +00001327 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001328 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001329 return;
1330 }
1331
hasso508e53e2004-05-18 18:57:06 +00001332 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1333 on->state != OSPF6_NEIGHBOR_LOADING &&
1334 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001335 {
hasso508e53e2004-05-18 18:57:06 +00001336 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001337 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001338 return;
1339 }
1340
hasso508e53e2004-05-18 18:57:06 +00001341 lsupdate = (struct ospf6_lsupdate *)
1342 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001343
hasso508e53e2004-05-18 18:57:06 +00001344 /* Process LSAs */
1345 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1346 p < OSPF6_MESSAGE_END (oh) &&
1347 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1348 p += OSPF6_LSA_SIZE (p))
1349 {
hasso6452df02004-08-15 05:52:07 +00001350 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001351 }
1352
Denis Ovsienko484af2c2011-10-08 17:22:45 +04001353 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001354
1355 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1356 with the proper Link State Update packet(s), the Link state request
1357 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001358 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001359 can be recognized as a response to our previous LS Request */
1360 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1361 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1362 on->state == OSPF6_NEIGHBOR_LOADING))
1363 {
1364 THREAD_OFF (on->thread_send_lsreq);
1365 on->thread_send_lsreq =
1366 thread_add_event (master, ospf6_lsreq_send, on, 0);
1367 }
paul718e3742002-12-13 20:15:29 +00001368}
1369
Paul Jakma6ac29a52008-08-15 13:45:30 +01001370static void
hasso508e53e2004-05-18 18:57:06 +00001371ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1372 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001373{
hasso508e53e2004-05-18 18:57:06 +00001374 struct ospf6_neighbor *on;
1375 char *p;
1376 struct ospf6_lsa *his, *mine;
1377 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001378
hasso508e53e2004-05-18 18:57:06 +00001379 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001380
hasso508e53e2004-05-18 18:57:06 +00001381 on = ospf6_neighbor_lookup (oh->router_id, oi);
1382 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001383 {
hasso508e53e2004-05-18 18:57:06 +00001384 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001385 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001386 return;
1387 }
1388
hasso508e53e2004-05-18 18:57:06 +00001389 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1390 on->state != OSPF6_NEIGHBOR_LOADING &&
1391 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001392 {
hasso508e53e2004-05-18 18:57:06 +00001393 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001394 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001395 return;
1396 }
1397
hasso508e53e2004-05-18 18:57:06 +00001398 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1399 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1400 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001401 {
hasso508e53e2004-05-18 18:57:06 +00001402 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001403
hasso6452df02004-08-15 05:52:07 +00001404 switch (OSPF6_LSA_SCOPE (his->header->type))
1405 {
1406 case OSPF6_SCOPE_LINKLOCAL:
1407 lsdb = on->ospf6_if->lsdb;
1408 break;
1409 case OSPF6_SCOPE_AREA:
1410 lsdb = on->ospf6_if->area->lsdb;
1411 break;
1412 case OSPF6_SCOPE_AS:
1413 lsdb = on->ospf6_if->area->ospf6->lsdb;
1414 break;
1415 case OSPF6_SCOPE_RESERVED:
1416 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001417 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001418 ospf6_lsa_delete (his);
1419 continue;
1420 break;
1421 }
1422
1423 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001424 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001425
1426 /* Find database copy */
1427 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1428 his->header->adv_router, lsdb);
1429 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001430 {
hasso508e53e2004-05-18 18:57:06 +00001431 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001432 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001433 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001434 continue;
1435 }
1436
hasso508e53e2004-05-18 18:57:06 +00001437 /* Check if the LSA is on his retrans-list */
1438 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1439 his->header->adv_router, on->retrans_list);
1440 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001441 {
hasso508e53e2004-05-18 18:57:06 +00001442 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001443 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001444 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001445 continue;
1446 }
1447
hasso508e53e2004-05-18 18:57:06 +00001448 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001449 {
hasso508e53e2004-05-18 18:57:06 +00001450 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001451 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001452 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001453 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001454 ospf6_lsa_delete (his);
1455 continue;
paul718e3742002-12-13 20:15:29 +00001456 }
1457
hasso6452df02004-08-15 05:52:07 +00001458 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001459 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1460 on->name);
hasso508e53e2004-05-18 18:57:06 +00001461
Paul Jakma932bf192006-05-15 10:42:24 +00001462 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001463 if (OSPF6_LSA_IS_MAXAGE (mine))
1464 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001465 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001466 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001467 }
1468
Denis Ovsienko484af2c2011-10-08 17:22:45 +04001469 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001470}
1471
Paul Jakma6ac29a52008-08-15 13:45:30 +01001472static u_char *recvbuf = NULL;
1473static u_char *sendbuf = NULL;
1474static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001475
1476int
paul0c083ee2004-10-10 12:54:58 +00001477ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001478{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001479 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001480
1481 if (size <= iobuflen)
1482 return iobuflen;
1483
1484 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1485 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1486 if (recvnew == NULL || sendnew == NULL)
1487 {
hassob596c712004-07-09 18:33:43 +00001488 if (recvnew)
1489 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1490 if (sendnew)
1491 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001492 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001493 return iobuflen;
1494 }
1495
1496 if (recvbuf)
1497 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1498 if (sendbuf)
1499 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1500 recvbuf = recvnew;
1501 sendbuf = sendnew;
1502 iobuflen = size;
1503
1504 return iobuflen;
1505}
paul718e3742002-12-13 20:15:29 +00001506
Tom Goff36d3e8d2010-11-10 13:01:41 -08001507void
1508ospf6_message_terminate (void)
1509{
1510 if (recvbuf)
1511 {
1512 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1513 recvbuf = NULL;
1514 }
1515
1516 if (sendbuf)
1517 {
1518 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1519 sendbuf = NULL;
1520 }
1521
1522 iobuflen = 0;
1523}
1524
paul718e3742002-12-13 20:15:29 +00001525int
1526ospf6_receive (struct thread *thread)
1527{
paul0c083ee2004-10-10 12:54:58 +00001528 int sockfd;
1529 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001530 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001531 struct in6_addr src, dst;
1532 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001533 struct iovec iovector[2];
1534 struct ospf6_interface *oi;
1535 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001536
1537 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001538 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001539 thread_add_read (master, ospf6_receive, NULL, sockfd);
1540
1541 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001542 memset (&src, 0, sizeof (src));
1543 memset (&dst, 0, sizeof (dst));
1544 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001545 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001546 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001547 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001548 iovector[1].iov_base = NULL;
1549 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001550
1551 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001552 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001553 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001554 {
hasso508e53e2004-05-18 18:57:06 +00001555 zlog_err ("Excess message read");
1556 return 0;
1557 }
paul718e3742002-12-13 20:15:29 +00001558
hasso508e53e2004-05-18 18:57:06 +00001559 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1560 if (oi == NULL || oi->area == NULL)
1561 {
hassoc6487d62004-12-24 06:00:11 +00001562 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001563 return 0;
1564 }
Denis Ovsienko552563a2011-09-26 13:18:51 +04001565 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1566 {
1567 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1568 zlog_debug ("%s: Ignore message on passive interface %s",
1569 __func__, oi->interface->name);
1570 return 0;
1571 }
hasso508e53e2004-05-18 18:57:06 +00001572
1573 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienko552563a2011-09-26 13:18:51 +04001574 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1575 return 0;
1576
1577 /* Being here means, that no sizing/alignment issues were detected in
1578 the input packet. This renders the additional checks performed below
1579 and also in the type-specific dispatching functions a dead code,
1580 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001581
1582 /* Log */
1583 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1584 {
1585 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1586 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001587 zlog_debug ("%s received on %s",
Denis Ovsienkoed721562011-10-14 21:59:58 +04001588 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001589 zlog_debug (" src: %s", srcname);
1590 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001591
1592 switch (oh->type)
1593 {
1594 case OSPF6_MESSAGE_TYPE_HELLO:
1595 ospf6_hello_print (oh);
1596 break;
1597 case OSPF6_MESSAGE_TYPE_DBDESC:
1598 ospf6_dbdesc_print (oh);
1599 break;
1600 case OSPF6_MESSAGE_TYPE_LSREQ:
1601 ospf6_lsreq_print (oh);
1602 break;
1603 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1604 ospf6_lsupdate_print (oh);
1605 break;
1606 case OSPF6_MESSAGE_TYPE_LSACK:
1607 ospf6_lsack_print (oh);
1608 break;
1609 default:
Denis Ovsienko484af2c2011-10-08 17:22:45 +04001610 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001611 }
1612 }
1613
hasso508e53e2004-05-18 18:57:06 +00001614 switch (oh->type)
1615 {
1616 case OSPF6_MESSAGE_TYPE_HELLO:
1617 ospf6_hello_recv (&src, &dst, oi, oh);
1618 break;
1619
1620 case OSPF6_MESSAGE_TYPE_DBDESC:
1621 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1622 break;
1623
1624 case OSPF6_MESSAGE_TYPE_LSREQ:
1625 ospf6_lsreq_recv (&src, &dst, oi, oh);
1626 break;
1627
1628 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1629 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1630 break;
1631
1632 case OSPF6_MESSAGE_TYPE_LSACK:
1633 ospf6_lsack_recv (&src, &dst, oi, oh);
1634 break;
1635
1636 default:
Denis Ovsienko484af2c2011-10-08 17:22:45 +04001637 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001638 }
1639
1640 return 0;
1641}
1642
Paul Jakma6ac29a52008-08-15 13:45:30 +01001643static void
hasso508e53e2004-05-18 18:57:06 +00001644ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1645 struct ospf6_interface *oi, struct ospf6_header *oh)
1646{
1647 int len;
1648 char srcname[64], dstname[64];
1649 struct iovec iovector[2];
1650
1651 /* initialize */
1652 iovector[0].iov_base = (caddr_t) oh;
1653 iovector[0].iov_len = ntohs (oh->length);
1654 iovector[1].iov_base = NULL;
1655 iovector[1].iov_len = 0;
1656
1657 /* fill OSPF header */
1658 oh->version = OSPFV3_VERSION;
1659 /* message type must be set before */
1660 /* message length must be set before */
1661 oh->router_id = oi->area->ospf6->router_id;
1662 oh->area_id = oi->area->area_id;
1663 /* checksum is calculated by kernel */
1664 oh->instance_id = oi->instance_id;
1665 oh->reserved = 0;
1666
1667 /* Log */
1668 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1669 {
1670 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1671 if (src)
1672 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1673 else
1674 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001675 zlog_debug ("%s send on %s",
Denis Ovsienkoed721562011-10-14 21:59:58 +04001676 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001677 zlog_debug (" src: %s", srcname);
1678 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001679
1680 switch (oh->type)
1681 {
1682 case OSPF6_MESSAGE_TYPE_HELLO:
1683 ospf6_hello_print (oh);
1684 break;
1685 case OSPF6_MESSAGE_TYPE_DBDESC:
1686 ospf6_dbdesc_print (oh);
1687 break;
1688 case OSPF6_MESSAGE_TYPE_LSREQ:
1689 ospf6_lsreq_print (oh);
1690 break;
1691 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1692 ospf6_lsupdate_print (oh);
1693 break;
1694 case OSPF6_MESSAGE_TYPE_LSACK:
1695 ospf6_lsack_print (oh);
1696 break;
1697 default:
hassoc6487d62004-12-24 06:00:11 +00001698 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001699 assert (0);
1700 break;
1701 }
1702 }
1703
1704 /* send message */
1705 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1706 if (len != ntohs (oh->length))
1707 zlog_err ("Could not send entire message");
1708}
1709
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001710static int
1711ospf6_packet_max(struct ospf6_interface *oi)
1712{
1713 return oi->ifmtu - sizeof(struct ip6_hdr);
1714}
1715
hasso508e53e2004-05-18 18:57:06 +00001716int
1717ospf6_hello_send (struct thread *thread)
1718{
1719 struct ospf6_interface *oi;
1720 struct ospf6_header *oh;
1721 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001722 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001723 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001724 struct ospf6_neighbor *on;
1725
1726 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1727 oi->thread_send_hello = (struct thread *) NULL;
1728
1729 if (oi->state <= OSPF6_INTERFACE_DOWN)
1730 {
1731 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001732 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001733 oi->interface->name);
1734 return 0;
1735 }
1736
1737 /* set next thread */
1738 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1739 oi, oi->hello_interval);
1740
hasso3b4cd3a2004-05-18 19:28:32 +00001741 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001742 oh = (struct ospf6_header *) sendbuf;
1743 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1744
1745 hello->interface_id = htonl (oi->interface->ifindex);
1746 hello->priority = oi->priority;
1747 hello->options[0] = oi->area->options[0];
1748 hello->options[1] = oi->area->options[1];
1749 hello->options[2] = oi->area->options[2];
1750 hello->hello_interval = htons (oi->hello_interval);
1751 hello->dead_interval = htons (oi->dead_interval);
1752 hello->drouter = oi->drouter;
1753 hello->bdrouter = oi->bdrouter;
1754
Paul Jakma6ac29a52008-08-15 13:45:30 +01001755 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001756
paul1eb8ef22005-04-07 07:30:20 +00001757 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001758 {
hasso508e53e2004-05-18 18:57:06 +00001759 if (on->state < OSPF6_NEIGHBOR_INIT)
1760 continue;
1761
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001762 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001763 {
1764 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001765 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001766 break;
1767 }
1768
1769 memcpy (p, &on->router_id, sizeof (u_int32_t));
1770 p += sizeof (u_int32_t);
1771 }
1772
1773 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1774 oh->length = htons (p - sendbuf);
1775
1776 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1777 return 0;
1778}
1779
1780int
1781ospf6_dbdesc_send (struct thread *thread)
1782{
1783 struct ospf6_neighbor *on;
1784 struct ospf6_header *oh;
1785 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001786 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001787 struct ospf6_lsa *lsa;
1788
1789 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1790 on->thread_send_dbdesc = (struct thread *) NULL;
1791
1792 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1793 {
1794 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001795 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1796 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001797 return 0;
1798 }
1799
1800 /* set next thread if master */
1801 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1802 on->thread_send_dbdesc =
1803 thread_add_timer (master, ospf6_dbdesc_send, on,
1804 on->ospf6_if->rxmt_interval);
1805
hasso3b4cd3a2004-05-18 19:28:32 +00001806 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001807 oh = (struct ospf6_header *) sendbuf;
1808 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1809 sizeof (struct ospf6_header));
1810
1811 /* if this is initial one, initialize sequence number for DbDesc */
1812 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1813 {
1814 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001815 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001816 tv.tv_sec = 1;
1817 on->dbdesc_seqnum = tv.tv_sec;
1818 }
1819
1820 dbdesc->options[0] = on->ospf6_if->area->options[0];
1821 dbdesc->options[1] = on->ospf6_if->area->options[1];
1822 dbdesc->options[2] = on->ospf6_if->area->options[2];
1823 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1824 dbdesc->bits = on->dbdesc_bits;
1825 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1826
1827 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001828 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001829 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1830 {
1831 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1832 lsa = ospf6_lsdb_next (lsa))
1833 {
1834 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1835
1836 /* MTU check */
1837 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001838 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001839 {
1840 ospf6_lsa_unlock (lsa);
1841 break;
1842 }
1843 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1844 p += sizeof (struct ospf6_lsa_header);
1845 }
1846 }
1847
1848 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1849 oh->length = htons (p - sendbuf);
1850
1851 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1852 on->ospf6_if, oh);
1853 return 0;
1854}
1855
1856int
1857ospf6_dbdesc_send_newone (struct thread *thread)
1858{
1859 struct ospf6_neighbor *on;
1860 struct ospf6_lsa *lsa;
1861 unsigned int size = 0;
1862
1863 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001864 ospf6_lsdb_remove_all (on->dbdesc_list);
1865
1866 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1867 so that ospf6_send_dbdesc () can send those LSAs */
1868 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1869 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1870 lsa = ospf6_lsdb_next (lsa))
1871 {
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001872 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001873 {
1874 ospf6_lsa_unlock (lsa);
1875 break;
1876 }
1877
hasso508e53e2004-05-18 18:57:06 +00001878 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1879 ospf6_lsdb_remove (lsa, on->summary_list);
1880 size += sizeof (struct ospf6_lsa_header);
1881 }
1882
1883 if (on->summary_list->count == 0)
1884 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1885
1886 /* If slave, More bit check must be done here */
1887 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1888 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1889 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1890 thread_add_event (master, exchange_done, on, 0);
1891
1892 thread_execute (master, ospf6_dbdesc_send, on, 0);
1893 return 0;
1894}
1895
1896int
1897ospf6_lsreq_send (struct thread *thread)
1898{
1899 struct ospf6_neighbor *on;
1900 struct ospf6_header *oh;
1901 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001902 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001903 struct ospf6_lsa *lsa;
1904
1905 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1906 on->thread_send_lsreq = (struct thread *) NULL;
1907
1908 /* LSReq will be sent only in ExStart or Loading */
1909 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1910 on->state != OSPF6_NEIGHBOR_LOADING)
1911 {
1912 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001913 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1914 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001915 return 0;
1916 }
1917
1918 /* schedule loading_done if request list is empty */
1919 if (on->request_list->count == 0)
1920 {
1921 thread_add_event (master, loading_done, on, 0);
1922 return 0;
1923 }
1924
1925 /* set next thread */
1926 on->thread_send_lsreq =
1927 thread_add_timer (master, ospf6_lsreq_send, on,
1928 on->ospf6_if->rxmt_interval);
1929
hasso3b4cd3a2004-05-18 19:28:32 +00001930 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001931 oh = (struct ospf6_header *) sendbuf;
1932
1933 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001934 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001935 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1936 lsa = ospf6_lsdb_next (lsa))
1937 {
1938 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001939 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001940 {
1941 ospf6_lsa_unlock (lsa);
1942 break;
1943 }
1944
1945 e = (struct ospf6_lsreq_entry *) p;
1946 e->type = lsa->header->type;
1947 e->id = lsa->header->id;
1948 e->adv_router = lsa->header->adv_router;
1949 p += sizeof (struct ospf6_lsreq_entry);
1950 }
1951
1952 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1953 oh->length = htons (p - sendbuf);
1954
1955 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1956 on->ospf6_if, oh);
1957 return 0;
1958}
1959
1960int
1961ospf6_lsupdate_send_neighbor (struct thread *thread)
1962{
1963 struct ospf6_neighbor *on;
1964 struct ospf6_header *oh;
1965 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001966 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001967 int num;
1968 struct ospf6_lsa *lsa;
1969
1970 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1971 on->thread_send_lsupdate = (struct thread *) NULL;
1972
hasso6452df02004-08-15 05:52:07 +00001973 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001974 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001975
hasso508e53e2004-05-18 18:57:06 +00001976 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1977 {
1978 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001979 zlog_debug ("Quit to send (neighbor state %s)",
1980 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001981 return 0;
1982 }
1983
1984 /* if we have nothing to send, return */
1985 if (on->lsupdate_list->count == 0 &&
1986 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001987 {
1988 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001989 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001990 return 0;
1991 }
hasso508e53e2004-05-18 18:57:06 +00001992
hasso3b4cd3a2004-05-18 19:28:32 +00001993 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001994 oh = (struct ospf6_header *) sendbuf;
1995 lsupdate = (struct ospf6_lsupdate *)
1996 ((caddr_t) oh + sizeof (struct ospf6_header));
1997
Paul Jakma6ac29a52008-08-15 13:45:30 +01001998 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001999 num = 0;
2000
2001 /* lsupdate_list lists those LSA which doesn't need to be
2002 retransmitted. remove those from the list */
2003 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2004 lsa = ospf6_lsdb_next (lsa))
2005 {
2006 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002007 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002008 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002009 {
2010 ospf6_lsa_unlock (lsa);
2011 break;
2012 }
2013
hasso508e53e2004-05-18 18:57:06 +00002014 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2015 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2016 p += OSPF6_LSA_SIZE (lsa->header);
2017 num++;
2018
2019 assert (lsa->lock == 2);
2020 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2021 }
2022
2023 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2024 lsa = ospf6_lsdb_next (lsa))
2025 {
2026 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002027 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002028 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002029 {
2030 ospf6_lsa_unlock (lsa);
2031 break;
2032 }
2033
hasso508e53e2004-05-18 18:57:06 +00002034 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2035 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2036 p += OSPF6_LSA_SIZE (lsa->header);
2037 num++;
2038 }
2039
2040 lsupdate->lsa_number = htonl (num);
2041
2042 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2043 oh->length = htons (p - sendbuf);
2044
2045 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2046 on->ospf6_if, oh);
2047
2048 if (on->lsupdate_list->count != 0 ||
2049 on->retrans_list->count != 0)
2050 {
2051 if (on->lsupdate_list->count != 0)
2052 on->thread_send_lsupdate =
2053 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2054 else
2055 on->thread_send_lsupdate =
2056 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2057 on->ospf6_if->rxmt_interval);
2058 }
2059
2060 return 0;
2061}
2062
2063int
2064ospf6_lsupdate_send_interface (struct thread *thread)
2065{
2066 struct ospf6_interface *oi;
2067 struct ospf6_header *oh;
2068 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002069 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002070 int num;
2071 struct ospf6_lsa *lsa;
2072
2073 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2074 oi->thread_send_lsupdate = (struct thread *) NULL;
2075
2076 if (oi->state <= OSPF6_INTERFACE_WAITING)
2077 {
2078 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002079 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2080 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002081 return 0;
2082 }
2083
2084 /* if we have nothing to send, return */
2085 if (oi->lsupdate_list->count == 0)
2086 return 0;
2087
hasso3b4cd3a2004-05-18 19:28:32 +00002088 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002089 oh = (struct ospf6_header *) sendbuf;
2090 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
2091 sizeof (struct ospf6_header));
2092
Paul Jakma6ac29a52008-08-15 13:45:30 +01002093 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002094 num = 0;
2095
2096 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2097 lsa = ospf6_lsdb_next (lsa))
2098 {
2099 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002100 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002101 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002102 {
2103 ospf6_lsa_unlock (lsa);
2104 break;
2105 }
2106
hasso508e53e2004-05-18 18:57:06 +00002107 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2108 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2109 p += OSPF6_LSA_SIZE (lsa->header);
2110 num++;
2111
2112 assert (lsa->lock == 2);
2113 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2114 }
2115
2116 lsupdate->lsa_number = htonl (num);
2117
2118 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2119 oh->length = htons (p - sendbuf);
2120
2121 if (oi->state == OSPF6_INTERFACE_DR ||
2122 oi->state == OSPF6_INTERFACE_BDR)
2123 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2124 else
2125 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2126
2127 if (oi->lsupdate_list->count > 0)
2128 {
2129 oi->thread_send_lsupdate =
2130 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2131 }
2132
2133 return 0;
2134}
2135
2136int
2137ospf6_lsack_send_neighbor (struct thread *thread)
2138{
2139 struct ospf6_neighbor *on;
2140 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002141 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002142 struct ospf6_lsa *lsa;
2143
2144 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2145 on->thread_send_lsack = (struct thread *) NULL;
2146
2147 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2148 {
2149 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002150 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2151 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002152 return 0;
2153 }
2154
2155 /* if we have nothing to send, return */
2156 if (on->lsack_list->count == 0)
2157 return 0;
2158
hasso3b4cd3a2004-05-18 19:28:32 +00002159 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002160 oh = (struct ospf6_header *) sendbuf;
2161
Paul Jakma6ac29a52008-08-15 13:45:30 +01002162 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002163
2164 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2165 lsa = ospf6_lsdb_next (lsa))
2166 {
2167 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002168 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002169 {
2170 /* if we run out of packet size/space here,
2171 better to try again soon. */
2172 THREAD_OFF (on->thread_send_lsack);
2173 on->thread_send_lsack =
2174 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2175
2176 ospf6_lsa_unlock (lsa);
2177 break;
2178 }
2179
2180 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2181 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2182 p += sizeof (struct ospf6_lsa_header);
2183
2184 assert (lsa->lock == 2);
2185 ospf6_lsdb_remove (lsa, on->lsack_list);
2186 }
2187
2188 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2189 oh->length = htons (p - sendbuf);
2190
2191 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2192 on->ospf6_if, oh);
2193 return 0;
2194}
2195
2196int
2197ospf6_lsack_send_interface (struct thread *thread)
2198{
2199 struct ospf6_interface *oi;
2200 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002201 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002202 struct ospf6_lsa *lsa;
2203
2204 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2205 oi->thread_send_lsack = (struct thread *) NULL;
2206
2207 if (oi->state <= OSPF6_INTERFACE_WAITING)
2208 {
2209 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002210 zlog_debug ("Quit to send LSAck to interface %s state %s",
2211 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002212 return 0;
2213 }
2214
2215 /* if we have nothing to send, return */
2216 if (oi->lsack_list->count == 0)
2217 return 0;
2218
hasso3b4cd3a2004-05-18 19:28:32 +00002219 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002220 oh = (struct ospf6_header *) sendbuf;
2221
Paul Jakma6ac29a52008-08-15 13:45:30 +01002222 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002223
2224 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2225 lsa = ospf6_lsdb_next (lsa))
2226 {
2227 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002228 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002229 {
2230 /* if we run out of packet size/space here,
2231 better to try again soon. */
2232 THREAD_OFF (oi->thread_send_lsack);
2233 oi->thread_send_lsack =
2234 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2235
2236 ospf6_lsa_unlock (lsa);
2237 break;
2238 }
2239
2240 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2241 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2242 p += sizeof (struct ospf6_lsa_header);
2243
2244 assert (lsa->lock == 2);
2245 ospf6_lsdb_remove (lsa, oi->lsack_list);
2246 }
2247
2248 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2249 oh->length = htons (p - sendbuf);
2250
2251 if (oi->state == OSPF6_INTERFACE_DR ||
2252 oi->state == OSPF6_INTERFACE_BDR)
2253 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2254 else
2255 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2256
2257 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2258 {
2259 oi->thread_send_lsack =
2260 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2261 }
paul718e3742002-12-13 20:15:29 +00002262
2263 return 0;
2264}
2265
2266
hasso508e53e2004-05-18 18:57:06 +00002267/* Commands */
2268DEFUN (debug_ospf6_message,
2269 debug_ospf6_message_cmd,
2270 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2271 DEBUG_STR
2272 OSPF6_STR
2273 "Debug OSPFv3 message\n"
2274 "Debug Unknown message\n"
2275 "Debug Hello message\n"
2276 "Debug Database Description message\n"
2277 "Debug Link State Request message\n"
2278 "Debug Link State Update message\n"
2279 "Debug Link State Acknowledgement message\n"
2280 "Debug All message\n"
2281 )
paul718e3742002-12-13 20:15:29 +00002282{
hasso508e53e2004-05-18 18:57:06 +00002283 unsigned char level = 0;
2284 int type = 0;
paul718e3742002-12-13 20:15:29 +00002285 int i;
2286
hasso508e53e2004-05-18 18:57:06 +00002287 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002288
hasso508e53e2004-05-18 18:57:06 +00002289 /* check type */
2290 if (! strncmp (argv[0], "u", 1))
2291 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2292 else if (! strncmp (argv[0], "h", 1))
2293 type = OSPF6_MESSAGE_TYPE_HELLO;
2294 else if (! strncmp (argv[0], "d", 1))
2295 type = OSPF6_MESSAGE_TYPE_DBDESC;
2296 else if (! strncmp (argv[0], "lsr", 3))
2297 type = OSPF6_MESSAGE_TYPE_LSREQ;
2298 else if (! strncmp (argv[0], "lsu", 3))
2299 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2300 else if (! strncmp (argv[0], "lsa", 3))
2301 type = OSPF6_MESSAGE_TYPE_LSACK;
2302 else if (! strncmp (argv[0], "a", 1))
2303 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002304
hasso508e53e2004-05-18 18:57:06 +00002305 if (argc == 1)
2306 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2307 else if (! strncmp (argv[1], "s", 1))
2308 level = OSPF6_DEBUG_MESSAGE_SEND;
2309 else if (! strncmp (argv[1], "r", 1))
2310 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002311
hasso508e53e2004-05-18 18:57:06 +00002312 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002313 {
hasso508e53e2004-05-18 18:57:06 +00002314 for (i = 0; i < 6; i++)
2315 OSPF6_DEBUG_MESSAGE_ON (i, level);
2316 }
2317 else
2318 OSPF6_DEBUG_MESSAGE_ON (type, level);
2319
2320 return CMD_SUCCESS;
2321}
2322
2323ALIAS (debug_ospf6_message,
2324 debug_ospf6_message_sendrecv_cmd,
2325 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2326 DEBUG_STR
2327 OSPF6_STR
2328 "Debug OSPFv3 message\n"
2329 "Debug Unknown message\n"
2330 "Debug Hello message\n"
2331 "Debug Database Description message\n"
2332 "Debug Link State Request message\n"
2333 "Debug Link State Update message\n"
2334 "Debug Link State Acknowledgement message\n"
2335 "Debug All message\n"
2336 "Debug only sending message\n"
2337 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002338 )
hasso508e53e2004-05-18 18:57:06 +00002339
2340
2341DEFUN (no_debug_ospf6_message,
2342 no_debug_ospf6_message_cmd,
2343 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2344 NO_STR
2345 DEBUG_STR
2346 OSPF6_STR
2347 "Debug OSPFv3 message\n"
2348 "Debug Unknown message\n"
2349 "Debug Hello message\n"
2350 "Debug Database Description message\n"
2351 "Debug Link State Request message\n"
2352 "Debug Link State Update message\n"
2353 "Debug Link State Acknowledgement message\n"
2354 "Debug All message\n"
2355 )
2356{
2357 unsigned char level = 0;
2358 int type = 0;
2359 int i;
2360
2361 assert (argc > 0);
2362
2363 /* check type */
2364 if (! strncmp (argv[0], "u", 1))
2365 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2366 else if (! strncmp (argv[0], "h", 1))
2367 type = OSPF6_MESSAGE_TYPE_HELLO;
2368 else if (! strncmp (argv[0], "d", 1))
2369 type = OSPF6_MESSAGE_TYPE_DBDESC;
2370 else if (! strncmp (argv[0], "lsr", 3))
2371 type = OSPF6_MESSAGE_TYPE_LSREQ;
2372 else if (! strncmp (argv[0], "lsu", 3))
2373 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2374 else if (! strncmp (argv[0], "lsa", 3))
2375 type = OSPF6_MESSAGE_TYPE_LSACK;
2376 else if (! strncmp (argv[0], "a", 1))
2377 type = OSPF6_MESSAGE_TYPE_ALL;
2378
2379 if (argc == 1)
2380 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2381 else if (! strncmp (argv[1], "s", 1))
2382 level = OSPF6_DEBUG_MESSAGE_SEND;
2383 else if (! strncmp (argv[1], "r", 1))
2384 level = OSPF6_DEBUG_MESSAGE_RECV;
2385
2386 if (type == OSPF6_MESSAGE_TYPE_ALL)
2387 {
2388 for (i = 0; i < 6; i++)
2389 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2390 }
2391 else
2392 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2393
2394 return CMD_SUCCESS;
2395}
2396
2397ALIAS (no_debug_ospf6_message,
2398 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002399 "no debug ospf6 message "
2400 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002401 NO_STR
2402 DEBUG_STR
2403 OSPF6_STR
2404 "Debug OSPFv3 message\n"
2405 "Debug Unknown message\n"
2406 "Debug Hello message\n"
2407 "Debug Database Description message\n"
2408 "Debug Link State Request message\n"
2409 "Debug Link State Update message\n"
2410 "Debug Link State Acknowledgement message\n"
2411 "Debug All message\n"
2412 "Debug only sending message\n"
2413 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002414 )
hasso508e53e2004-05-18 18:57:06 +00002415
2416int
2417config_write_ospf6_debug_message (struct vty *vty)
2418{
paul0c083ee2004-10-10 12:54:58 +00002419 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002420 "lsreq", "lsupdate", "lsack"};
2421 unsigned char s = 0, r = 0;
2422 int i;
2423
2424 for (i = 0; i < 6; i++)
2425 {
2426 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2427 s |= 1 << i;
2428 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2429 r |= 1 << i;
2430 }
2431
2432 if (s == 0x3f && r == 0x3f)
2433 {
hasso049207c2004-08-04 20:02:13 +00002434 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002435 return 0;
2436 }
2437
hasso508e53e2004-05-18 18:57:06 +00002438 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002439 {
hasso049207c2004-08-04 20:02:13 +00002440 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002441 return 0;
2442 }
2443 else if (s == 0 && r == 0x3f)
2444 {
hasso049207c2004-08-04 20:02:13 +00002445 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002446 return 0;
paul718e3742002-12-13 20:15:29 +00002447 }
2448
hasso508e53e2004-05-18 18:57:06 +00002449 /* Unknown message is logged by default */
2450 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2451 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002452 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002453 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002454 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002455 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002456 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002457
hasso508e53e2004-05-18 18:57:06 +00002458 for (i = 1; i < 6; i++)
2459 {
2460 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2461 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002462 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002463 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2464 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002465 VNL);
hasso508e53e2004-05-18 18:57:06 +00002466 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2467 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002468 VNL);
hasso508e53e2004-05-18 18:57:06 +00002469 }
paul718e3742002-12-13 20:15:29 +00002470
2471 return 0;
2472}
2473
paul718e3742002-12-13 20:15:29 +00002474void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002475install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002476{
hasso508e53e2004-05-18 18:57:06 +00002477 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2478 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2479 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2480 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2481 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2482 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2483 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2484 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002485}
2486
paul718e3742002-12-13 20:15:29 +00002487