blob: 5edb70ce64586dde0cb28a83458b6f87735a2459 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
hasso3b4cd3a2004-05-18 19:28:32 +000024#include "memory.h"
hasso508e53e2004-05-18 18:57:06 +000025#include "log.h"
26#include "vty.h"
27#include "command.h"
28#include "thread.h"
29#include "linklist.h"
30
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
34#include "ospf6_network.h"
35#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000036
hasso508e53e2004-05-18 18:57:06 +000037#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_neighbor.h"
40#include "ospf6_interface.h"
41
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040042/* for structures and macros ospf6_lsa_examin() needs */
43#include "ospf6_abr.h"
44#include "ospf6_asbr.h"
45#include "ospf6_intra.h"
46
hasso508e53e2004-05-18 18:57:06 +000047#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000048#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000049
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +040050#include <netinet/ip6.h>
51
hasso508e53e2004-05-18 18:57:06 +000052unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
Denis Ovsienko5031ed12011-10-14 21:59:58 +040053static const struct message ospf6_message_type_str [] =
54{
55 { OSPF6_MESSAGE_TYPE_HELLO, "Hello" },
56 { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" },
57 { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" },
58 { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" },
59 { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" },
60};
Balaji.G837d16c2012-09-26 14:09:10 +053061static const size_t ospf6_message_type_str_max = array_size(ospf6_message_type_str);
hasso508e53e2004-05-18 18:57:06 +000062
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040063/* Minimum (besides the standard OSPF packet header) lengths for OSPF
64 packets of particular types, offset is the "type" field. */
65const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
66{
67 0,
68 OSPF6_HELLO_MIN_SIZE,
69 OSPF6_DB_DESC_MIN_SIZE,
70 OSPF6_LS_REQ_MIN_SIZE,
71 OSPF6_LS_UPD_MIN_SIZE,
72 OSPF6_LS_ACK_MIN_SIZE
73};
74
75/* Minimum (besides the standard LSA header) lengths for LSAs of particular
76 types, offset is the "LSA function code" portion of "LSA type" field. */
77const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
78{
79 0,
80 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
81 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
82 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
83 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
84 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
85 /* 0x2006 */ 0,
86 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
87 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
88 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
89};
90
hasso508e53e2004-05-18 18:57:06 +000091/* print functions */
92
93static void
94ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000095{
hasso508e53e2004-05-18 18:57:06 +000096 char router_id[16], area_id[16];
97 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
98 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000099
hassoc6487d62004-12-24 06:00:11 +0000100 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +0000101 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +0000102 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +0000103 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +0000104}
paul718e3742002-12-13 20:15:29 +0000105
106void
hasso508e53e2004-05-18 18:57:06 +0000107ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000108{
paul718e3742002-12-13 20:15:29 +0000109 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000110 char options[16];
111 char drouter[16], bdrouter[16], neighbor[16];
112 char *p;
paul718e3742002-12-13 20:15:29 +0000113
hasso508e53e2004-05-18 18:57:06 +0000114 ospf6_header_print (oh);
115 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000116
hasso508e53e2004-05-18 18:57:06 +0000117 hello = (struct ospf6_hello *)
118 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000119
hasso508e53e2004-05-18 18:57:06 +0000120 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
121 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
122 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000123
hassoc6487d62004-12-24 06:00:11 +0000124 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000125 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000126 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000127 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000128 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000129
hasso508e53e2004-05-18 18:57:06 +0000130 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
131 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
132 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000133 {
hasso508e53e2004-05-18 18:57:06 +0000134 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000135 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000136 }
hasso508e53e2004-05-18 18:57:06 +0000137
Denis Ovsienkofa079662011-10-08 17:22:45 +0400138 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000139}
140
hasso508e53e2004-05-18 18:57:06 +0000141void
142ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000143{
paul718e3742002-12-13 20:15:29 +0000144 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000145 char options[16];
146 char *p;
paul718e3742002-12-13 20:15:29 +0000147
hasso508e53e2004-05-18 18:57:06 +0000148 ospf6_header_print (oh);
149 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000150
hasso508e53e2004-05-18 18:57:06 +0000151 dbdesc = (struct ospf6_dbdesc *)
152 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000153
hasso508e53e2004-05-18 18:57:06 +0000154 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000155
hassoc6487d62004-12-24 06:00:11 +0000156 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000157 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000158 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000159 dbdesc->reserved2,
160 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
161 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
162 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
163 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000164
hasso508e53e2004-05-18 18:57:06 +0000165 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
166 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
167 p += sizeof (struct ospf6_lsa_header))
168 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
169
Denis Ovsienkofa079662011-10-08 17:22:45 +0400170 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000171}
172
hasso508e53e2004-05-18 18:57:06 +0000173void
174ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000175{
hasso508e53e2004-05-18 18:57:06 +0000176 char id[16], adv_router[16];
177 char *p;
paul718e3742002-12-13 20:15:29 +0000178
hasso508e53e2004-05-18 18:57:06 +0000179 ospf6_header_print (oh);
180 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000181
hasso508e53e2004-05-18 18:57:06 +0000182 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
183 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
184 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000185 {
hasso508e53e2004-05-18 18:57:06 +0000186 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
187 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
188 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000189 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000190 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000191 }
hasso508e53e2004-05-18 18:57:06 +0000192
Denis Ovsienkofa079662011-10-08 17:22:45 +0400193 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000194}
195
hasso508e53e2004-05-18 18:57:06 +0000196void
197ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000198{
paul718e3742002-12-13 20:15:29 +0000199 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000200 u_long num;
201 char *p;
paul718e3742002-12-13 20:15:29 +0000202
hasso508e53e2004-05-18 18:57:06 +0000203 ospf6_header_print (oh);
204 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000205
hasso508e53e2004-05-18 18:57:06 +0000206 lsupdate = (struct ospf6_lsupdate *)
207 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000208
hasso508e53e2004-05-18 18:57:06 +0000209 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000210 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000211
hasso508e53e2004-05-18 18:57:06 +0000212 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
213 p < OSPF6_MESSAGE_END (oh) &&
214 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
215 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000216 {
hasso508e53e2004-05-18 18:57:06 +0000217 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000218 }
paul718e3742002-12-13 20:15:29 +0000219
Denis Ovsienkofa079662011-10-08 17:22:45 +0400220 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000221}
222
hasso508e53e2004-05-18 18:57:06 +0000223void
224ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000225{
hasso508e53e2004-05-18 18:57:06 +0000226 char *p;
paul718e3742002-12-13 20:15:29 +0000227
hasso508e53e2004-05-18 18:57:06 +0000228 ospf6_header_print (oh);
229 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000230
hasso508e53e2004-05-18 18:57:06 +0000231 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
232 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
233 p += sizeof (struct ospf6_lsa_header))
234 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
235
Denis Ovsienkofa079662011-10-08 17:22:45 +0400236 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000237}
238
Paul Jakma6ac29a52008-08-15 13:45:30 +0100239static void
hasso508e53e2004-05-18 18:57:06 +0000240ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
241 struct ospf6_interface *oi, struct ospf6_header *oh)
242{
243 struct ospf6_hello *hello;
244 struct ospf6_neighbor *on;
245 char *p;
246 int twoway = 0;
247 int neighborchange = 0;
248 int backupseen = 0;
249
hasso508e53e2004-05-18 18:57:06 +0000250 hello = (struct ospf6_hello *)
251 ((caddr_t) oh + sizeof (struct ospf6_header));
252
paul718e3742002-12-13 20:15:29 +0000253 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000254 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000255 {
hasso508e53e2004-05-18 18:57:06 +0000256 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000257 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000258 return;
259 }
260
261 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000262 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000263 {
hasso508e53e2004-05-18 18:57:06 +0000264 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000265 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000266 return;
267 }
268
hasso508e53e2004-05-18 18:57:06 +0000269 /* E-bit check */
270 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
271 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000272 {
hasso508e53e2004-05-18 18:57:06 +0000273 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000274 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000275 return;
276 }
277
hasso508e53e2004-05-18 18:57:06 +0000278 /* Find neighbor, create if not exist */
279 on = ospf6_neighbor_lookup (oh->router_id, oi);
280 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000281 {
hasso508e53e2004-05-18 18:57:06 +0000282 on = ospf6_neighbor_create (oh->router_id, oi);
283 on->prev_drouter = on->drouter = hello->drouter;
284 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
285 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000286 }
287
hasso7b6ae022005-06-24 08:17:51 +0000288 /* always override neighbor's source address and ifindex */
289 on->ifindex = ntohl (hello->interface_id);
290 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
291
paul718e3742002-12-13 20:15:29 +0000292 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000293 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
294 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
295 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000296 {
hasso508e53e2004-05-18 18:57:06 +0000297 u_int32_t *router_id = (u_int32_t *) p;
298
299 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000300 twoway++;
paul718e3742002-12-13 20:15:29 +0000301 }
302
Denis Ovsienkofa079662011-10-08 17:22:45 +0400303 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000304
305 /* RouterPriority check */
306 if (on->priority != hello->priority)
307 {
308 on->priority = hello->priority;
309 neighborchange++;
310 }
311
312 /* DR check */
313 if (on->drouter != hello->drouter)
314 {
315 on->prev_drouter = on->drouter;
316 on->drouter = hello->drouter;
317 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
318 neighborchange++;
319 }
320
321 /* BDR check */
322 if (on->bdrouter != hello->bdrouter)
323 {
324 on->prev_bdrouter = on->bdrouter;
325 on->bdrouter = hello->bdrouter;
326 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
327 neighborchange++;
328 }
paul718e3742002-12-13 20:15:29 +0000329
330 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000331 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000332 {
hasso508e53e2004-05-18 18:57:06 +0000333 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000334 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000335 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000336 backupseen++;
337 }
338
hasso508e53e2004-05-18 18:57:06 +0000339 /* Execute neighbor events */
340 thread_execute (master, hello_received, on, 0);
341 if (twoway)
342 thread_execute (master, twoway_received, on, 0);
343 else
344 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000345
hasso508e53e2004-05-18 18:57:06 +0000346 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000347 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000348 thread_add_event (master, backup_seen, oi, 0);
349 if (neighborchange)
350 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000351}
352
hasso508e53e2004-05-18 18:57:06 +0000353static void
354ospf6_dbdesc_recv_master (struct ospf6_header *oh,
355 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000356{
paul718e3742002-12-13 20:15:29 +0000357 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000358 char *p;
paul718e3742002-12-13 20:15:29 +0000359
hasso508e53e2004-05-18 18:57:06 +0000360 dbdesc = (struct ospf6_dbdesc *)
361 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000362
hasso508e53e2004-05-18 18:57:06 +0000363 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000364 {
hasso508e53e2004-05-18 18:57:06 +0000365 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000366 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000367 return;
368 }
369
hasso508e53e2004-05-18 18:57:06 +0000370 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000371 {
hasso508e53e2004-05-18 18:57:06 +0000372 case OSPF6_NEIGHBOR_TWOWAY:
373 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000374 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000375 return;
376
377 case OSPF6_NEIGHBOR_INIT:
378 thread_execute (master, twoway_received, on, 0);
379 if (on->state != OSPF6_NEIGHBOR_EXSTART)
380 {
381 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000382 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000383 return;
384 }
385 /* else fall through to ExStart */
386
387 case OSPF6_NEIGHBOR_EXSTART:
388 /* if neighbor obeys us as our slave, schedule negotiation_done
389 and process LSA Headers. Otherwise, ignore this message */
390 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
391 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
392 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
393 {
394 /* execute NegotiationDone */
395 thread_execute (master, negotiation_done, on, 0);
396
397 /* Record neighbor options */
398 memcpy (on->options, dbdesc->options, sizeof (on->options));
399 }
400 else
401 {
402 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000403 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000404 return;
405 }
406 /* fall through to exchange */
407
408 case OSPF6_NEIGHBOR_EXCHANGE:
409 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
410 {
411 /* Duplicated DatabaseDescription is dropped by master */
412 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000413 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000414 return;
415 }
416
417 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
418 {
419 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000420 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000421 thread_add_event (master, seqnumber_mismatch, on, 0);
422 return;
423 }
424
425 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
426 {
427 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000428 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000429 thread_add_event (master, seqnumber_mismatch, on, 0);
430 return;
431 }
432
433 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
434 {
435 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000436 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000437 thread_add_event (master, seqnumber_mismatch, on, 0);
438 return;
439 }
440
441 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
442 {
443 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000444 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000445 (u_long) on->dbdesc_seqnum);
446 thread_add_event (master, seqnumber_mismatch, on, 0);
447 return;
448 }
449 break;
450
451 case OSPF6_NEIGHBOR_LOADING:
452 case OSPF6_NEIGHBOR_FULL:
453 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
454 {
455 /* Duplicated DatabaseDescription is dropped by master */
456 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000457 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000458 return;
459 }
460
461 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000462 zlog_debug ("Not duplicate dbdesc in state %s",
463 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000464 thread_add_event (master, seqnumber_mismatch, on, 0);
465 return;
466
467 default:
468 assert (0);
469 break;
470 }
471
472 /* Process LSA headers */
473 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
474 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
475 p += sizeof (struct ospf6_lsa_header))
476 {
477 struct ospf6_lsa *his, *mine;
478 struct ospf6_lsdb *lsdb = NULL;
479
480 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000481
482 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000483 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000484
485 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000486 {
hasso6452df02004-08-15 05:52:07 +0000487 case OSPF6_SCOPE_LINKLOCAL:
488 lsdb = on->ospf6_if->lsdb;
489 break;
490 case OSPF6_SCOPE_AREA:
491 lsdb = on->ospf6_if->area->lsdb;
492 break;
493 case OSPF6_SCOPE_AS:
494 lsdb = on->ospf6_if->area->ospf6->lsdb;
495 break;
496 case OSPF6_SCOPE_RESERVED:
497 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000498 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000499 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000500 continue;
501 break;
hasso508e53e2004-05-18 18:57:06 +0000502 }
503
504 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000505 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000506 {
507 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000508 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000509 ospf6_lsa_delete (his);
510 thread_add_event (master, seqnumber_mismatch, on, 0);
511 return;
512 }
513
514 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
515 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000516 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000517 {
hasso6452df02004-08-15 05:52:07 +0000518 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000519 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000520 ospf6_lsdb_add (his, on->request_list);
521 }
522 else if (ospf6_lsa_compare (his, mine) < 0)
523 {
524 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000525 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000526 ospf6_lsdb_add (his, on->request_list);
527 }
528 else
hasso6452df02004-08-15 05:52:07 +0000529 {
530 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000531 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000532 ospf6_lsa_delete (his);
533 }
hasso508e53e2004-05-18 18:57:06 +0000534 }
535
Denis Ovsienkofa079662011-10-08 17:22:45 +0400536 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000537
538 /* Increment sequence number */
539 on->dbdesc_seqnum ++;
540
541 /* schedule send lsreq */
542 if (on->thread_send_lsreq == NULL)
543 on->thread_send_lsreq =
544 thread_add_event (master, ospf6_lsreq_send, on, 0);
545
546 THREAD_OFF (on->thread_send_dbdesc);
547
548 /* More bit check */
549 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
550 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
551 thread_add_event (master, exchange_done, on, 0);
552 else
553 on->thread_send_dbdesc =
554 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
555
556 /* save last received dbdesc */
557 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
558}
559
560static void
561ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
562 struct ospf6_neighbor *on)
563{
564 struct ospf6_dbdesc *dbdesc;
565 char *p;
566
567 dbdesc = (struct ospf6_dbdesc *)
568 ((caddr_t) oh + sizeof (struct ospf6_header));
569
570 if (on->state < OSPF6_NEIGHBOR_INIT)
571 {
572 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000573 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000574 return;
575 }
576
hasso508e53e2004-05-18 18:57:06 +0000577 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000578 {
hasso508e53e2004-05-18 18:57:06 +0000579 case OSPF6_NEIGHBOR_TWOWAY:
580 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000581 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000582 return;
583
584 case OSPF6_NEIGHBOR_INIT:
585 thread_execute (master, twoway_received, on, 0);
586 if (on->state != OSPF6_NEIGHBOR_EXSTART)
587 {
588 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000589 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000590 return;
591 }
592 /* else fall through to ExStart */
593
594 case OSPF6_NEIGHBOR_EXSTART:
595 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
596 and process LSA Headers. Otherwise, ignore this message */
597 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
598 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
599 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
600 ntohs (oh->length) == sizeof (struct ospf6_header) +
601 sizeof (struct ospf6_dbdesc))
602 {
603 /* set the master/slave bit to slave */
604 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
605
606 /* set the DD sequence number to one specified by master */
607 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
608
609 /* schedule NegotiationDone */
610 thread_execute (master, negotiation_done, on, 0);
611
612 /* Record neighbor options */
613 memcpy (on->options, dbdesc->options, sizeof (on->options));
614 }
615 else
616 {
617 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000618 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000619 return;
620 }
621 break;
622
623 case OSPF6_NEIGHBOR_EXCHANGE:
624 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
625 {
626 /* Duplicated DatabaseDescription causes slave to retransmit */
627 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000628 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000629 THREAD_OFF (on->thread_send_dbdesc);
630 on->thread_send_dbdesc =
631 thread_add_event (master, ospf6_dbdesc_send, on, 0);
632 return;
633 }
634
635 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
636 {
637 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000638 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000639 thread_add_event (master, seqnumber_mismatch, on, 0);
640 return;
641 }
642
643 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
644 {
645 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000646 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000647 thread_add_event (master, seqnumber_mismatch, on, 0);
648 return;
649 }
650
651 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
652 {
653 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000654 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000655 thread_add_event (master, seqnumber_mismatch, on, 0);
656 return;
657 }
658
659 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
660 {
661 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000662 zlog_debug ("Sequence number mismatch (%#lx expected)",
663 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000664 thread_add_event (master, seqnumber_mismatch, on, 0);
665 return;
666 }
667 break;
668
669 case OSPF6_NEIGHBOR_LOADING:
670 case OSPF6_NEIGHBOR_FULL:
671 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
672 {
673 /* Duplicated DatabaseDescription causes slave to retransmit */
674 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000675 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000676 THREAD_OFF (on->thread_send_dbdesc);
677 on->thread_send_dbdesc =
678 thread_add_event (master, ospf6_dbdesc_send, on, 0);
679 return;
680 }
681
682 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000683 zlog_debug ("Not duplicate dbdesc in state %s",
684 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000685 thread_add_event (master, seqnumber_mismatch, on, 0);
686 return;
687
688 default:
689 assert (0);
690 break;
paul718e3742002-12-13 20:15:29 +0000691 }
692
hasso508e53e2004-05-18 18:57:06 +0000693 /* Process LSA headers */
694 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
695 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
696 p += sizeof (struct ospf6_lsa_header))
697 {
698 struct ospf6_lsa *his, *mine;
699 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000700
hasso508e53e2004-05-18 18:57:06 +0000701 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000702
703 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000704 {
hasso6452df02004-08-15 05:52:07 +0000705 case OSPF6_SCOPE_LINKLOCAL:
706 lsdb = on->ospf6_if->lsdb;
707 break;
708 case OSPF6_SCOPE_AREA:
709 lsdb = on->ospf6_if->area->lsdb;
710 break;
711 case OSPF6_SCOPE_AS:
712 lsdb = on->ospf6_if->area->ospf6->lsdb;
713 break;
714 case OSPF6_SCOPE_RESERVED:
715 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000716 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000717 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000718 continue;
719 break;
hasso508e53e2004-05-18 18:57:06 +0000720 }
721
hasso6452df02004-08-15 05:52:07 +0000722 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
723 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000724 {
725 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000726 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000727 ospf6_lsa_delete (his);
728 thread_add_event (master, seqnumber_mismatch, on, 0);
729 return;
730 }
731
732 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
733 his->header->adv_router, lsdb);
734 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
735 {
hasso6452df02004-08-15 05:52:07 +0000736 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000737 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000738 ospf6_lsdb_add (his, on->request_list);
739 }
740 else
741 ospf6_lsa_delete (his);
742 }
743
Denis Ovsienkofa079662011-10-08 17:22:45 +0400744 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000745
746 /* Set sequence number to Master's */
747 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
748
749 /* schedule send lsreq */
750 if (on->thread_send_lsreq == NULL)
751 on->thread_send_lsreq =
752 thread_add_event (master, ospf6_lsreq_send, on, 0);
753
754 THREAD_OFF (on->thread_send_dbdesc);
755 on->thread_send_dbdesc =
756 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
757
758 /* save last received dbdesc */
759 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000760}
761
Paul Jakma6ac29a52008-08-15 13:45:30 +0100762static void
hasso508e53e2004-05-18 18:57:06 +0000763ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
764 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000765{
hasso508e53e2004-05-18 18:57:06 +0000766 struct ospf6_neighbor *on;
767 struct ospf6_dbdesc *dbdesc;
768
hasso508e53e2004-05-18 18:57:06 +0000769 on = ospf6_neighbor_lookup (oh->router_id, oi);
770 if (on == NULL)
771 {
772 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000773 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000774 return;
775 }
776
hasso508e53e2004-05-18 18:57:06 +0000777 dbdesc = (struct ospf6_dbdesc *)
778 ((caddr_t) oh + sizeof (struct ospf6_header));
779
780 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400781 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000782 {
783 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000784 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000785 return;
786 }
787
788 if (dbdesc->reserved1 || dbdesc->reserved2)
789 {
790 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000791 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
792 on->name);
hasso508e53e2004-05-18 18:57:06 +0000793 dbdesc->reserved1 = 0;
794 dbdesc->reserved2 = 0;
795 }
796
797 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
798 ospf6_dbdesc_recv_master (oh, on);
799 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
800 ospf6_dbdesc_recv_slave (oh, on);
801 else
802 {
803 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000804 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000805 }
806}
807
Paul Jakma6ac29a52008-08-15 13:45:30 +0100808static void
hasso508e53e2004-05-18 18:57:06 +0000809ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
810 struct ospf6_interface *oi, struct ospf6_header *oh)
811{
812 struct ospf6_neighbor *on;
813 char *p;
814 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000815 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000816 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000817
hasso508e53e2004-05-18 18:57:06 +0000818 on = ospf6_neighbor_lookup (oh->router_id, oi);
819 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000820 {
hasso508e53e2004-05-18 18:57:06 +0000821 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000822 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000823 return;
824 }
825
hasso508e53e2004-05-18 18:57:06 +0000826 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
827 on->state != OSPF6_NEIGHBOR_LOADING &&
828 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000829 {
hasso508e53e2004-05-18 18:57:06 +0000830 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000831 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000832 return;
833 }
834
hasso508e53e2004-05-18 18:57:06 +0000835 /* Process each request */
836 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
837 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
838 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000839 {
hasso508e53e2004-05-18 18:57:06 +0000840 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000841
842 switch (OSPF6_LSA_SCOPE (e->type))
843 {
844 case OSPF6_SCOPE_LINKLOCAL:
845 lsdb = on->ospf6_if->lsdb;
846 break;
847 case OSPF6_SCOPE_AREA:
848 lsdb = on->ospf6_if->area->lsdb;
849 break;
850 case OSPF6_SCOPE_AS:
851 lsdb = on->ospf6_if->area->ospf6->lsdb;
852 break;
853 default:
854 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000855 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000856 continue;
857 break;
858 }
paul718e3742002-12-13 20:15:29 +0000859
hasso508e53e2004-05-18 18:57:06 +0000860 /* Find database copy */
861 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
862 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000863 {
hasso508e53e2004-05-18 18:57:06 +0000864 char id[16], adv_router[16];
865 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
866 {
867 inet_ntop (AF_INET, &e->id, id, sizeof (id));
868 inet_ntop (AF_INET, &e->adv_router, adv_router,
869 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000870 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
871 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000872 }
873 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000874 return;
875 }
876
hasso508e53e2004-05-18 18:57:06 +0000877 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000878 }
879
Denis Ovsienkofa079662011-10-08 17:22:45 +0400880 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000881
hasso508e53e2004-05-18 18:57:06 +0000882 /* schedule send lsupdate */
883 THREAD_OFF (on->thread_send_lsupdate);
884 on->thread_send_lsupdate =
885 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000886}
887
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400888/* Verify, that the specified memory area contains exactly N valid IPv6
889 prefixes as specified by RFC5340, A.4.1. */
890static unsigned
891ospf6_prefixes_examin
892(
893 struct ospf6_prefix *current, /* start of buffer */
894 unsigned length,
895 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
896)
897{
898 u_char requested_pfx_bytes;
899 u_int32_t real_num_pfxs = 0;
900
901 while (length)
902 {
903 if (length < OSPF6_PREFIX_MIN_SIZE)
904 {
905 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
906 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
907 return MSG_NG;
908 }
909 /* safe to look deeper */
910 if (current->prefix_length > IPV6_MAX_BITLEN)
911 {
912 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
913 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
914 return MSG_NG;
915 }
916 /* covers both fixed- and variable-sized fields */
917 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
918 if (requested_pfx_bytes > length)
919 {
920 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
921 zlog_debug ("%s: undersized IPv6 prefix", __func__);
922 return MSG_NG;
923 }
924 /* next prefix */
925 length -= requested_pfx_bytes;
926 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
927 real_num_pfxs++;
928 }
929 if (real_num_pfxs != req_num_pfxs)
930 {
931 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
932 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
933 __func__, req_num_pfxs, real_num_pfxs);
934 return MSG_NG;
935 }
936 return MSG_OK;
937}
938
939/* Verify an LSA to have a valid length and dispatch further (where
940 appropriate) to check if the contents, including nested IPv6 prefixes,
941 is properly sized/aligned within the LSA. Note that this function gets
942 LSA type in network byte order, uses in host byte order and passes to
943 ospf6_lstype_name() in network byte order again. */
944static unsigned
945ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
946{
947 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
948 struct ospf6_as_external_lsa *as_external_lsa;
949 struct ospf6_link_lsa *link_lsa;
950 unsigned exp_length;
951 u_int8_t ltindex;
952 u_int16_t lsatype;
953
954 /* In case an additional minimum length constraint is defined for current
955 LSA type, make sure that this constraint is met. */
956 lsatype = ntohs (lsah->type);
957 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
958 if
959 (
960 ltindex < OSPF6_LSTYPE_SIZE &&
961 ospf6_lsa_minlen[ltindex] &&
962 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
963 )
964 {
965 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
966 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
967 return MSG_NG;
968 }
969 switch (lsatype)
970 {
971 case OSPF6_LSTYPE_ROUTER:
972 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
973 by N>=0 interface descriptions. */
974 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
975 {
976 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
977 zlog_debug ("%s: interface description alignment error", __func__);
978 return MSG_NG;
979 }
980 break;
981 case OSPF6_LSTYPE_NETWORK:
982 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
983 followed by N>=0 attached router descriptions. */
984 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
985 {
986 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
987 zlog_debug ("%s: router description alignment error", __func__);
988 return MSG_NG;
989 }
990 break;
991 case OSPF6_LSTYPE_INTER_PREFIX:
992 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
993 followed by 3-4 fields of a single IPv6 prefix. */
994 if (headeronly)
995 break;
996 return ospf6_prefixes_examin
997 (
998 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
999 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1000 1
1001 );
1002 case OSPF6_LSTYPE_INTER_ROUTER:
1003 /* RFC5340 A.4.6, fixed-size LSA. */
1004 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1005 {
1006 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1007 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1008 return MSG_NG;
1009 }
1010 break;
1011 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1012 case OSPF6_LSTYPE_TYPE_7:
1013 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1014 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1015 16 bytes of forwarding address, 4 bytes of external route tag,
1016 4 bytes of referenced link state ID. */
1017 if (headeronly)
1018 break;
1019 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1020 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1021 /* To find out if the last optional field (Referenced Link State ID) is
1022 assumed in this LSA, we need to access fixed fields of the IPv6
1023 prefix before ospf6_prefix_examin() confirms its sizing. */
1024 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1025 {
1026 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1027 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1028 return MSG_NG;
1029 }
1030 /* forwarding address */
1031 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1032 exp_length += 16;
1033 /* external route tag */
1034 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1035 exp_length += 4;
1036 /* referenced link state ID */
1037 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1038 exp_length += 4;
1039 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1040 this check does not include any IPv6 prefix fields. */
1041 if (exp_length > lsalen)
1042 {
1043 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1044 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1045 return MSG_NG;
1046 }
1047 /* The last call completely covers the remainder (IPv6 prefix). */
1048 return ospf6_prefixes_examin
1049 (
1050 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1051 lsalen - exp_length,
1052 1
1053 );
1054 case OSPF6_LSTYPE_LINK:
1055 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1056 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1057 if (headeronly)
1058 break;
1059 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1060 return ospf6_prefixes_examin
1061 (
1062 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1063 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1064 ntohl (link_lsa->prefix_num) /* 32 bits */
1065 );
1066 case OSPF6_LSTYPE_INTRA_PREFIX:
1067 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1068 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1069 if (headeronly)
1070 break;
1071 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1072 return ospf6_prefixes_examin
1073 (
1074 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1075 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1076 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1077 );
1078 }
1079 /* No additional validation is possible for unknown LSA types, which are
1080 themselves valid in OPSFv3, hence the default decision is to accept. */
1081 return MSG_OK;
1082}
1083
1084/* Verify if the provided input buffer is a valid sequence of LSAs. This
1085 includes verification of LSA blocks length/alignment and dispatching
1086 of deeper-level checks. */
1087static unsigned
1088ospf6_lsaseq_examin
1089(
1090 struct ospf6_lsa_header *lsah, /* start of buffered data */
1091 size_t length,
1092 const u_char headeronly,
1093 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1094 and treat the difference as an error. */
1095 const u_int32_t declared_num_lsas
1096)
1097{
1098 u_int32_t counted_lsas = 0;
1099
1100 while (length)
1101 {
1102 u_int16_t lsalen;
1103 if (length < OSPF6_LSA_HEADER_SIZE)
1104 {
1105 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001106 zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001107 __func__, length, counted_lsas);
1108 return MSG_NG;
1109 }
1110 /* save on ntohs() calls here and in the LSA validator */
1111 lsalen = OSPF6_LSA_SIZE (lsah);
1112 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1113 {
1114 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1115 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1116 __func__, counted_lsas, lsalen);
1117 return MSG_NG;
1118 }
1119 if (headeronly)
1120 {
1121 /* less checks here and in ospf6_lsa_examin() */
1122 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1123 {
1124 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1125 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1126 ospf6_lstype_name (lsah->type), counted_lsas);
1127 return MSG_NG;
1128 }
1129 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1130 length -= OSPF6_LSA_HEADER_SIZE;
1131 }
1132 else
1133 {
1134 /* make sure the input buffer is deep enough before further checks */
1135 if (lsalen > length)
1136 {
1137 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001138 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001139 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1140 return MSG_NG;
1141 }
1142 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1143 {
1144 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1145 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1146 ospf6_lstype_name (lsah->type), counted_lsas);
1147 return MSG_NG;
1148 }
1149 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1150 length -= lsalen;
1151 }
1152 counted_lsas++;
1153 }
1154
1155 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1156 {
1157 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1158 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1159 __func__, declared_num_lsas, counted_lsas);
1160 return MSG_NG;
1161 }
1162 return MSG_OK;
1163}
1164
1165/* Verify a complete OSPF packet for proper sizing/alignment. */
1166static unsigned
1167ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1168{
1169 struct ospf6_lsupdate *lsupd;
1170 unsigned test;
1171
1172 /* length, 1st approximation */
1173 if (bytesonwire < OSPF6_HEADER_SIZE)
1174 {
1175 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1176 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1177 return MSG_NG;
1178 }
1179 /* Now it is safe to access header fields. */
1180 if (bytesonwire != ntohs (oh->length))
1181 {
1182 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1183 zlog_debug ("%s: packet length error (%u real, %u declared)",
1184 __func__, bytesonwire, ntohs (oh->length));
1185 return MSG_NG;
1186 }
1187 /* version check */
1188 if (oh->version != OSPFV3_VERSION)
1189 {
1190 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1191 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1192 return MSG_NG;
1193 }
1194 /* length, 2nd approximation */
1195 if
1196 (
1197 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1198 ospf6_packet_minlen[oh->type] &&
1199 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1200 )
1201 {
1202 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1203 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001204 bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001205 return MSG_NG;
1206 }
1207 /* type-specific deeper validation */
1208 switch (oh->type)
1209 {
1210 case OSPF6_MESSAGE_TYPE_HELLO:
1211 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1212 by N>=0 router-IDs. */
1213 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1214 return MSG_OK;
1215 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1216 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001217 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001218 return MSG_NG;
1219 case OSPF6_MESSAGE_TYPE_DBDESC:
1220 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1221 by N>=0 header-only LSAs. */
1222 test = ospf6_lsaseq_examin
1223 (
1224 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1225 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1226 1,
1227 0
1228 );
1229 break;
1230 case OSPF6_MESSAGE_TYPE_LSREQ:
1231 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1232 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1233 return MSG_OK;
1234 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1235 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001236 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001237 return MSG_NG;
1238 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1239 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1240 by N>=0 full LSAs (with N declared beforehand). */
1241 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1242 test = ospf6_lsaseq_examin
1243 (
1244 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1245 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1246 0,
1247 ntohl (lsupd->lsa_number) /* 32 bits */
1248 );
1249 break;
1250 case OSPF6_MESSAGE_TYPE_LSACK:
1251 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1252 test = ospf6_lsaseq_examin
1253 (
1254 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1255 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1256 1,
1257 0
1258 );
1259 break;
1260 default:
1261 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1262 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1263 return MSG_NG;
1264 }
1265 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001266 zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001267 return test;
1268}
1269
1270/* Verify particular fields of otherwise correct received OSPF packet to
1271 meet the requirements of RFC. */
1272static int
1273ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1274{
1275 char buf[2][INET_ADDRSTRLEN];
1276
1277 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1278 return MSG_NG;
1279
1280 /* Area-ID check */
1281 if (oh->area_id != oi->area->area_id)
1282 {
1283 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1284 {
1285 if (oh->area_id == BACKBONE_AREA_ID)
1286 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1287 else
1288 zlog_debug
1289 (
1290 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1291 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1292 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1293 );
1294 }
1295 return MSG_NG;
1296 }
1297
1298 /* Instance-ID check */
1299 if (oh->instance_id != oi->instance_id)
1300 {
1301 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1302 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1303 return MSG_NG;
1304 }
1305
1306 /* Router-ID check */
1307 if (oh->router_id == oi->area->ospf6->router_id)
1308 {
1309 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1310 return MSG_NG;
1311 }
1312 return MSG_OK;
1313}
1314
Paul Jakma6ac29a52008-08-15 13:45:30 +01001315static void
hasso508e53e2004-05-18 18:57:06 +00001316ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1317 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001318{
hasso508e53e2004-05-18 18:57:06 +00001319 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001320 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001321 char *p;
paul718e3742002-12-13 20:15:29 +00001322
hasso508e53e2004-05-18 18:57:06 +00001323 on = ospf6_neighbor_lookup (oh->router_id, oi);
1324 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001325 {
hasso508e53e2004-05-18 18:57:06 +00001326 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001327 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001328 return;
1329 }
1330
hasso508e53e2004-05-18 18:57:06 +00001331 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1332 on->state != OSPF6_NEIGHBOR_LOADING &&
1333 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001334 {
hasso508e53e2004-05-18 18:57:06 +00001335 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001336 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001337 return;
1338 }
1339
hasso508e53e2004-05-18 18:57:06 +00001340 lsupdate = (struct ospf6_lsupdate *)
1341 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001342
hasso508e53e2004-05-18 18:57:06 +00001343 /* Process LSAs */
1344 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1345 p < OSPF6_MESSAGE_END (oh) &&
1346 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1347 p += OSPF6_LSA_SIZE (p))
1348 {
hasso6452df02004-08-15 05:52:07 +00001349 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001350 }
1351
Denis Ovsienkofa079662011-10-08 17:22:45 +04001352 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001353
1354 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1355 with the proper Link State Update packet(s), the Link state request
1356 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001357 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001358 can be recognized as a response to our previous LS Request */
1359 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1360 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1361 on->state == OSPF6_NEIGHBOR_LOADING))
1362 {
1363 THREAD_OFF (on->thread_send_lsreq);
1364 on->thread_send_lsreq =
1365 thread_add_event (master, ospf6_lsreq_send, on, 0);
1366 }
paul718e3742002-12-13 20:15:29 +00001367}
1368
Paul Jakma6ac29a52008-08-15 13:45:30 +01001369static void
hasso508e53e2004-05-18 18:57:06 +00001370ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1371 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001372{
hasso508e53e2004-05-18 18:57:06 +00001373 struct ospf6_neighbor *on;
1374 char *p;
1375 struct ospf6_lsa *his, *mine;
1376 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001377
hasso508e53e2004-05-18 18:57:06 +00001378 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001379
hasso508e53e2004-05-18 18:57:06 +00001380 on = ospf6_neighbor_lookup (oh->router_id, oi);
1381 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001382 {
hasso508e53e2004-05-18 18:57:06 +00001383 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001384 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001385 return;
1386 }
1387
hasso508e53e2004-05-18 18:57:06 +00001388 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1389 on->state != OSPF6_NEIGHBOR_LOADING &&
1390 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001391 {
hasso508e53e2004-05-18 18:57:06 +00001392 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001393 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001394 return;
1395 }
1396
hasso508e53e2004-05-18 18:57:06 +00001397 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1398 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1399 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001400 {
hasso508e53e2004-05-18 18:57:06 +00001401 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001402
hasso6452df02004-08-15 05:52:07 +00001403 switch (OSPF6_LSA_SCOPE (his->header->type))
1404 {
1405 case OSPF6_SCOPE_LINKLOCAL:
1406 lsdb = on->ospf6_if->lsdb;
1407 break;
1408 case OSPF6_SCOPE_AREA:
1409 lsdb = on->ospf6_if->area->lsdb;
1410 break;
1411 case OSPF6_SCOPE_AS:
1412 lsdb = on->ospf6_if->area->ospf6->lsdb;
1413 break;
1414 case OSPF6_SCOPE_RESERVED:
1415 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001416 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001417 ospf6_lsa_delete (his);
1418 continue;
1419 break;
1420 }
1421
1422 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001423 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001424
1425 /* Find database copy */
1426 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1427 his->header->adv_router, lsdb);
1428 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001429 {
hasso508e53e2004-05-18 18:57:06 +00001430 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001431 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001432 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001433 continue;
1434 }
1435
hasso508e53e2004-05-18 18:57:06 +00001436 /* Check if the LSA is on his retrans-list */
1437 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1438 his->header->adv_router, on->retrans_list);
1439 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001440 {
hasso508e53e2004-05-18 18:57:06 +00001441 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001442 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001443 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001444 continue;
1445 }
1446
hasso508e53e2004-05-18 18:57:06 +00001447 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001448 {
hasso508e53e2004-05-18 18:57:06 +00001449 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001450 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001451 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001452 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001453 ospf6_lsa_delete (his);
1454 continue;
paul718e3742002-12-13 20:15:29 +00001455 }
1456
hasso6452df02004-08-15 05:52:07 +00001457 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001458 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1459 on->name);
hasso508e53e2004-05-18 18:57:06 +00001460
Paul Jakma932bf192006-05-15 10:42:24 +00001461 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001462 if (OSPF6_LSA_IS_MAXAGE (mine))
1463 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001464 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001465 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001466 }
1467
Denis Ovsienkofa079662011-10-08 17:22:45 +04001468 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001469}
1470
Paul Jakma6ac29a52008-08-15 13:45:30 +01001471static u_char *recvbuf = NULL;
1472static u_char *sendbuf = NULL;
1473static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001474
1475int
paul0c083ee2004-10-10 12:54:58 +00001476ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001477{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001478 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001479
1480 if (size <= iobuflen)
1481 return iobuflen;
1482
1483 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1484 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1485 if (recvnew == NULL || sendnew == NULL)
1486 {
hassob596c712004-07-09 18:33:43 +00001487 if (recvnew)
1488 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1489 if (sendnew)
1490 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001491 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001492 return iobuflen;
1493 }
1494
1495 if (recvbuf)
1496 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1497 if (sendbuf)
1498 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1499 recvbuf = recvnew;
1500 sendbuf = sendnew;
1501 iobuflen = size;
1502
1503 return iobuflen;
1504}
paul718e3742002-12-13 20:15:29 +00001505
Tom Goffae2254a2010-11-10 13:01:41 -08001506void
1507ospf6_message_terminate (void)
1508{
1509 if (recvbuf)
1510 {
1511 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1512 recvbuf = NULL;
1513 }
1514
1515 if (sendbuf)
1516 {
1517 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1518 sendbuf = NULL;
1519 }
1520
1521 iobuflen = 0;
1522}
1523
paul718e3742002-12-13 20:15:29 +00001524int
1525ospf6_receive (struct thread *thread)
1526{
paul0c083ee2004-10-10 12:54:58 +00001527 int sockfd;
1528 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001529 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001530 struct in6_addr src, dst;
1531 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001532 struct iovec iovector[2];
1533 struct ospf6_interface *oi;
1534 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001535
1536 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001537 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001538 thread_add_read (master, ospf6_receive, NULL, sockfd);
1539
1540 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001541 memset (&src, 0, sizeof (src));
1542 memset (&dst, 0, sizeof (dst));
1543 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001544 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001545 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001546 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001547 iovector[1].iov_base = NULL;
1548 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001549
1550 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001551 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001552 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001553 {
hasso508e53e2004-05-18 18:57:06 +00001554 zlog_err ("Excess message read");
1555 return 0;
1556 }
paul718e3742002-12-13 20:15:29 +00001557
hasso508e53e2004-05-18 18:57:06 +00001558 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1559 if (oi == NULL || oi->area == NULL)
1560 {
hassoc6487d62004-12-24 06:00:11 +00001561 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001562 return 0;
1563 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001564 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1565 {
1566 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1567 zlog_debug ("%s: Ignore message on passive interface %s",
1568 __func__, oi->interface->name);
1569 return 0;
1570 }
hasso508e53e2004-05-18 18:57:06 +00001571
1572 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001573 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1574 return 0;
1575
1576 /* Being here means, that no sizing/alignment issues were detected in
1577 the input packet. This renders the additional checks performed below
1578 and also in the type-specific dispatching functions a dead code,
1579 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001580
1581 /* Log */
1582 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1583 {
1584 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1585 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001586 zlog_debug ("%s received on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001587 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001588 zlog_debug (" src: %s", srcname);
1589 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001590
1591 switch (oh->type)
1592 {
1593 case OSPF6_MESSAGE_TYPE_HELLO:
1594 ospf6_hello_print (oh);
1595 break;
1596 case OSPF6_MESSAGE_TYPE_DBDESC:
1597 ospf6_dbdesc_print (oh);
1598 break;
1599 case OSPF6_MESSAGE_TYPE_LSREQ:
1600 ospf6_lsreq_print (oh);
1601 break;
1602 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1603 ospf6_lsupdate_print (oh);
1604 break;
1605 case OSPF6_MESSAGE_TYPE_LSACK:
1606 ospf6_lsack_print (oh);
1607 break;
1608 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001609 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001610 }
1611 }
1612
hasso508e53e2004-05-18 18:57:06 +00001613 switch (oh->type)
1614 {
1615 case OSPF6_MESSAGE_TYPE_HELLO:
1616 ospf6_hello_recv (&src, &dst, oi, oh);
1617 break;
1618
1619 case OSPF6_MESSAGE_TYPE_DBDESC:
1620 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1621 break;
1622
1623 case OSPF6_MESSAGE_TYPE_LSREQ:
1624 ospf6_lsreq_recv (&src, &dst, oi, oh);
1625 break;
1626
1627 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1628 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1629 break;
1630
1631 case OSPF6_MESSAGE_TYPE_LSACK:
1632 ospf6_lsack_recv (&src, &dst, oi, oh);
1633 break;
1634
1635 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001636 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001637 }
1638
1639 return 0;
1640}
1641
Paul Jakma6ac29a52008-08-15 13:45:30 +01001642static void
hasso508e53e2004-05-18 18:57:06 +00001643ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1644 struct ospf6_interface *oi, struct ospf6_header *oh)
1645{
1646 int len;
1647 char srcname[64], dstname[64];
1648 struct iovec iovector[2];
1649
1650 /* initialize */
1651 iovector[0].iov_base = (caddr_t) oh;
1652 iovector[0].iov_len = ntohs (oh->length);
1653 iovector[1].iov_base = NULL;
1654 iovector[1].iov_len = 0;
1655
1656 /* fill OSPF header */
1657 oh->version = OSPFV3_VERSION;
1658 /* message type must be set before */
1659 /* message length must be set before */
1660 oh->router_id = oi->area->ospf6->router_id;
1661 oh->area_id = oi->area->area_id;
1662 /* checksum is calculated by kernel */
1663 oh->instance_id = oi->instance_id;
1664 oh->reserved = 0;
1665
1666 /* Log */
1667 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1668 {
1669 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1670 if (src)
1671 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1672 else
1673 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001674 zlog_debug ("%s send on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001675 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001676 zlog_debug (" src: %s", srcname);
1677 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001678
1679 switch (oh->type)
1680 {
1681 case OSPF6_MESSAGE_TYPE_HELLO:
1682 ospf6_hello_print (oh);
1683 break;
1684 case OSPF6_MESSAGE_TYPE_DBDESC:
1685 ospf6_dbdesc_print (oh);
1686 break;
1687 case OSPF6_MESSAGE_TYPE_LSREQ:
1688 ospf6_lsreq_print (oh);
1689 break;
1690 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1691 ospf6_lsupdate_print (oh);
1692 break;
1693 case OSPF6_MESSAGE_TYPE_LSACK:
1694 ospf6_lsack_print (oh);
1695 break;
1696 default:
hassoc6487d62004-12-24 06:00:11 +00001697 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001698 assert (0);
1699 break;
1700 }
1701 }
1702
1703 /* send message */
1704 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1705 if (len != ntohs (oh->length))
1706 zlog_err ("Could not send entire message");
1707}
1708
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001709static uint32_t
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001710ospf6_packet_max(struct ospf6_interface *oi)
1711{
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001712 assert (oi->ifmtu > sizeof (struct ip6_hdr));
1713 return oi->ifmtu - (sizeof (struct ip6_hdr));
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001714}
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 Tejblum681b84e2011-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 Tejblum681b84e2011-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 Tejblum681b84e2011-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 Tejblum681b84e2011-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 Tejblum681b84e2011-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 Tejblum681b84e2011-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 Tejblum681b84e2011-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 Tejblum681b84e2011-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 Tejblum681b84e2011-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