blob: f6577a99ca8264ab0744f95bc965b7aef8441fe7 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Copyright (C) 1999 Yasuhiro Ohara
3 *
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
22#include "ospf6d.h"
23
24int
25is_ospf6_message_dump (u_char type)
26{
27 if (type > OSPF6_MESSAGE_TYPE_LSACK)
28 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
29
30 switch (type)
31 {
32 case OSPF6_MESSAGE_TYPE_UNKNOWN:
33 return 1;
34 break;
35 case OSPF6_MESSAGE_TYPE_HELLO:
36 if (IS_OSPF6_DUMP_HELLO)
37 return 1;
38 break;
39 case OSPF6_MESSAGE_TYPE_DBDESC:
40 if (IS_OSPF6_DUMP_DBDESC)
41 return 1;
42 break;
43 case OSPF6_MESSAGE_TYPE_LSREQ:
44 if (IS_OSPF6_DUMP_LSREQ)
45 return 1;
46 break;
47 case OSPF6_MESSAGE_TYPE_LSUPDATE:
48 if (IS_OSPF6_DUMP_LSUPDATE)
49 return 1;
50 break;
51 case OSPF6_MESSAGE_TYPE_LSACK:
52 if (IS_OSPF6_DUMP_LSACK)
53 return 1;
54 break;
55 default:
56 break;
57 }
58 return 0;
59}
60#define IS_OSPF6_DUMP_MESSAGE(x) (is_ospf6_message_dump(x))
61
62char *ospf6_message_type_string[] =
63{
64 "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck", NULL
65};
66
67void
68ospf6_message_log_lsa_header (struct ospf6_lsa_header *lsa_header)
69{
70 char buf_id[16], buf_router[16], typebuf[32];
71
72 inet_ntop (AF_INET, &lsa_header->advrtr, buf_router, sizeof (buf_router));
73 inet_ntop (AF_INET, &lsa_header->ls_id, buf_id, sizeof (buf_id));
74 zlog_info (" [%s ID=%s Adv=%s]",
75 ospf6_lsa_type_string (lsa_header->type, typebuf,
76 sizeof (typebuf)),
77 buf_id, buf_router);
78 zlog_info (" Age=%hu SeqNum=%#lx Cksum=%#hx Len=%hu",
79 ntohs (lsa_header->age), (u_long)ntohl (lsa_header->seqnum),
80 ntohs (lsa_header->checksum), ntohs (lsa_header->length));
81}
82
83static void
84ospf6_message_log_unknown (struct iovec *message)
85{
86 zlog_info ("Message: Unknown");
87}
88
89static void
90ospf6_message_log_hello (struct iovec *message)
91{
92 struct ospf6_header *ospf6_header;
93 u_int16_t length_left;
94 struct ospf6_hello *hello;
95 char dr_str[16], bdr_str[16];
96 char *start, *end, *current;
97
98 /* calculate length */
99 ospf6_header = (struct ospf6_header *) message[0].iov_base;
100 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
101 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
102 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
103
104 hello = (struct ospf6_hello *) message[1].iov_base;
105
106 inet_ntop (AF_INET, &hello->dr, dr_str, sizeof (dr_str));
107 inet_ntop (AF_INET, &hello->bdr, bdr_str, sizeof (bdr_str));
108
109 zlog_info (" IFID:%ld Priority:%d Option:%s",
110 (u_long)ntohl (hello->interface_id), hello->rtr_pri, "xxx");
111 zlog_info (" HelloInterval:%hu Deadinterval:%hu",
112 ntohs (hello->hello_interval),
113 ntohs (hello->router_dead_interval));
114 zlog_info (" DR:%s BDR:%s", dr_str, bdr_str);
115
116 start = (char *) (hello + 1);
117 if (start >= (char *) message[1].iov_base + message[1].iov_len)
118 start = message[2].iov_base;
119 end = (char *) start + (length_left - sizeof (struct ospf6_hello));
120
121 for (current = start; current < end; current += sizeof (u_int32_t))
122 {
123 char neighbor[16];
124 inet_ntop (AF_INET, current, neighbor, sizeof (neighbor));
125 zlog_info (" Neighbor: %s", neighbor);
126 }
127}
128
129static void
130ospf6_message_log_dbdesc (struct iovec *message)
131{
132 struct ospf6_header *ospf6_header;
133 u_int16_t length_left;
134 struct ospf6_dbdesc *dbdesc;
135 int i;
136 char buffer[16];
137 struct ospf6_lsa_header *lsa_header;
138
139 /* calculate length */
140 ospf6_header = (struct ospf6_header *) message[0].iov_base;
141 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
142 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
143 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
144
145 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
146 ospf6_options_string (dbdesc->options, buffer, sizeof (buffer));
147
148 zlog_info (" Option:%s IFMTU:%hu", buffer, ntohs (dbdesc->ifmtu));
149 zlog_info (" Bits:%s%s%s SeqNum:%#lx",
150 (DD_IS_IBIT_SET (dbdesc->bits) ? "I" : "-"),
151 (DD_IS_MBIT_SET (dbdesc->bits) ? "M" : "-"),
152 (DD_IS_MSBIT_SET (dbdesc->bits) ? "m" : "s"),
153 (u_long)ntohl (dbdesc->seqnum));
154
155 for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
156 (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + message[1].iov_len) &&
157 (char *)(lsa_header + 1) <= (char *)dbdesc + length_left;
158 lsa_header++)
159 ospf6_message_log_lsa_header (lsa_header);
160
161 length_left -= message[1].iov_len;
162 for (i = 2; message[i].iov_base; i++)
163 {
164 for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
165 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base +
166 message[i].iov_len) &&
167 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left);
168 lsa_header++)
169 ospf6_message_log_lsa_header (lsa_header);
170 length_left -= message[i].iov_len;
171 }
172}
173
174static void
175ospf6_message_log_lsreq (struct iovec *message)
176{
177 struct ospf6_header *ospf6_header;
178 u_int16_t length_left;
179 int i;
180 struct ospf6_lsreq *lsreq;
181 char buf_router[16], buf_id[16], buf_type[16];
182
183 /* calculate length */
184 ospf6_header = (struct ospf6_header *) message[0].iov_base;
185 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
186 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
187 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
188
189 for (i = 1; message[i].iov_base; i++)
190 {
191 for (lsreq = (struct ospf6_lsreq *) message[i].iov_base;
192 (char *)(lsreq + 1) <= (char *) (message[i].iov_base + message[i].iov_len) &&
193 (char *)(lsreq + 1) <= (char *) (message[i].iov_base + length_left);
194 lsreq++)
195 {
196 inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router));
197 inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id));
198 zlog_info (" [%s ID=%s Adv=%s]",
199 ospf6_lsa_type_string (lsreq->type, buf_type,
200 sizeof (buf_type)),
201 buf_id, buf_router);
202 }
203 length_left -= message[i].iov_len;
204 }
205}
206
207static void
208ospf6_message_log_lsupdate (struct iovec *message)
209{
210 struct ospf6_header *ospf6_header;
211 u_int16_t length_left;
212 int i, lsanum;
213 struct ospf6_lsupdate *lsupdate;
214 struct ospf6_lsa_header *lsa_header;
215
216 /* calculate length */
217 ospf6_header = (struct ospf6_header *) message[0].iov_base;
218 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
219 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
220 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
221
222 lsupdate = (struct ospf6_lsupdate *) message[1].iov_base;
223 lsanum = ntohl (lsupdate->lsupdate_num);
224
225 zlog_info (" Number of LSA: #%d", lsanum);
226
227 for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1);
228 (char *)lsa_header < (char *)(message[1].iov_base + message[1].iov_len) &&
229 (char *)lsa_header < (char *)(message[1].iov_base + length_left);
230 lsa_header = OSPF6_LSA_NEXT (lsa_header))
231 ospf6_message_log_lsa_header (lsa_header);
232 length_left -= message[1].iov_len;
233
234 for (i = 2; message[i].iov_base; i++)
235 {
236
237 for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
238 (char *)lsa_header < (char *) (message[i].iov_base + message[i].iov_len) &&
239 (char *)lsa_header < (char *) (message[i].iov_base + length_left);
240 lsa_header = OSPF6_LSA_NEXT (lsa_header))
241 ospf6_message_log_lsa_header (lsa_header);
242 length_left -= message[i].iov_len;
243 }
244}
245
246static void
247ospf6_message_log_lsack (struct iovec *message)
248{
249 struct ospf6_header *ospf6_header;
250 u_int16_t length_left;
251 struct ospf6_lsa_header *lsa_header;
252 int i;
253
254 /* calculate length */
255 ospf6_header = (struct ospf6_header *) message[0].iov_base;
256 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
257 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
258 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
259
260 for (i = 1; message[i].iov_base; i++)
261 {
262 for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
263 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base +
264 message[i].iov_len) &&
265 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left);
266 lsa_header++)
267 ospf6_message_log_lsa_header (lsa_header);
268 length_left -= message[i].iov_len;
269 }
270}
271
272struct {
273 void (*message_log) (struct iovec *);
274} ospf6_message_log_body [] =
275{
276 {ospf6_message_log_unknown},
277 {ospf6_message_log_hello},
278 {ospf6_message_log_dbdesc},
279 {ospf6_message_log_lsreq},
280 {ospf6_message_log_lsupdate},
281 {ospf6_message_log_lsack},
282};
283
284static void
285ospf6_message_log (struct iovec *message)
286{
287 struct ospf6_header *o6h;
288 char router_id[16], area_id[16];
289 u_char type;
290
291 assert (message[0].iov_len == sizeof (struct ospf6_header));
292 o6h = (struct ospf6_header *) message[0].iov_base;
293
294 inet_ntop (AF_INET, &o6h->router_id, router_id, sizeof (router_id));
295 inet_ntop (AF_INET, &o6h->area_id, area_id, sizeof (area_id));
296
297 zlog_info (" OSPFv%d Type:%d Len:%hu RouterID:%s",
298 o6h->version, o6h->type, ntohs (o6h->len), router_id);
299 zlog_info (" AreaID:%s Cksum:%hx InstanceID:%d",
300 area_id, ntohs (o6h->cksum), o6h->instance_id);
301
302 type = (OSPF6_MESSAGE_TYPE_UNKNOWN < o6h->type &&
303 o6h->type <= OSPF6_MESSAGE_TYPE_LSACK ?
304 o6h->type : OSPF6_MESSAGE_TYPE_UNKNOWN);
305 (* ospf6_message_log_body[type].message_log) (&message[0]);
306}
307
308int
309ospf6_opt_is_mismatch (unsigned char opt, char *options1, char *options2)
310{
311 return (OSPF6_OPT_ISSET (options1, opt) ^ OSPF6_OPT_ISSET (options2, opt));
312}
313
314
315void
316ospf6_process_unknown (struct iovec *message,
317 struct in6_addr *src,
318 struct in6_addr *dst,
319 struct ospf6_interface *o6i,
320 u_int32_t router_id)
321{
322 zlog_warn ("unknown message type, drop");
323}
324
325void
326ospf6_process_hello (struct iovec *message,
327 struct in6_addr *src,
328 struct in6_addr *dst,
329 struct ospf6_interface *o6i,
330 u_int32_t router_id)
331{
332 struct ospf6_header *ospf6_header;
333 u_int16_t length;
334 struct ospf6_hello *hello;
335 char changes = 0;
336#define CHANGE_RTRPRI (1 << 0)
337#define CHANGE_DR (1 << 1)
338#define CHANGE_BDR (1 << 2)
339 int twoway = 0, backupseen = 0, nbchange = 0;
340 u_int32_t *router_id_ptr;
341 int i, seenrtrnum = 0, router_id_space = 0;
342 char strbuf[64];
343 struct ospf6_neighbor *o6n = NULL;
344
345 /* assert interface */
346 assert (o6i);
347
348 /* caluculate length */
349 ospf6_header = (struct ospf6_header *) message[0].iov_base;
350 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
351 length = (length < message[1].iov_len ? length : message[1].iov_len);
352
353 /* set hello pointer */
354 hello = (struct ospf6_hello *) message[1].iov_base;
355
356 /* find neighbor. if cannot be found, create */
357 o6n = ospf6_neighbor_lookup (router_id, o6i);
358 if (!o6n)
359 {
360 o6n = ospf6_neighbor_create (router_id, o6i);
361 o6n->ifid = ntohl (hello->interface_id);
362 o6n->prevdr = o6n->dr = hello->dr;
363 o6n->prevbdr = o6n->bdr = hello->bdr;
364 o6n->priority = hello->rtr_pri;
365 memcpy (&o6n->hisaddr, src, sizeof (struct in6_addr));
366 }
367
368 /* HelloInterval check */
369 if (ntohs (hello->hello_interval) != o6i->hello_interval)
370 {
371 zlog_warn ("HelloInterval mismatch with %s", o6n->str);
372 return;
373 }
374
375 /* RouterDeadInterval check */
376 if (ntohs (hello->router_dead_interval)
377 != o6i->dead_interval)
378 {
379 zlog_warn ("RouterDeadInterval mismatch with %s", o6n->str);
380 return;
381 }
382
383 /* check options */
384 /* Ebit */
385 if (ospf6_opt_is_mismatch (OSPF6_OPT_E, hello->options, o6i->area->options))
386 {
387 zlog_warn ("Ebit mismatch with %s", o6n->str);
388 return;
389 }
390
391 /* RouterPriority set */
392 if (o6n->priority != hello->rtr_pri)
393 {
394 o6n->priority = hello->rtr_pri;
395 if (IS_OSPF6_DUMP_HELLO)
396 zlog_info ("%s: RouterPriority changed", o6n->str);
397 changes |= CHANGE_RTRPRI;
398 }
399
400 /* DR set */
401 if (o6n->dr != hello->dr)
402 {
403 /* save previous dr, set current */
404 o6n->prevdr = o6n->dr;
405 o6n->dr = hello->dr;
406 inet_ntop (AF_INET, &o6n->dr, strbuf, sizeof (strbuf));
407 if (IS_OSPF6_DUMP_HELLO)
408 zlog_info ("%s declare %s as DR", o6n->str, strbuf);
409 changes |= CHANGE_DR;
410 }
411
412 /* BDR set */
413 if (o6n->bdr != hello->bdr)
414 {
415 /* save previous bdr, set current */
416 o6n->prevbdr = o6n->bdr;
417 o6n->bdr = hello->bdr;
418 inet_ntop (AF_INET, &o6n->bdr, strbuf, sizeof (strbuf));
419 if (IS_OSPF6_DUMP_HELLO)
420 zlog_info ("%s declare %s as BDR", o6n->str, strbuf);
421 changes |= CHANGE_BDR;
422 }
423
424 /* TwoWay check */
425 router_id_space = length - sizeof (struct ospf6_hello);
426 seenrtrnum = router_id_space / sizeof (u_int32_t);
427 router_id_ptr = (u_int32_t *) (hello + 1);
428 for (i = 0; i < seenrtrnum; i++)
429 {
430 if (*router_id_ptr == o6i->area->ospf6->router_id)
431 twoway++;
432 router_id_ptr++;
433 }
434
435 /* execute neighbor events */
436 thread_execute (master, hello_received, o6n, 0);
437 if (twoway)
438 thread_execute (master, twoway_received, o6n, 0);
439 else
440 thread_execute (master, oneway_received, o6n, 0);
441
442 /* BackupSeen check */
443 if (o6i->state == IFS_WAITING)
444 {
445 if (hello->dr == hello->bdr &&
446 hello->dr == o6n->router_id)
447 zlog_warn ("*** DR Election of %s is illegal", o6n->str);
448
449 if (hello->bdr == o6n->router_id)
450 backupseen++;
451 else if (hello->dr == o6n->router_id && hello->bdr == 0)
452 backupseen++;
453 }
454
455 /* NeighborChange check */
456 if (changes & CHANGE_RTRPRI)
457 nbchange++;
458 if (changes & CHANGE_DR)
459 if (o6n->prevdr == o6n->router_id || o6n->dr == o6n->router_id)
460 nbchange++;
461 if (changes & CHANGE_BDR)
462 if (o6n->prevbdr == o6n->router_id || o6n->bdr == o6n->router_id)
463 nbchange++;
464
465 /* schedule interface events */
466 if (backupseen)
467 thread_add_event (master, backup_seen, o6i, 0);
468 if (nbchange)
469 thread_add_event (master, neighbor_change, o6i, 0);
470
471 return;
472}
473
474int
475ospf6_dbdesc_is_master (struct ospf6_neighbor *o6n)
476{
477 char buf[128];
478
479 if (o6n->router_id == ospf6->router_id)
480 {
481 inet_ntop (AF_INET6, &o6n->hisaddr, buf, sizeof (buf));
482 zlog_warn ("Message: Neighbor router-id conflicts: %s: %s",
483 o6n->str, buf);
484 return -1;
485 }
486 else if (ntohl (o6n->router_id) > ntohl (ospf6->router_id))
487 return 0;
488 return 1;
489}
490
491int
492ospf6_dbdesc_is_duplicate (struct ospf6_dbdesc *received,
493 struct ospf6_dbdesc *last_received)
494{
495 if (memcmp (received->options, last_received->options, 3) != 0)
496 return 0;
497 if (received->ifmtu != last_received->ifmtu)
498 return 0;
499 if (received->bits != last_received->bits)
500 return 0;
501 if (received->seqnum != last_received->seqnum)
502 return 0;
503 return 1;
504}
505
506void
507ospf6_process_dbdesc_master (struct iovec *message, struct ospf6_neighbor *o6n)
508{
509 struct ospf6_header *ospf6_header;
510 u_int16_t length, lsa_count;
511 struct ospf6_dbdesc *dbdesc;
512 struct ospf6_lsa_header *lsa_header;
513
514 /* caluculate length */
515 ospf6_header = (struct ospf6_header *) message[0].iov_base;
516 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
517 length = (length < message[1].iov_len ? length : message[1].iov_len);
518
519 /* set database description pointer */
520 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
521
522 switch (o6n->state)
523 {
524 case NBS_DOWN:
525 case NBS_ATTEMPT:
526 case NBS_TWOWAY:
527 if (IS_OSPF6_DUMP_DBDESC)
528 zlog_info ("DbDesc from %s Ignored: state less than Init",
529 o6n->str);
530 return;
531
532 case NBS_INIT:
533 thread_execute (master, twoway_received, o6n, 0);
534 if (o6n->state != NBS_EXSTART)
535 {
536 if (IS_OSPF6_DUMP_DBDESC)
537 zlog_info ("DbDesc from %s Ignored: state less than ExStart",
538 o6n->str);
539 return;
540 }
541 /* else fall through to ExStart */
542 case NBS_EXSTART:
543 if (DDBIT_IS_SLAVE (dbdesc->bits) &&
544 !DDBIT_IS_INITIAL (dbdesc->bits) &&
545 ntohl (dbdesc->seqnum) == o6n->dbdesc_seqnum)
546 {
547 ospf6_neighbor_dbex_init (o6n);
548
549 if (o6n->thread_rxmt_dbdesc)
550 thread_cancel (o6n->thread_rxmt_dbdesc);
551 o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
552
553 thread_add_event (master, negotiation_done, o6n, 0);
554 }
555 else
556 {
557 if (IS_OSPF6_DUMP_DBDESC)
558 zlog_info (" negotiation failed with %s", o6n->str);
559 return;
560 }
561 break;
562
563 case NBS_EXCHANGE:
564 /* duplicate dbdesc dropped by master */
565 if (!memcmp (dbdesc, &o6n->last_dd,
566 sizeof (struct ospf6_dbdesc)))
567 {
568 if (IS_OSPF6_DUMP_DBDESC)
569 zlog_info (" duplicate dbdesc, drop");
570 return;
571 }
572
573 /* check Initialize bit and Master/Slave bit */
574 if (DDBIT_IS_INITIAL (dbdesc->bits))
575 {
576 if (IS_OSPF6_DUMP_DBDESC)
577 zlog_info ("Initialize bit mismatch");
578 thread_add_event (master, seqnumber_mismatch, o6n, 0);
579 return;
580 }
581 if (DDBIT_IS_MASTER (dbdesc->bits))
582 {
583 if (IS_OSPF6_DUMP_DBDESC)
584 zlog_info ("Master/Slave bit mismatch");
585 thread_add_event (master, seqnumber_mismatch, o6n, 0);
586 return;
587 }
588
589 /* dbdesc option check */
590 if (memcmp (dbdesc->options, o6n->last_dd.options,
591 sizeof (dbdesc->options)))
592 {
593 if (IS_OSPF6_DUMP_DBDESC)
594 zlog_info ("dbdesc option field changed");
595 thread_add_event (master, seqnumber_mismatch, o6n, 0);
596 return;
597 }
598
599 /* dbdesc sequence number check */
600 if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum)
601 {
602 if (IS_OSPF6_DUMP_DBDESC)
603 zlog_warn ("*** dbdesc seqnumber mismatch: %d expected",
604 o6n->dbdesc_seqnum);
605 thread_add_event (master, seqnumber_mismatch, o6n, 0);
606 return;
607 }
608 break;
609
610 case NBS_LOADING:
611 case NBS_FULL:
612 /* duplicate dbdesc dropped by master */
613 if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd))
614 {
615 if (IS_OSPF6_DUMP_DBDESC)
616 zlog_info (" duplicate dbdesc, drop");
617 return;
618 }
619 else
620 {
621 if (IS_OSPF6_DUMP_DBDESC)
622 zlog_info (" not duplicate dbdesc in state %s",
623 ospf6_neighbor_state_string[o6n->state]);
624 thread_add_event (master, seqnumber_mismatch, o6n, 0);
625 return;
626 }
627 break; /* not reached */
628
629 default:
630 assert (0);
631 break; /* not reached */
632 }
633
634 /* process LSA headers */
635 lsa_count = 0;
636 for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
637 (char *)(lsa_header + 1) <= (char *)dbdesc + length;
638 lsa_header++)
639 {
640 if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0)
641 {
642 thread_add_event (master, seqnumber_mismatch, o6n, 0);
643 return;
644 }
645 lsa_count ++;
646 }
647
648 /* increment dbdesc seqnum */
649 o6n->dbdesc_seqnum++;
650
651 /* cancel transmission/retransmission thread */
652 if (o6n->thread_send_dbdesc)
653 thread_cancel (o6n->thread_send_dbdesc);
654 o6n->thread_send_dbdesc = (struct thread *) NULL;
655 if (o6n->thread_rxmt_dbdesc)
656 thread_cancel (o6n->thread_rxmt_dbdesc);
657 o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
658
659 /* more bit check */
660 if (!DD_IS_MBIT_SET (dbdesc->bits) && !DD_IS_MBIT_SET (o6n->dbdesc_bits))
661 thread_add_event (master, exchange_done, o6n, 0);
662 else
663 o6n->thread_send_dbdesc =
664 thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
665
666 /* save last received dbdesc */
667 memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc));
668
669 /* statistics */
670 o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count;
671
672 return;
673}
674
675void
676ospf6_process_dbdesc_slave (struct iovec *message, struct ospf6_neighbor *o6n)
677{
678 struct ospf6_header *ospf6_header;
679 u_int16_t length, lsa_count;
680 struct ospf6_dbdesc *dbdesc;
681 struct ospf6_lsa_header *lsa_header;
682
683 /* caluculate length */
684 ospf6_header = (struct ospf6_header *) message[0].iov_base;
685 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
686 length = (length < message[1].iov_len ? length : message[1].iov_len);
687
688 /* set database description pointer */
689 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
690
691 switch (o6n->state)
692 {
693 case NBS_DOWN:
694 case NBS_ATTEMPT:
695 case NBS_TWOWAY:
696 return;
697 case NBS_INIT:
698 thread_execute (master, twoway_received, o6n, 0);
699 if (o6n->state != NBS_EXSTART)
700 {
701 return;
702 }
703 /* else fall through to ExStart */
704 case NBS_EXSTART:
705 if (DD_IS_IBIT_SET (dbdesc->bits) &&
706 DD_IS_MBIT_SET (dbdesc->bits) &&
707 DD_IS_MSBIT_SET (dbdesc->bits))
708 {
709 /* Master/Slave bit set to slave */
710 DD_MSBIT_CLEAR (o6n->dbdesc_bits);
711 /* Initialize bit clear */
712 DD_IBIT_CLEAR (o6n->dbdesc_bits);
713 /* sequence number set to master's */
714 o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum);
715 ospf6_neighbor_dbex_init (o6n);
716
717 if (o6n->thread_rxmt_dbdesc)
718 thread_cancel (o6n->thread_rxmt_dbdesc);
719 o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
720
721 thread_add_event (master, negotiation_done, o6n, 0);
722 }
723 else
724 {
725 if (IS_OSPF6_DUMP_DBDESC)
726 zlog_info ("negotiation failed");
727 return;
728 }
729 break;
730
731 case NBS_EXCHANGE:
732 /* duplicate dbdesc dropped by master */
733 if (!memcmp (dbdesc, &o6n->last_dd,
734 sizeof (struct ospf6_dbdesc)))
735 {
736 if (IS_OSPF6_DUMP_DBDESC)
737 zlog_info (" duplicate dbdesc, retransmit dbdesc");
738
739 if (o6n->thread_rxmt_dbdesc)
740 thread_cancel (o6n->thread_rxmt_dbdesc);
741 o6n->thread_rxmt_dbdesc =
742 thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0);
743
744 return;
745 }
746
747 /* check Initialize bit and Master/Slave bit */
748 if (DDBIT_IS_INITIAL (dbdesc->bits))
749 {
750 if (IS_OSPF6_DUMP_DBDESC)
751 zlog_info ("Initialize bit mismatch");
752 thread_add_event (master, seqnumber_mismatch, o6n, 0);
753 return;
754 }
755 if (DDBIT_IS_SLAVE (dbdesc->bits))
756 {
757 if (IS_OSPF6_DUMP_DBDESC)
758 zlog_info ("Master/Slave bit mismatch");
759 thread_add_event (master, seqnumber_mismatch, o6n, 0);
760 return;
761 }
762
763 /* dbdesc option check */
764 if (memcmp (dbdesc->options, o6n->last_dd.options,
765 sizeof (dbdesc->options)))
766 {
767 if (IS_OSPF6_DUMP_DBDESC)
768 zlog_info ("dbdesc option field changed");
769 thread_add_event (master, seqnumber_mismatch, o6n, 0);
770 return;
771 }
772
773 /* dbdesc sequence number check */
774 if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum + 1)
775 {
776 if (IS_OSPF6_DUMP_DBDESC)
777 zlog_warn ("*** dbdesc seqnumber mismatch: %d expected",
778 o6n->dbdesc_seqnum + 1);
779 thread_add_event (master, seqnumber_mismatch, o6n, 0);
780 return;
781 }
782 break;
783
784 case NBS_LOADING:
785 case NBS_FULL:
786 /* duplicate dbdesc cause slave to retransmit */
787 if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd))
788 {
789 if (IS_OSPF6_DUMP_DBDESC)
790 zlog_info (" duplicate dbdesc, retransmit");
791
792 if (o6n->thread_rxmt_dbdesc)
793 thread_cancel (o6n->thread_rxmt_dbdesc);
794 o6n->thread_rxmt_dbdesc =
795 thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0);
796
797 return;
798 }
799 else
800 {
801 if (IS_OSPF6_DUMP_DBDESC)
802 zlog_info (" not duplicate dbdesc in state %s",
803 ospf6_neighbor_state_string[o6n->state]);
804 thread_add_event (master, seqnumber_mismatch, o6n, 0);
805 return;
806 }
807 break; /* not reached */
808
809 default:
810 assert (0);
811 break; /* not reached */
812 }
813
814 /* process LSA headers */
815 lsa_count = 0;
816 for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
817 (char *)(lsa_header + 1) <= (char *)dbdesc + length;
818 lsa_header++)
819 {
820 if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0)
821 {
822 thread_add_event (master, seqnumber_mismatch, o6n, 0);
823 return;
824 }
825 lsa_count ++;
826 }
827
828 /* set dbdesc seqnum to master's */
829 o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum);
830
831 if (o6n->thread_send_dbdesc)
832 thread_cancel (o6n->thread_send_dbdesc);
833 o6n->thread_send_dbdesc =
834 thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
835
836 /* save last received dbdesc */
837 memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc));
838
839 /* statistics */
840 o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count;
841
842 return;
843}
844
845void
846ospf6_process_dbdesc (struct iovec *message,
847 struct in6_addr *src,
848 struct in6_addr *dst,
849 struct ospf6_interface *o6i,
850 u_int32_t router_id)
851{
852 struct ospf6_header *ospf6_header;
853 u_int16_t length;
854 struct ospf6_neighbor *o6n;
855 struct ospf6_dbdesc *dbdesc;
856 int Im_master = 0;
857
858 /* assert interface */
859 assert (o6i);
860
861 /* caluculate length */
862 ospf6_header = (struct ospf6_header *) message[0].iov_base;
863 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
864 length = (length < message[1].iov_len ? length : message[1].iov_len);
865
866 /* set database description pointer */
867 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
868
869 /* find neighbor. if cannot be found, reject this message */
870 o6n = ospf6_neighbor_lookup (router_id, o6i);
871 if (!o6n)
872 {
873 if (IS_OSPF6_DUMP_DBDESC)
874 zlog_info ("neighbor not found, reject");
875 return;
876 }
877
878 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
879 {
880 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
881 zlog_info ("From Secondary I/F of the neighbor: ignore");
882 return;
883 }
884
885 /* interface mtu check */
886 /* xxx */
887
888 /* check am I master */
889 Im_master = ospf6_dbdesc_is_master (o6n);
890 if (Im_master < 0)
891 {
892 return; /* can't decide which is master, return */
893 }
894
895 if (Im_master)
896 ospf6_process_dbdesc_master (message, o6n);
897 else
898 ospf6_process_dbdesc_slave (message, o6n);
899
900 return;
901}
902
903void
904ospf6_process_lsreq (struct iovec *message,
905 struct in6_addr *src,
906 struct in6_addr *dst,
907 struct ospf6_interface *o6i,
908 u_int32_t router_id)
909{
910 struct ospf6_header *ospf6_header;
911 u_int16_t length;
912 struct ospf6_neighbor *o6n;
913 struct ospf6_lsreq *lsreq;
914 struct iovec response[OSPF6_MESSAGE_IOVEC_SIZE];
915 struct ospf6_lsa *lsa;
916 unsigned long lsanum = 0;
917 struct ospf6_lsupdate lsupdate;
918 char buf_id[16], buf_router[16], buf_type[16];
919
920 /* assert interface */
921 assert (o6i);
922
923 /* caluculate length */
924 ospf6_header = (struct ospf6_header *) message[0].iov_base;
925 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
926 length = (length < message[1].iov_len ? length : message[1].iov_len);
927
928 /* find neighbor. if cannot be found, reject this message */
929 o6n = ospf6_neighbor_lookup (router_id, o6i);
930 if (!o6n)
931 {
932 if (IS_OSPF6_DUMP_LSREQ)
933 zlog_info (" neighbor not found, reject");
934 return;
935 }
936
937 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
938 {
939 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
940 zlog_info ("From Secondary I/F of the neighbor: ignore");
941 return;
942 }
943
944 /* In states other than ExChange, Loading, or Full, the packet
945 should be ignored. */
946 if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING
947 && o6n->state != NBS_FULL)
948 {
949 if (IS_OSPF6_DUMP_LSREQ)
950 zlog_info (" neighbor state less than Exchange, reject");
951 return;
952 }
953
954 /* Initialize response LSUpdate packet */
955 OSPF6_MESSAGE_CLEAR (response);
956 memset (&lsupdate, 0, sizeof (struct ospf6_lsupdate));
957 OSPF6_MESSAGE_ATTACH (response, &lsupdate, sizeof (struct ospf6_lsupdate));
958
959 /* process each request */
960 lsanum = 0;
961 for (lsreq = (struct ospf6_lsreq *) message[1].iov_base;
962 (char *)(lsreq + 1) <= (char *)(message[1].iov_base + length);
963 lsreq++)
964 {
965 inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router));
966 inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id));
967
968 /* find instance of database copy */
969 lsa = ospf6_lsdb_lookup (lsreq->type, lsreq->id, lsreq->adv_router,
970 ospf6_lsa_get_scope (lsreq->type, o6i));
971
972 if (!lsa)
973 {
974 if (IS_OSPF6_DUMP_LSREQ)
975 zlog_info ("BadLSReq: %s requests [%s ID=%s Adv=%s] not found",
976 o6n->str, ospf6_lsa_type_string (lsreq->type, buf_type,
977 sizeof (buf_type)),
978 buf_id, buf_router);
979 thread_add_event (master, bad_lsreq, o6n, 0);
980 return;
981 }
982
983 /* I/F MTU check */
984 if (sizeof (struct ospf6_header) + sizeof (struct ospf6_lsupdate)
985 + iov_totallen (response) + ntohs (lsa->header->length)
986 > o6i->ifmtu)
987 break;
988
989 OSPF6_MESSAGE_ATTACH (response, lsa->header, ntohs (lsa->header->length));
990 lsanum++;
991 }
992
993 /* send response LSUpdate to this request */
994 if (lsanum)
995 {
996 lsupdate.lsupdate_num = htonl (lsanum);
997
998 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, response,
999 &o6n->hisaddr, o6i->if_id);
1000 }
1001
1002 /* statistics */
1003 o6n->lsa_receive[OSPF6_MESSAGE_TYPE_LSREQ]
1004 += length / sizeof (struct ospf6_lsreq);
1005}
1006
1007void
1008ospf6_process_lsupdate (struct iovec *message,
1009 struct in6_addr *src,
1010 struct in6_addr *dst,
1011 struct ospf6_interface *o6i,
1012 u_int32_t router_id)
1013{
1014 struct ospf6_header *ospf6_header;
1015 u_int16_t length;
1016 struct ospf6_lsupdate *lsupdate;
1017 struct ospf6_neighbor *o6n;
1018 unsigned long lsanum;
1019 struct ospf6_lsa_header *lsa_header;
1020
1021 /* assert interface */
1022 assert (o6i);
1023
1024 /* caluculate length */
1025 ospf6_header = (struct ospf6_header *) message[0].iov_base;
1026 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
1027 length = (length < message[1].iov_len ? length : message[1].iov_len);
1028
1029 /* find neighbor. if cannot be found, reject this message */
1030 o6n = ospf6_neighbor_lookup (router_id, o6i);
1031 if (! o6n)
1032 {
1033 if (IS_OSPF6_DUMP_LSUPDATE)
1034 zlog_info (" neighbor not found, reject");
1035 return;
1036 }
1037
1038 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
1039 {
1040 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1041 zlog_info ("From Secondary I/F of the neighbor: ignore");
1042 return;
1043 }
1044
1045 /* if neighbor state less than ExChange, reject this message */
1046 if (o6n->state < NBS_EXCHANGE)
1047 {
1048 if (IS_OSPF6_DUMP_LSUPDATE)
1049 zlog_info (" neighbor state less than Exchange, reject");
1050 return;
1051 }
1052
1053 /* set linkstate update pointer */
1054 lsupdate = (struct ospf6_lsupdate *) message[1].iov_base;
1055
1056 /* save linkstate update info */
1057 lsanum = ntohl (lsupdate->lsupdate_num);
1058
1059 /* statistics */
1060 o6n->ospf6_stat_received_lsa += lsanum;
1061 o6n->ospf6_stat_received_lsupdate++;
1062
1063 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1064 with the proper Link State Update packet(s), the Link state request
1065 list is truncated and a new Link State Request packet is sent. */
1066
1067 /* process LSAs */
1068 for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1);
1069 lsanum && (char *)lsa_header < (char *)lsupdate + length;
1070 lsanum--)
1071 {
1072 ospf6_dbex_receive_lsa (lsa_header, o6n);
1073 lsa_header = OSPF6_LSA_NEXT (lsa_header);
1074 }
1075
1076 /* send new Link State Request packet if this LS Update packet
1077 can be recognized as a response to our previous LS request */
1078 if (! IN6_IS_ADDR_MULTICAST(dst) &&
1079 (o6n->state == NBS_EXCHANGE || o6n->state == NBS_LOADING))
1080 thread_add_event (master, ospf6_send_lsreq, o6n, 0);
1081
1082 return;
1083}
1084
1085void
1086ospf6_process_lsack (struct iovec *message,
1087 struct in6_addr *src,
1088 struct in6_addr *dst,
1089 struct ospf6_interface *o6i,
1090 u_int32_t router_id)
1091{
1092 struct ospf6_header *ospf6_header;
1093 u_int16_t length;
1094 struct ospf6_neighbor *o6n;
1095 struct ospf6_lsa_header *lsa_header;
1096 struct ospf6_lsa *lsa, *copy, *rem;
1097
1098 /* assert interface */
1099 assert (o6i);
1100
1101 /* caluculate length */
1102 ospf6_header = (struct ospf6_header *) message[0].iov_base;
1103 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
1104 length = (length < message[1].iov_len ? length : message[1].iov_len);
1105
1106 /* find neighbor. if cannot be found, reject this message */
1107 o6n = ospf6_neighbor_lookup (router_id, o6i);
1108 if (!o6n)
1109 {
1110 if (IS_OSPF6_DUMP_LSACK)
1111 zlog_info ("LSACK: neighbor not found, reject");
1112 return;
1113 }
1114
1115 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
1116 {
1117 if (IS_OSPF6_DUMP_LSACK)
1118 zlog_info ("LSACK: From Secondary I/F of the neighbor: ignore");
1119 return;
1120 }
1121
1122 /* if neighbor state less than ExChange, reject this message */
1123 if (o6n->state < NBS_EXCHANGE)
1124 {
1125 if (IS_OSPF6_DUMP_LSACK)
1126 zlog_info ("LSACK: neighbor state less than Exchange, reject");
1127 return;
1128 }
1129
1130 /* process each LSA header */
1131 for (lsa_header = (struct ospf6_lsa_header *) message[1].iov_base;
1132 (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + length);
1133 lsa_header++)
1134 {
1135 /* find database copy */
1136 copy = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id,
1137 lsa_header->advrtr,
1138 ospf6_lsa_get_scope (lsa_header->type, o6i));
1139
1140 /* if no database copy */
1141 if (!copy)
1142 {
1143 if (IS_OSPF6_DUMP_LSACK)
1144 zlog_info ("LSACK: no database copy, ignore");
1145 continue;
1146 }
1147
1148 /* if not on his retrans list */
1149 rem = ospf6_lsdb_lookup_lsdb (copy->header->type, copy->header->id,
1150 copy->header->adv_router,
1151 o6n->retrans_list);
1152 if (rem == NULL)
1153 {
1154 if (IS_OSPF6_DUMP_LSACK)
1155 zlog_info ("LSACK: not on %s's retranslist, ignore", o6n->str);
1156 continue;
1157 }
1158
1159 /* create temporary LSA from Ack message */
1160 lsa = ospf6_lsa_summary_create ((struct ospf6_lsa_header__ *) lsa_header);
1161
1162 /* if the same instance, remove from retrans list.
1163 else, log and ignore */
1164 if (ospf6_lsa_check_recent (lsa, copy) == 0)
1165 ospf6_neighbor_retrans_remove (rem, o6n);
1166 else
1167 {
1168 /* Log the questionable acknowledgement,
1169 and examine the next one. */
1170 zlog_info ("LSACK: questionable acknowledge: %s", copy->str);
1171 zlog_info ("LSACK: received: seq: %#x age: %hu",
1172 ntohl (lsa->header->seqnum),
1173 ntohs (lsa->header->age));
1174 zlog_info ("LSACK: instance: seq: %#x age: %hu",
1175 ntohl (copy->header->seqnum),
1176 ospf6_lsa_age_current (copy));
1177 }
1178
1179 /* release temporary LSA from Ack message */
1180 ospf6_lsa_delete (lsa);
1181 }
1182
1183 ospf6_maxage_remover ();
1184 return;
1185}
1186
1187struct {
1188 void (*process) (struct iovec *, struct in6_addr *, struct in6_addr *,
1189 struct ospf6_interface *, u_int32_t);
1190} ospf6_message_process_type [] =
1191{
1192 {ospf6_process_unknown},
1193 {ospf6_process_hello},
1194 {ospf6_process_dbdesc},
1195 {ospf6_process_lsreq},
1196 {ospf6_process_lsupdate},
1197 {ospf6_process_lsack}
1198};
1199
1200/* process ospf6 protocol header. then, call next process function
1201 for each message type */
1202static void
1203ospf6_message_process (struct iovec *message,
1204 struct in6_addr *src,
1205 struct in6_addr *dst,
1206 struct ospf6_interface *o6i)
1207{
1208 struct ospf6_header *ospf6_header = NULL;
1209 u_char type;
1210 u_int32_t router_id;
1211 char srcname[64];
1212
1213 assert (o6i);
1214 assert (src);
1215 assert (dst);
1216
1217 /* set ospf6_hdr pointer to head of buffer */
1218 ospf6_header = (struct ospf6_header *) message[0].iov_base;
1219
1220 /* version check */
1221 if (ospf6_header->version != OSPF6_VERSION)
1222 {
1223 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1224 zlog_info ("version mismatch, drop");
1225 return;
1226 }
1227
1228 /* area id check */
1229 if (ospf6_header->area_id != o6i->area->area_id)
1230 {
1231 if (ospf6_header->area_id == 0)
1232 {
1233 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1234 zlog_info ("virtual link not yet, drop");
1235 return;
1236 }
1237
1238 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1239 zlog_info ("area id mismatch, drop");
1240 return;
1241 }
1242
1243 /* instance id check */
1244 if (ospf6_header->instance_id != o6i->instance_id)
1245 {
1246 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1247 zlog_info ("instance id mismatch, drop");
1248 return;
1249 }
1250
1251 /* message type check */
1252 type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ?
1253 OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type);
1254
1255 /* log */
1256 if (IS_OSPF6_DUMP_MESSAGE (type))
1257 {
1258 char srcname[64], dstname[64];
1259 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1260 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1261 zlog_info ("Receive %s on %s",
1262 ospf6_message_type_string[type], o6i->interface->name);
1263 zlog_info (" %s -> %s", srcname, dstname);
1264 ospf6_message_log (message);
1265 }
1266
1267 /* router id check */
1268 router_id = ospf6_header->router_id;
1269 if (ospf6_header->router_id == o6i->area->ospf6->router_id)
1270 {
1271 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1272 zlog_warn ("*** Router-ID mismatch: from %s on %s",
1273 srcname, o6i->interface->name);
1274 return;
1275 }
1276
1277 /* octet statistics relies on some asumption:
1278 on ethernet, no IPv6 Extention header, etc */
1279#define OSPF6_IP6_HEADER_SIZE 40
1280#define OSPF6_ETHER_HEADER_SIZE 14
1281 o6i->message_stat[type].recv++;
1282 o6i->message_stat[type].recv_octet += ntohs (ospf6_header->len)
1283 + OSPF6_IP6_HEADER_SIZE + OSPF6_ETHER_HEADER_SIZE;
1284
1285 /* futher process */
1286 (*ospf6_message_process_type[type].process) (&message[0], src, dst, o6i, router_id);
1287
1288 return;
1289}
1290
1291int
1292ospf6_receive (struct thread *thread)
1293{
1294 int sockfd;
1295 struct in6_addr src, dst;
1296 unsigned int ifindex;
1297 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1298 struct ospf6_header ospf6_header;
1299 char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE];
1300 struct ospf6_interface *o6i;
1301 unsigned char type;
1302
1303 /* get socket */
1304 sockfd = THREAD_FD (thread);
1305
1306 /* add next read thread */
1307 thread_add_read (master, ospf6_receive, NULL, sockfd);
1308
1309 /* initialize */
1310 OSPF6_MESSAGE_CLEAR (message);
1311 memset (&ospf6_header, 0, sizeof (struct ospf6_header));
1312
1313 OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header));
1314 OSPF6_MESSAGE_ATTACH (message, buffer, OSPF6_MESSAGE_RECEIVE_BUFSIZE);
1315
1316 /* receive message */
1317 ospf6_recvmsg (&src, &dst, &ifindex, message);
1318
1319 type = (OSPF6_MESSAGE_TYPE_UNKNOWN < ospf6_header.type &&
1320 ospf6_header.type <= OSPF6_MESSAGE_TYPE_LSACK ?
1321 ospf6_header.type : OSPF6_MESSAGE_TYPE_UNKNOWN);
1322 o6i = ospf6_interface_lookup_by_index (ifindex);
1323 if (!o6i || !o6i->area)
1324 {
1325 //zlog_warn ("*** received interface ospf6 disabled");
1326 return 0;
1327 }
1328
1329 /* if not passive, process message */
1330 if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE))
1331 ospf6_message_process (message, &src, &dst, o6i);
1332 else if (IS_OSPF6_DUMP_MESSAGE (type))
1333 zlog_info ("Ignore message on passive interface %s",
1334 o6i->interface->name);
1335
1336 return 0;
1337}
1338
1339
1340/* send section */
1341int
1342ospf6_message_length (struct iovec *message)
1343{
1344 int i, length = 0;
1345 for (i = 0; i < OSPF6_MESSAGE_IOVEC_SIZE; i++)
1346 {
1347 if (message[i].iov_base == NULL && message[i].iov_len == 0)
1348 break;
1349 length += message[i].iov_len;
1350 }
1351 return length;
1352}
1353#define OSPF6_MESSAGE_LENGTH(msg) \
1354(ospf6_message_length (msg))
1355
1356void
1357ospf6_message_send (unsigned char type, struct iovec *msg,
1358 struct in6_addr *dst, u_int ifindex)
1359{
1360 struct ospf6_interface *o6i;
1361 struct ospf6_header ospf6_header;
1362 char dst_name[64], src_name[64];
1363 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1364 int msg_len;
1365
1366 /* ospf6 interface lookup */
1367 o6i = ospf6_interface_lookup_by_index (ifindex);
1368 assert (o6i);
1369
1370 msg_len = OSPF6_MESSAGE_LENGTH (msg);
1371
1372 /* I/F MTU check */
1373#if 0
1374 if (msg_len + sizeof (struct ospf6_header) >= o6i->interface->mtu)
1375#else
1376 if (msg_len + sizeof (struct ospf6_header) >= o6i->ifmtu)
1377#endif
1378 {
1379 /* If Interface MTU is 0, save the case
1380 since zebra had been failed to get MTU from Kernel */
1381 if (o6i->interface->mtu != 0)
1382 {
1383 zlog_warn ("Message: Send failed on %s: exceeds I/F MTU",
1384 o6i->interface->name);
1385 zlog_warn ("Message: while sending %s: Len:%d MTU:%d",
1386 ospf6_message_type_string[type],
1387 msg_len + sizeof (struct ospf6_header),
1388 o6i->ifmtu);
1389 return;
1390 }
1391 else
1392 {
1393 zlog_warn ("Message: I/F MTU check ignored on %s",
1394 o6i->interface->name);
1395 }
1396 }
1397
1398 /* Initialize */
1399 OSPF6_MESSAGE_CLEAR (message);
1400
1401 /* set OSPF header */
1402 memset (&ospf6_header, 0, sizeof (ospf6_header));
1403 ospf6_header.version = OSPF6_VERSION;
1404 ospf6_header.type = type;
1405 ospf6_header.len = htons (msg_len + sizeof (struct ospf6_header));
1406 ospf6_header.router_id = ospf6->router_id;
1407 ospf6_header.area_id = o6i->area->area_id;
1408 /* checksum is calculated by kernel */
1409 ospf6_header.instance_id = o6i->instance_id;
1410 ospf6_header.reserved = 0;
1411 OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header));
1412
1413 /* Attach rest to message */
1414 OSPF6_MESSAGE_JOIN (message, msg);
1415
1416 /* statistics */
1417 if (type >= OSPF6_MESSAGE_TYPE_MAX)
1418 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1419 o6i->message_stat[type].send++;
1420 o6i->message_stat[type].send_octet += ntohs (ospf6_header.len);
1421
1422 /* log */
1423 if (IS_OSPF6_DUMP_MESSAGE (type))
1424 {
1425 inet_ntop (AF_INET6, dst, dst_name, sizeof (dst_name));
1426 if (o6i->lladdr)
1427 inet_ntop (AF_INET6, o6i->lladdr, src_name, sizeof (src_name));
1428 else
1429 memcpy (src_name, "Unknown", sizeof (src_name));
1430 zlog_info ("Send %s on %s",
1431 ospf6_message_type_string[type], o6i->interface->name);
1432 zlog_info (" %s -> %s", src_name, dst_name);
1433 ospf6_message_log (message);
1434 }
1435
1436 /* send message */
1437 ospf6_sendmsg (o6i->lladdr, dst, &ifindex, message);
1438}
1439
1440
1441int
1442ospf6_send_hello (struct thread *thread)
1443{
1444 listnode n;
1445 struct ospf6_interface *o6i;
1446 struct ospf6_neighbor *o6n;
1447 struct in6_addr dst;
1448 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1449 struct ospf6_hello hello;
1450 char router_buffer[1024]; /* xxx */
1451 u_int router_size;
1452
1453 /* which ospf6 interface to send */
1454 o6i = (struct ospf6_interface *) THREAD_ARG (thread);
1455 o6i->thread_send_hello = (struct thread *) NULL;
1456
1457 /* assure interface is up */
1458 if (o6i->state <= IFS_DOWN)
1459 {
1460 if (IS_OSPF6_DUMP_HELLO)
1461 zlog_warn ("Send HELLO Failed: Interface not enabled: %s",
1462 o6i->interface->name);
1463 return 0;
1464 }
1465
1466 /* clear message buffer */
1467 OSPF6_MESSAGE_CLEAR (message);
1468
1469 /* set Hello fields */
1470 hello.interface_id = htonl (o6i->if_id);
1471 hello.rtr_pri = o6i->priority;
1472 memcpy (hello.options, o6i->area->options, sizeof (hello.options));
1473 hello.hello_interval = htons (o6i->hello_interval);
1474 hello.router_dead_interval = htons (o6i->dead_interval);
1475 hello.dr = o6i->dr;
1476 hello.bdr = o6i->bdr;
1477 OSPF6_MESSAGE_ATTACH (message, &hello, sizeof (struct ospf6_hello));
1478
1479 /* set neighbor router id */
1480 router_size = 0;
1481 for (n = listhead (o6i->neighbor_list); n; nextnode (n))
1482 {
1483 o6n = (struct ospf6_neighbor *) getdata (n);
1484
1485 if (o6n->state < NBS_INIT)
1486 continue;
1487
1488 if (router_size + sizeof (o6n->router_id) > sizeof (router_buffer))
1489 {
1490 zlog_warn ("Send HELLO: Buffer shortage on %s",
1491 o6i->interface->name);
1492 break;
1493 }
1494
1495 /* Copy Router-ID to Buffer */
1496 memcpy (router_buffer + router_size, &o6n->router_id,
1497 sizeof (o6n->router_id));
1498 router_size += sizeof (o6n->router_id);
1499 }
1500 OSPF6_MESSAGE_ATTACH (message, router_buffer, router_size);
1501
1502 /* set destionation */
1503 inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
1504
1505 /* send hello */
1506 ospf6_message_send (OSPF6_MESSAGE_TYPE_HELLO, message, &dst,
1507 o6i->interface->ifindex);
1508
1509 /* set next timer thread */
1510 o6i->thread_send_hello = thread_add_timer (master, ospf6_send_hello,
1511 o6i, o6i->hello_interval);
1512
1513 return 0;
1514}
1515
1516void
1517ospf6_dbdesc_seqnum_init (struct ospf6_neighbor *o6n)
1518{
1519 struct timeval tv;
1520
1521 if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
1522 tv.tv_sec = 1;
1523
1524 o6n->dbdesc_seqnum = tv.tv_sec;
1525
1526 if (IS_OSPF6_DUMP_DBDESC)
1527 zlog_info ("set dbdesc seqnum %d for %s", o6n->dbdesc_seqnum, o6n->str);
1528}
1529
1530int
1531ospf6_send_dbdesc_rxmt (struct thread *thread)
1532{
1533 struct ospf6_lsdb_node node;
1534 struct ospf6_neighbor *o6n;
1535 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1536 struct ospf6_lsa *lsa;
1537 struct ospf6_lsa_header *lsa_header;
1538 struct ospf6_dbdesc dbdesc;
1539
1540 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1541 assert (o6n);
1542
1543 /* clear thread */
1544 o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
1545
1546 /* if state less than ExStart, do nothing */
1547 if (o6n->state < NBS_EXSTART)
1548 return 0;
1549
1550 OSPF6_MESSAGE_CLEAR (message);
1551
1552 /* set dbdesc */
1553 memcpy (dbdesc.options, o6n->ospf6_interface->area->options,
1554 sizeof (dbdesc.options));
1555 dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu);
1556 dbdesc.bits = o6n->dbdesc_bits;
1557 dbdesc.seqnum = htonl (o6n->dbdesc_seqnum);
1558 OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc));
1559
1560 /* if this is not initial, set LSA summary to dbdesc */
1561 if (! DD_IS_IBIT_SET (o6n->dbdesc_bits))
1562 {
1563 for (ospf6_lsdb_head (&node, o6n->dbdesc_list);
1564 ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
1565 {
1566 lsa = node.lsa;
1567
1568 /* xxx, no MTU check: no support for Dynamic MTU change */
1569
1570 /* set age and add InfTransDelay */
1571 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1572
1573 /* set LSA summary to send buffer */
1574 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
1575 OSPF6_MESSAGE_ATTACH (message, lsa_header,
1576 sizeof (struct ospf6_lsa_header));
1577 }
1578 }
1579
1580 /* send dbdesc */
1581 ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr,
1582 o6n->ospf6_interface->interface->ifindex);
1583
1584 /* if master, set futher retransmission */
1585 if (DD_IS_MSBIT_SET (o6n->dbdesc_bits))
1586 o6n->thread_rxmt_dbdesc =
1587 thread_add_timer (master, ospf6_send_dbdesc_rxmt,
1588 o6n, o6n->ospf6_interface->rxmt_interval);
1589
1590 /* statistics */
1591 o6n->ospf6_stat_retrans_dbdesc++;
1592
1593 return 0;
1594}
1595
1596int
1597ospf6_send_dbdesc (struct thread *thread)
1598{
1599 struct ospf6_neighbor *o6n;
1600 struct ospf6_lsa *lsa;
1601 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1602 struct ospf6_dbdesc dbdesc;
1603 struct ospf6_lsdb_node node;
1604
1605 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1606 assert (o6n);
1607
1608 /* clear thread */
1609 o6n->thread_send_dbdesc = (struct thread *) NULL;
1610 if (o6n->thread_rxmt_dbdesc)
1611 thread_cancel (o6n->thread_rxmt_dbdesc);
1612 o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
1613
1614 /* if state less than ExStart, do nothing */
1615 if (o6n->state < NBS_EXSTART)
1616 return 0;
1617
1618 OSPF6_MESSAGE_CLEAR (message);
1619 OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc));
1620
1621 /* clear previous LSA summary sent */
1622 ospf6_lsdb_remove_all (o6n->dbdesc_list);
1623 assert (o6n->dbdesc_list->count == 0);
1624
1625 /* if this is not initial, set LSA summary to dbdesc */
1626 if (! DD_IS_IBIT_SET (o6n->dbdesc_bits))
1627 {
1628 for (ospf6_lsdb_head (&node, o6n->summary_list);
1629 ! ospf6_lsdb_is_end (&node);
1630 ospf6_lsdb_next (&node))
1631 {
1632 lsa = node.lsa;
1633
1634 /* MTU check */
1635 if (OSPF6_MESSAGE_LENGTH (message)
1636 + sizeof (struct ospf6_lsa_header)
1637 + sizeof (struct ospf6_header)
1638 > o6n->ospf6_interface->ifmtu)
1639 break;
1640
1641 /* debug */
1642 if (IS_OSPF6_DUMP_DBDESC)
1643 zlog_info ("Include DbDesc: %s", lsa->str);
1644
1645 /* attach to dbdesclist */
1646 ospf6_neighbor_dbdesc_add (lsa, o6n);
1647 /* detach from summarylist */
1648 ospf6_neighbor_summary_remove (lsa, o6n);
1649
1650 /* set age and add InfTransDelay */
1651 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1652
1653 /* set LSA summary to send buffer */
1654 OSPF6_MESSAGE_ATTACH (message, lsa->header,
1655 sizeof (struct ospf6_lsa_header));
1656 }
1657
1658 if (o6n->summary_list->count == 0)
1659 {
1660 /* Clear more bit */
1661 DD_MBIT_CLEAR (o6n->dbdesc_bits);
1662
1663 /* slave must schedule ExchangeDone on sending, here */
1664 if (! DD_IS_MSBIT_SET (o6n->dbdesc_bits))
1665 {
1666 if (! DD_IS_MBIT_SET (o6n->dbdesc_bits) &&
1667 ! DD_IS_MBIT_SET (o6n->last_dd.bits))
1668 thread_add_event (master, exchange_done, o6n, 0);
1669 }
1670 }
1671 }
1672
1673 /* if this is initial, set seqnum */
1674 if (DDBIT_IS_INITIAL (o6n->dbdesc_bits))
1675 ospf6_dbdesc_seqnum_init (o6n);
1676
1677 /* set dbdesc */
1678 memcpy (dbdesc.options, o6n->ospf6_interface->area->options,
1679 sizeof (dbdesc.options));
1680 dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu);
1681 dbdesc.bits = o6n->dbdesc_bits;
1682 dbdesc.seqnum = htonl (o6n->dbdesc_seqnum);
1683
1684 /* send dbdesc */
1685 ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr,
1686 o6n->ospf6_interface->interface->ifindex);
1687
1688 /* if master, set retransmission */
1689 if (DD_IS_MSBIT_SET (o6n->dbdesc_bits))
1690 o6n->thread_rxmt_dbdesc =
1691 thread_add_timer (master, ospf6_send_dbdesc_rxmt,
1692 o6n, o6n->ospf6_interface->rxmt_interval);
1693
1694 /* statistics */
1695 o6n->lsa_send[OSPF6_MESSAGE_TYPE_DBDESC] += o6n->dbdesc_list->count;
1696
1697 return 0;
1698}
1699
1700int
1701ospf6_send_lsreq_rxmt (struct thread *thread)
1702{
1703 struct ospf6_neighbor *o6n;
1704
1705 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1706 assert (o6n);
1707
1708 o6n->thread_rxmt_lsreq = (struct thread *) NULL;
1709 o6n->thread_send_lsreq = thread_add_event (master, ospf6_send_lsreq, o6n, 0);
1710 return 0;
1711}
1712
1713int
1714ospf6_send_lsreq (struct thread *thread)
1715{
1716 struct ospf6_neighbor *o6n;
1717 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1718 struct ospf6_lsreq lsreq[OSPF6_MESSAGE_IOVEC_SIZE];
1719 struct ospf6_lsa *lsa;
1720 struct ospf6_lsdb_node node;
1721 int i;
1722
1723 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1724 assert (o6n);
1725
1726 /* LSReq will be send only in ExStart or Loading */
1727 if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING)
1728 return 0;
1729
1730 /* clear thread */
1731 o6n->thread_send_lsreq = (struct thread *) NULL;
1732 if (o6n->thread_rxmt_lsreq)
1733 thread_cancel (o6n->thread_rxmt_lsreq);
1734 o6n->thread_rxmt_lsreq = (struct thread *) NULL;
1735
1736 /* schedule loading_done if request list is empty */
1737 if (o6n->request_list->count == 0)
1738 {
1739 thread_add_event (master, loading_done, o6n, 0);
1740 return 0;
1741 }
1742
1743 /* clear message buffer */
1744 OSPF6_MESSAGE_CLEAR (message);
1745
1746 i = 0;
1747 for (ospf6_lsdb_head (&node, o6n->request_list);
1748 ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
1749 {
1750 lsa = node.lsa;
1751
1752 /* Buffer Overflow */
1753 if (i >= OSPF6_MESSAGE_IOVEC_SIZE)
1754 break;
1755
1756 /* I/F MTU check */
1757 if (OSPF6_MESSAGE_LENGTH (message)
1758 + sizeof (struct ospf6_lsreq)
1759 + sizeof (struct ospf6_header)
1760 > o6n->ospf6_interface->ifmtu)
1761 break;
1762
1763 lsreq[i].mbz = 0;
1764 lsreq[i].type = lsa->header->type;
1765 lsreq[i].id = lsa->header->id;
1766 lsreq[i].adv_router = lsa->header->adv_router;
1767
1768 OSPF6_MESSAGE_ATTACH (message, &lsreq[i], sizeof (struct ospf6_lsreq));
1769 i++;
1770 }
1771
1772 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSREQ, message, &o6n->hisaddr,
1773 o6n->ospf6_interface->interface->ifindex);
1774
1775 /* set retransmit thread */
1776 o6n->thread_rxmt_lsreq =
1777 thread_add_timer (master, ospf6_send_lsreq_rxmt,
1778 o6n, o6n->ospf6_interface->rxmt_interval);
1779
1780 /* statistics */
1781 o6n->lsa_send[OSPF6_MESSAGE_TYPE_LSREQ] += i;
1782
1783 return 0;
1784}
1785
1786/* Send LSUpdate directly to the neighbor, from his retransmission list */
1787int
1788ospf6_send_lsupdate_rxmt (struct thread *thread)
1789{
1790 struct ospf6_neighbor *o6n;
1791 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1792 struct ospf6_lsupdate lsupdate;
1793 struct ospf6_lsa *lsa;
1794 struct ospf6_lsdb_node node;
1795
1796 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1797 assert (o6n);
1798
1799 o6n->send_update = (struct thread *) NULL;
1800
1801 if (o6n->ospf6_interface->state <= IFS_WAITING)
1802 return -1;
1803
1804 /* clear message buffer */
1805 OSPF6_MESSAGE_CLEAR (message);
1806
1807 /* set lsupdate header */
1808 lsupdate.lsupdate_num = 0; /* set gradually */
1809 OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
1810
1811 /* for each LSA listed on retransmission-list */
1812 for (ospf6_lsdb_head (&node, o6n->retrans_list);
1813 ! ospf6_lsdb_is_end (&node);
1814 ospf6_lsdb_next (&node))
1815 {
1816 lsa = node.lsa;
1817
1818 /* I/F MTU check */
1819 if (OSPF6_MESSAGE_LENGTH (message)
1820 + sizeof (struct ospf6_lsupdate)
1821 + sizeof (struct ospf6_header)
1822 + ntohs (lsa->header->length)
1823 > o6n->ospf6_interface->ifmtu)
1824 break;
1825
1826 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1827 OSPF6_MESSAGE_ATTACH (message, lsa->header, ntohs (lsa->header->length));
1828 lsupdate.lsupdate_num++;
1829 }
1830
1831 /* check and correct lsupdate */
1832 if (lsupdate.lsupdate_num == 0)
1833 return 0;
1834 lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num);
1835
1836 if (IS_OSPF6_DUMP_LSUPDATE)
1837 zlog_info ("MESSAGE: retrsnsmit LSUpdate to %s", o6n->str);
1838
1839 /* statistics */
1840 o6n->ospf6_stat_retrans_lsupdate++;
1841
1842 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message,
1843 &o6n->hisaddr, o6n->ospf6_interface->if_id);
1844
1845 o6n->send_update = thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n,
1846 o6n->ospf6_interface->rxmt_interval);
1847 return 0;
1848}
1849
1850/* Send LSUpdate containing one LSA directly to the neighbor.
1851 This is "implied acknowledgement" */
1852void
1853ospf6_send_lsupdate_direct (struct ospf6_lsa *lsa, struct ospf6_neighbor *o6n)
1854{
1855 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1856 struct ospf6_lsupdate lsupdate;
1857 int lsa_len;
1858
1859 /* clear message buffer */
1860 OSPF6_MESSAGE_CLEAR (message);
1861
1862 /* set lsupdate header */
1863 lsupdate.lsupdate_num = ntohl (1);
1864 OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
1865
1866 /* set one LSA */
1867 lsa_len = ntohs (lsa->lsa_hdr->lsh_len);
1868 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1869 OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len);
1870
1871 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &o6n->hisaddr,
1872 o6n->ospf6_interface->if_id);
1873}
1874
1875/* Send LSUpdate containing one LSA by multicast.
1876 On non-broadcast link, send it to each neighbor by unicast.
1877 This is ordinary flooding */
1878void
1879ospf6_send_lsupdate_flood (struct ospf6_lsa *lsa, struct ospf6_interface *o6i)
1880{
1881 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1882 struct ospf6_lsupdate lsupdate;
1883 struct in6_addr dst;
1884 int lsa_len;
1885
1886 /* clear message buffer */
1887 OSPF6_MESSAGE_CLEAR (message);
1888
1889 /* set lsupdate header */
1890 lsupdate.lsupdate_num = ntohl (1);
1891 OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
1892
1893 /* set one LSA */
1894 lsa_len = ntohs (lsa->lsa_hdr->lsh_len);
1895 ospf6_lsa_age_update_to_send (lsa, o6i->transdelay);
1896 OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len);
1897
1898 if (if_is_broadcast (o6i->interface))
1899 {
1900 /* set destination */
1901 if (o6i->state == IFS_DR || o6i->state == IFS_BDR)
1902 inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
1903 else
1904 inet_pton (AF_INET6, ALLDROUTERS6, &dst);
1905 }
1906 else
1907 {
1908 /* IPv6 relies on link local multicast */
1909 inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
1910 }
1911
1912 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &dst,
1913 o6i->if_id);
1914}
1915
1916int
1917ospf6_send_lsack_delayed (struct thread *thread)
1918{
1919 struct ospf6_interface *o6i;
1920 struct iovec message[MAXIOVLIST];
1921 struct ospf6_lsa *lsa;
1922 struct ospf6_lsdb_node node;
1923
1924 o6i = THREAD_ARG (thread);
1925 assert (o6i);
1926
1927 if (IS_OSPF6_DUMP_LSACK)
1928 zlog_info ("LSACK: Delayed LSAck for %s\n", o6i->interface->name);
1929
1930 o6i->thread_send_lsack_delayed = (struct thread *) NULL;
1931
1932 if (o6i->state <= IFS_WAITING)
1933 return 0;
1934
1935 if (o6i->ack_list->count == 0)
1936 return 0;
1937
1938 iov_clear (message, MAXIOVLIST);
1939
1940 for (ospf6_lsdb_head (&node, o6i->ack_list);
1941 ! ospf6_lsdb_is_end (&node);
1942 ospf6_lsdb_next (&node))
1943 {
1944 lsa = node.lsa;
1945 if (IS_OVER_MTU (message, o6i->ifmtu, sizeof (struct ospf6_lsa_hdr)))
1946 break;
1947
1948 OSPF6_MESSAGE_ATTACH (message, lsa->header,
1949 sizeof (struct ospf6_lsa_header));
1950 ospf6_interface_delayed_ack_remove (lsa, o6i);
1951 }
1952
1953 /* statistics */
1954 o6i->ospf6_stat_delayed_lsack++;
1955
1956 switch (o6i->state)
1957 {
1958 case IFS_DR:
1959 case IFS_BDR:
1960 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message,
1961 &allspfrouters6.sin6_addr, o6i->if_id);
1962 break;
1963 default:
1964 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message,
1965 &alldrouters6.sin6_addr, o6i->if_id);
1966 break;
1967 }
1968
1969 iov_clear (message, MAXIOVLIST);
1970 return 0;
1971}
1972