]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
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 | ||
24 | #include "ospf6_damp.h" | |
25 | ||
26 | /* global ospf6d variable */ | |
27 | int ospf6_sock; | |
28 | list iflist; | |
29 | list nexthoplist = NULL; | |
30 | struct sockaddr_in6 allspfrouters6; | |
31 | struct sockaddr_in6 alldrouters6; | |
32 | char *recent_reason; /* set by ospf6_lsa_check_recent () */ | |
33 | int proctitle_mode = 0; | |
34 | ||
35 | char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION; | |
36 | ||
37 | \f | |
38 | #define TIMER_SEC_MICRO 1000000 | |
39 | ||
40 | void | |
41 | ospf6_timeval_sub (const struct timeval *t1, const struct timeval *t2, | |
42 | struct timeval *result) | |
43 | { | |
44 | long usec, movedown = 0; | |
45 | ||
46 | if (t1->tv_sec < t2->tv_sec || | |
47 | (t1->tv_sec == t2->tv_sec && t1->tv_usec < t2->tv_usec)) | |
48 | { | |
49 | result->tv_sec = 0; | |
50 | result->tv_usec = 0; | |
51 | return; | |
52 | } | |
53 | ||
54 | if (t1->tv_usec < t2->tv_usec) | |
55 | { | |
56 | usec = t1->tv_usec + TIMER_SEC_MICRO; | |
57 | movedown++; | |
58 | } | |
59 | else | |
60 | usec = t1->tv_usec; | |
61 | result->tv_usec = usec - t2->tv_usec; | |
62 | ||
63 | result->tv_sec = t1->tv_sec - t2->tv_sec - movedown; | |
64 | } | |
65 | ||
66 | void | |
67 | ospf6_timeval_div (const struct timeval *t1, u_int by, | |
68 | struct timeval *result) | |
69 | { | |
70 | long movedown; | |
71 | ||
72 | if (by == 0) | |
73 | { | |
74 | result->tv_sec = 0; | |
75 | result->tv_usec = 0; | |
76 | return; | |
77 | } | |
78 | ||
79 | movedown = t1->tv_sec % by; | |
80 | result->tv_sec = t1->tv_sec / by; | |
81 | result->tv_usec = (t1->tv_usec + movedown * TIMER_SEC_MICRO) / by; | |
82 | } | |
83 | ||
84 | void | |
85 | ospf6_timeval_decode (const struct timeval *t, long *dayp, long *hourp, | |
86 | long *minp, long *secp, long *msecp, long *usecp) | |
87 | { | |
88 | long day, hour, min, sec, msec, usec, left; | |
89 | ||
90 | left = t->tv_sec; | |
91 | day = left / 86400; left -= day * 86400; | |
92 | hour = left / 3600; left -= hour * 3600; | |
93 | min = left / 60; left -= min * 60; | |
94 | sec = left; | |
95 | left = t->tv_usec; | |
96 | msec = left / 1000; left -= msec * 1000; | |
97 | usec = left; | |
98 | ||
99 | if (dayp) *dayp = day; | |
100 | if (hourp) *hourp = hour; | |
101 | if (minp) *minp = min; | |
102 | if (secp) *secp = sec; | |
103 | if (msecp) *msecp = msec; | |
104 | if (usecp) *usecp = usec; | |
105 | } | |
106 | ||
107 | void | |
108 | ospf6_timeval_string (struct timeval *tv, char *buf, int size) | |
109 | { | |
110 | char days[16], hours[16], mins[16], secs[16], msecs[16], usecs[16]; | |
111 | long day, hour, min, sec, msec, usec; | |
112 | ||
113 | ospf6_timeval_decode (tv, &day, &hour, &min, &sec, &msec, &usec); | |
114 | snprintf (days, sizeof (days), "%ld days ", day); | |
115 | snprintf (hours, sizeof (hours), "%ld hours ", hour); | |
116 | snprintf (mins, sizeof (mins), "%ld mins ", min); | |
117 | snprintf (secs, sizeof (secs), "%ld secs ", sec); | |
118 | snprintf (msecs, sizeof (msecs), "%ld msecs ", msec); | |
119 | snprintf (usecs, sizeof (usecs), "%ld usecs ", usec); | |
120 | ||
121 | snprintf (buf, size, "%s%s%s%s%s%s", | |
122 | (day ? days : ""), (hour ? hours : ""), | |
123 | (min ? mins : ""), (sec ? secs : ""), | |
124 | (msec ? msecs : ""), (usec ? usecs : "")); | |
125 | } | |
126 | ||
127 | void | |
128 | ospf6_timeval_string_summary (struct timeval *tv, char *buf, int size) | |
129 | { | |
130 | char days[16], hours[16], mins[16], secs[16], msecs[16], usecs[16]; | |
131 | long day, hour, min, sec, msec, usec; | |
132 | ||
133 | ospf6_timeval_decode (tv, &day, &hour, &min, &sec, &msec, &usec); | |
134 | snprintf (days, sizeof (days), "%02ldd", day); | |
135 | snprintf (hours, sizeof (hours), "%ldh", hour); | |
136 | snprintf (mins, sizeof (mins), "%ldm", min); | |
137 | snprintf (secs, sizeof (secs), "%lds", sec); | |
138 | snprintf (msecs, sizeof (msecs), "%ldms", msec); | |
139 | snprintf (usecs, sizeof (usecs), "%ldus", usec); | |
140 | ||
141 | snprintf (buf, size, "%s%02ld:%02ld:%02ld", | |
142 | (day ? days : ""), hour, min, sec); | |
143 | } | |
144 | ||
145 | /* foreach function */ | |
146 | void | |
147 | ospf6_count_state (void *arg, int val, void *obj) | |
148 | { | |
149 | int *count = (int *) arg; | |
150 | u_char state = val; | |
151 | struct ospf6_neighbor *nei = (struct ospf6_neighbor *) obj; | |
152 | ||
153 | if (nei->state == state) | |
154 | (*count)++; | |
155 | } | |
156 | \f | |
157 | /* VTY commands. */ | |
158 | DEFUN (reload, | |
159 | reload_cmd, | |
160 | "reload", | |
161 | "Reloads\n") | |
162 | { | |
163 | extern void _reload (); | |
164 | _reload (); | |
165 | return CMD_SUCCESS; | |
166 | } | |
167 | ||
168 | DEFUN (garbage_collection, | |
169 | garbage_collection_cmd, | |
170 | "ipv6 ospf6 garbage collect", | |
171 | IPV6_STR | |
172 | OSPF6_STR | |
173 | "garbage collection by hand\n" | |
174 | "Remove Maxages if possible and recalculate routes\n") | |
175 | { | |
176 | ospf6_maxage_remover (); | |
177 | #if 0 | |
178 | ospf6_route_calculation_schedule (); | |
179 | #endif | |
180 | return CMD_SUCCESS; | |
181 | } | |
182 | ||
183 | /* Show version. */ | |
184 | DEFUN (show_version_ospf6, | |
185 | show_version_ospf6_cmd, | |
186 | "show version ospf6", | |
187 | SHOW_STR | |
188 | "Displays ospf6d version\n") | |
189 | { | |
190 | vty_out (vty, "Zebra OSPF6d Version: %s%s", | |
191 | ospf6_daemon_version, VTY_NEWLINE); | |
192 | ||
193 | return CMD_SUCCESS; | |
194 | } | |
195 | ||
196 | /* start ospf6 */ | |
197 | DEFUN (router_ospf6, | |
198 | router_ospf6_cmd, | |
199 | "router ospf6", | |
200 | OSPF6_ROUTER_STR | |
201 | OSPF6_STR) | |
202 | { | |
203 | if (ospf6 == NULL) | |
204 | ospf6_start (); | |
205 | ||
206 | /* set current ospf point. */ | |
207 | vty->node = OSPF6_NODE; | |
208 | vty->index = ospf6; | |
209 | ||
210 | return CMD_SUCCESS; | |
211 | } | |
212 | ||
213 | /* stop ospf6 */ | |
214 | DEFUN (no_router_ospf6, | |
215 | no_router_ospf6_cmd, | |
216 | "no router ospf6", | |
217 | NO_STR | |
218 | OSPF6_ROUTER_STR) | |
219 | { | |
220 | if (!ospf6) | |
221 | vty_out (vty, "OSPFv3 is not running%s", VTY_NEWLINE); | |
222 | else | |
223 | ospf6_stop (); | |
224 | ||
225 | /* return to config node . */ | |
226 | vty->node = CONFIG_NODE; | |
227 | vty->index = NULL; | |
228 | ||
229 | return CMD_SUCCESS; | |
230 | } | |
231 | ||
232 | /* show top level structures */ | |
233 | DEFUN (show_ipv6_ospf6, | |
234 | show_ipv6_ospf6_cmd, | |
235 | "show ipv6 ospf6", | |
236 | SHOW_STR | |
237 | IP6_STR | |
238 | OSPF6_STR) | |
239 | { | |
240 | OSPF6_CMD_CHECK_RUNNING (); | |
241 | ||
242 | ospf6_show (vty); | |
243 | return CMD_SUCCESS; | |
244 | } | |
245 | ||
246 | DEFUN (show_ipv6_ospf6_nexthoplist, | |
247 | show_ipv6_ospf6_nexthoplist_cmd, | |
248 | "show ipv6 ospf6 nexthop-list", | |
249 | SHOW_STR | |
250 | IP6_STR | |
251 | OSPF6_STR | |
252 | "List of nexthop\n") | |
253 | { | |
254 | #if 0 | |
255 | listnode i; | |
256 | struct ospf6_nexthop *nh; | |
257 | char buf[128]; | |
258 | for (i = listhead (nexthoplist); i; nextnode (i)) | |
259 | { | |
260 | nh = (struct ospf6_nexthop *) getdata (i); | |
261 | nexthop_str (nh, buf, sizeof (buf)); | |
262 | vty_out (vty, "%s%s", buf, | |
263 | VTY_NEWLINE); | |
264 | } | |
265 | #endif | |
266 | return CMD_SUCCESS; | |
267 | } | |
268 | ||
269 | DEFUN (show_ipv6_ospf6_statistics, | |
270 | show_ipv6_ospf6_statistics_cmd, | |
271 | "show ipv6 ospf6 statistics", | |
272 | SHOW_STR | |
273 | IP6_STR | |
274 | OSPF6_STR | |
275 | "Statistics\n") | |
276 | { | |
277 | OSPF6_CMD_CHECK_RUNNING (); | |
278 | ||
279 | ospf6_statistics_show (vty, ospf6); | |
280 | return CMD_SUCCESS; | |
281 | } | |
282 | ||
283 | /* change Router_ID commands. */ | |
a2c62831 | 284 | DEFUN (ospf6_router_id, |
285 | ospf6_router_id_cmd, | |
718e3744 | 286 | "router-id ROUTER_ID", |
287 | "Configure ospf Router-ID.\n" | |
288 | V4NOTATION_STR) | |
289 | { | |
290 | int ret; | |
291 | u_int32_t router_id; | |
292 | ||
293 | ret = inet_pton (AF_INET, argv[0], &router_id); | |
294 | if (!ret) | |
295 | { | |
296 | vty_out (vty, "malformed ospf router identifier%s", VTY_NEWLINE); | |
297 | vty_out (vty, "%s", VTY_NEWLINE); | |
298 | return CMD_WARNING; | |
299 | } | |
300 | ||
301 | if (IS_OSPF6_DUMP_CONFIG) | |
302 | zlog_info ("CONFIG: router-id %s", argv[0]); | |
303 | ospf6->router_id = router_id; | |
304 | ||
305 | return CMD_SUCCESS; | |
306 | } | |
307 | ||
308 | int | |
309 | ospf6_interface_bind_area (struct vty *vty, | |
310 | char *if_name, char *area_name, | |
311 | char *plist_name, int passive) | |
312 | { | |
313 | struct interface *ifp; | |
314 | struct ospf6_interface *o6i; | |
315 | struct ospf6_area *o6a; | |
316 | u_int32_t area_id; | |
317 | ||
318 | /* find/create ospf6 interface */ | |
319 | ifp = if_get_by_name (if_name); | |
320 | o6i = (struct ospf6_interface *) ifp->info; | |
321 | if (! o6i) | |
322 | o6i = ospf6_interface_create (ifp); | |
323 | ||
324 | /* parse Area-ID */ | |
325 | if (inet_pton (AF_INET, area_name, &area_id) != 1) | |
326 | { | |
327 | vty_out (vty, "Invalid Area-ID: %s%s", area_name, VTY_NEWLINE); | |
328 | return CMD_ERR_AMBIGUOUS; | |
329 | } | |
330 | ||
331 | /* find/create ospf6 area */ | |
332 | o6a = ospf6_area_lookup (area_id, ospf6); | |
333 | if (!o6a) | |
334 | { | |
335 | o6a = ospf6_area_create (area_id); | |
336 | o6a->ospf6 = ospf6; | |
337 | listnode_add (ospf6->area_list, o6a); | |
338 | } | |
339 | ||
340 | if (o6i->area) | |
341 | { | |
342 | if (o6i->area != o6a) | |
343 | { | |
344 | vty_out (vty, "Aready attached to area %s%s", | |
345 | o6i->area->str, VTY_NEWLINE); | |
346 | return CMD_ERR_NOTHING_TODO; | |
347 | } | |
348 | } | |
349 | else | |
350 | { | |
351 | listnode_add (o6a->if_list, o6i); | |
352 | o6i->area = o6a; | |
353 | } | |
354 | ||
355 | /* prefix-list name */ | |
356 | if (plist_name) | |
357 | { | |
358 | if (o6i->plist_name) | |
359 | XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name); | |
360 | o6i->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, plist_name); | |
361 | } | |
362 | else | |
363 | { | |
364 | if (o6i->plist_name) | |
365 | XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name); | |
366 | o6i->plist_name = NULL; | |
367 | } | |
368 | ||
369 | if (passive) | |
370 | { | |
371 | listnode node; | |
372 | struct ospf6_neighbor *o6n; | |
373 | ||
374 | SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); | |
375 | if (o6i->thread_send_hello) | |
376 | { | |
377 | thread_cancel (o6i->thread_send_hello); | |
378 | o6i->thread_send_hello = (struct thread *) NULL; | |
379 | } | |
380 | ||
381 | for (node = listhead (o6i->neighbor_list); node; nextnode (node)) | |
382 | { | |
383 | o6n = getdata (node); | |
384 | if (o6n->inactivity_timer) | |
385 | thread_cancel (o6n->inactivity_timer); | |
386 | thread_execute (master, inactivity_timer, o6n, 0); | |
387 | } | |
388 | } | |
389 | else | |
390 | { | |
391 | UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); | |
392 | if (o6i->thread_send_hello == NULL) | |
393 | thread_add_event (master, ospf6_send_hello, o6i, 0); | |
394 | } | |
395 | ||
396 | /* enable I/F if it's not enabled still */ | |
397 | if (! ospf6_interface_is_enabled (o6i->interface->ifindex)) | |
398 | thread_add_event (master, interface_up, o6i, 0); | |
399 | else | |
400 | CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i); | |
401 | ||
402 | CALL_CHANGE_HOOK (&interface_hook, o6i); | |
403 | return CMD_SUCCESS; | |
404 | } | |
405 | ||
a2c62831 | 406 | DEFUN (ospf6_interface_area_plist, |
407 | ospf6_interface_area_plist_cmd, | |
718e3744 | 408 | "interface IFNAME area A.B.C.D prefix-list WORD", |
409 | "Enable routing on an IPv6 interface\n" | |
410 | IFNAME_STR | |
411 | "Set the OSPF6 area ID\n" | |
412 | "OSPF6 area ID in IPv4 address notation\n" | |
413 | OSPF6_PREFIX_LIST_STR | |
414 | "IPv6 prefix-list name\n" | |
415 | ) | |
416 | { | |
417 | if (IS_OSPF6_DUMP_CONFIG) | |
418 | zlog_info ("CONFIG: interface %s area %s prefix-list %s", | |
419 | argv[0], argv[1], argv[2]); | |
420 | ||
421 | return ospf6_interface_bind_area (vty, argv[0], argv[1], argv[2], 0); | |
422 | } | |
423 | ||
a2c62831 | 424 | DEFUN (ospf6_interface_area_plist_passive, |
425 | ospf6_interface_area_plist_passive_cmd, | |
718e3744 | 426 | "interface IFNAME area A.B.C.D prefix-list WORD passive", |
427 | "Enable routing on an IPv6 interface\n" | |
428 | IFNAME_STR | |
429 | "Set the OSPF6 area ID\n" | |
430 | "OSPF6 area ID in IPv4 address notation\n" | |
431 | OSPF6_PREFIX_LIST_STR | |
432 | "IPv6 prefix-list name\n" | |
433 | "IPv6 prefix-list name\n" | |
434 | OSPF6_PASSIVE_STR | |
435 | ) | |
436 | { | |
437 | if (IS_OSPF6_DUMP_CONFIG) | |
438 | zlog_info ("CONFIG: interface %s area %s prefix-list %s passive", | |
439 | argv[0], argv[1], argv[2]); | |
440 | ||
441 | return ospf6_interface_bind_area (vty, argv[0], argv[1], argv[2], 1); | |
442 | } | |
443 | ||
a2c62831 | 444 | DEFUN (ospf6_interface_area, |
445 | ospf6_interface_area_cmd, | |
718e3744 | 446 | "interface IFNAME area A.B.C.D", |
447 | "Enable routing on an IPv6 interface\n" | |
448 | IFNAME_STR | |
449 | "Set the OSPF6 area ID\n" | |
450 | "OSPF6 area ID in IPv4 address notation\n" | |
451 | ) | |
452 | { | |
453 | struct interface *ifp; | |
454 | struct ospf6_interface *o6i; | |
455 | int passive; | |
456 | char *plist_name; | |
457 | ||
458 | if (IS_OSPF6_DUMP_CONFIG) | |
459 | zlog_info ("CONFIG: interface %s area %s", | |
460 | argv[0], argv[1]); | |
461 | ||
462 | ifp = if_get_by_name (argv[0]); | |
463 | o6i = (struct ospf6_interface *) ifp->info; | |
464 | if (o6i) | |
465 | { | |
466 | passive = CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); | |
467 | plist_name = o6i->plist_name; | |
468 | } | |
469 | else | |
470 | { | |
471 | passive = 0; | |
472 | plist_name = NULL; | |
473 | } | |
474 | ||
475 | return ospf6_interface_bind_area (vty, argv[0], argv[1], | |
476 | plist_name, passive); | |
477 | } | |
478 | ||
a2c62831 | 479 | DEFUN (ospf6_interface_area_passive, |
480 | ospf6_interface_area_passive_cmd, | |
718e3744 | 481 | "interface IFNAME area A.B.C.D passive", |
482 | "Enable routing on an IPv6 interface\n" | |
483 | IFNAME_STR | |
484 | "Set the OSPF6 area ID\n" | |
485 | "OSPF6 area ID in IPv4 address notation\n" | |
486 | OSPF6_PASSIVE_STR | |
487 | ) | |
488 | { | |
489 | if (IS_OSPF6_DUMP_CONFIG) | |
490 | zlog_info ("CONFIG: interface %s area %s passive", | |
491 | argv[0], argv[1]); | |
492 | ||
493 | return ospf6_interface_bind_area (vty, argv[0], argv[1], NULL, 1); | |
494 | } | |
495 | ||
a2c62831 | 496 | DEFUN (no_ospf6_interface_area, |
497 | no_ospf6_interface_area_cmd, | |
718e3744 | 498 | "no interface IFNAME area A.B.C.D", |
499 | NO_STR | |
500 | "Disable routing on an IPv6 interface\n" | |
501 | IFNAME_STR) | |
502 | { | |
503 | struct interface *ifp; | |
504 | struct ospf6_interface *o6i; | |
505 | struct ospf6 *o6; | |
506 | u_int32_t area_id; | |
507 | ||
508 | o6 = (struct ospf6 *) vty->index; | |
509 | ||
510 | ifp = if_lookup_by_name (argv[0]); | |
511 | if (!ifp) | |
512 | return CMD_ERR_NO_MATCH; | |
513 | ||
514 | o6i = (struct ospf6_interface *) ifp->info; | |
515 | if (!o6i) | |
516 | return CMD_SUCCESS; | |
517 | ||
518 | /* parse Area-ID */ | |
519 | if (inet_pton (AF_INET, argv[1], &area_id) != 1) | |
520 | { | |
521 | vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE); | |
522 | return CMD_ERR_AMBIGUOUS; | |
523 | } | |
524 | ||
525 | if (o6i->area->area_id != area_id) | |
526 | { | |
527 | vty_out (vty, "Wrong Area-ID: %s aready attached to area %s%s", | |
528 | o6i->interface->name, o6i->area->str, VTY_NEWLINE); | |
529 | return CMD_ERR_NOTHING_TODO; | |
530 | } | |
531 | ||
532 | if (o6i->area) | |
533 | thread_execute (master, interface_down, o6i, 0); | |
534 | ||
535 | listnode_delete (o6i->area->if_list, o6i); | |
536 | o6i->area = (struct ospf6_area *) NULL; | |
537 | ||
538 | return CMD_SUCCESS; | |
539 | } | |
540 | ||
a2c62831 | 541 | DEFUN (ospf6_area_range, |
542 | ospf6_area_range_cmd, | |
718e3744 | 543 | "area A.B.C.D range X:X::X:X/M", |
544 | "OSPFv3 area parameters\n" | |
545 | "OSPFv3 area ID in IPv4 address format\n" | |
546 | "Summarize routes matching address/mask (border routers only)\n" | |
547 | "IPv6 address range\n") | |
548 | { | |
549 | struct ospf6 *o6; | |
550 | struct ospf6_area *o6a; | |
551 | u_int32_t area_id; | |
552 | int ret; | |
553 | ||
554 | o6 = (struct ospf6 *) vty->index; | |
555 | inet_pton (AF_INET, argv[0], &area_id); | |
556 | o6a = ospf6_area_lookup (area_id, o6); | |
557 | if (! o6a) | |
558 | { | |
559 | vty_out (vty, "No such area%s", VTY_NEWLINE); | |
560 | return CMD_ERR_NO_MATCH; | |
561 | } | |
562 | ||
563 | ret = str2prefix_ipv6 (argv[1], &o6a->area_range); | |
564 | if (ret <= 0) | |
565 | { | |
566 | vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE); | |
567 | return CMD_WARNING; | |
568 | } | |
569 | ||
570 | return CMD_SUCCESS; | |
571 | } | |
572 | ||
a2c62831 | 573 | DEFUN (ospf6_passive_interface, |
574 | ospf6_passive_interface_cmd, | |
718e3744 | 575 | "passive-interface IFNAME", |
576 | OSPF6_PASSIVE_STR | |
577 | IFNAME_STR) | |
578 | { | |
579 | struct interface *ifp; | |
580 | struct ospf6_interface *o6i; | |
581 | ||
582 | ifp = if_get_by_name (argv[0]); | |
583 | if (ifp->info) | |
584 | o6i = (struct ospf6_interface *) ifp->info; | |
585 | else | |
586 | o6i = ospf6_interface_create (ifp); | |
587 | ||
588 | SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); | |
589 | ||
590 | if (o6i->thread_send_hello) | |
591 | { | |
592 | thread_cancel (o6i->thread_send_hello); | |
593 | o6i->thread_send_hello = (struct thread *) NULL; | |
594 | } | |
595 | ||
596 | return CMD_SUCCESS; | |
597 | } | |
598 | ||
a2c62831 | 599 | DEFUN (no_ospf6_passive_interface, |
600 | no_ospf6_passive_interface_cmd, | |
718e3744 | 601 | "no passive-interface IFNAME", |
602 | NO_STR | |
603 | OSPF6_PASSIVE_STR | |
604 | IFNAME_STR) | |
605 | { | |
606 | struct interface *ifp; | |
607 | struct ospf6_interface *o6i; | |
608 | ||
609 | ifp = if_lookup_by_name (argv[0]); | |
610 | if (! ifp) | |
611 | return CMD_ERR_NO_MATCH; | |
612 | ||
613 | o6i = (struct ospf6_interface *) ifp->info; | |
614 | UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); | |
615 | if (o6i->thread_send_hello == NULL) | |
616 | thread_add_event (master, ospf6_send_hello, o6i, 0); | |
617 | ||
618 | return CMD_SUCCESS; | |
619 | } | |
620 | ||
621 | #ifdef HAVE_SETPROCTITLE | |
622 | extern int _argc; | |
623 | extern char **_argv; | |
624 | ||
625 | DEFUN (set_proctitle, | |
626 | set_proctitle_cmd, | |
627 | "set proctitle (version|normal|none)", | |
628 | "Set command\n" | |
629 | "Process title\n" | |
630 | "Version information\n" | |
631 | "Normal command-line options\n" | |
632 | "Just program name\n") | |
633 | { | |
634 | int i; | |
635 | char buf[64], tmp[64]; | |
636 | ||
637 | if (strncmp (argv[0], "v", 1) == 0) | |
638 | { | |
639 | proctitle_mode = 1; | |
e8f2984c | 640 | setproctitle ("%s Zebra: %s", OSPF6_DAEMON_VERSION, QUAGGA_VERSION); |
718e3744 | 641 | } |
642 | else if (strncmp (argv[0], "nor", 3) == 0) | |
643 | { | |
644 | proctitle_mode = 0; | |
645 | memset (tmp, 0, sizeof (tmp)); | |
646 | memset (buf, 0, sizeof (buf)); | |
647 | for (i = 0; i < _argc; i++) | |
648 | { | |
649 | snprintf (buf, sizeof (buf), "%s%s ", tmp, _argv[i]); | |
650 | memcpy (&tmp, &buf, sizeof (tmp)); | |
651 | } | |
652 | setproctitle (buf); | |
653 | } | |
654 | else if (strncmp (argv[0], "non", 3) == 0) | |
655 | { | |
656 | proctitle_mode = -1; | |
657 | setproctitle (NULL); | |
658 | } | |
659 | else | |
660 | return CMD_ERR_NO_MATCH; | |
661 | ||
662 | return CMD_SUCCESS; | |
663 | } | |
664 | #endif /* HAVE_SETPROCTITLE */ | |
665 | ||
666 | /* OSPF configuration write function. */ | |
667 | int | |
668 | ospf6_config_write (struct vty *vty) | |
669 | { | |
670 | listnode j, k; | |
671 | char buf[64]; | |
672 | struct ospf6_area *area; | |
673 | struct ospf6_interface *o6i; | |
674 | ||
675 | if (proctitle_mode == 1) | |
676 | vty_out (vty, "set proctitle version%s", VTY_NEWLINE); | |
677 | else if (proctitle_mode == -1) | |
678 | vty_out (vty, "set proctitle none%s", VTY_NEWLINE); | |
679 | ||
680 | vty_out (vty, "!%s", VTY_NEWLINE); | |
681 | ||
682 | if (! ospf6) | |
683 | return 0; | |
684 | ||
685 | /* OSPFv6 configuration. */ | |
686 | if (!ospf6) | |
687 | return CMD_SUCCESS; | |
688 | ||
689 | inet_ntop (AF_INET, &ospf6->router_id, buf, sizeof (buf)); | |
690 | vty_out (vty, "router ospf6%s", VTY_NEWLINE); | |
691 | vty_out (vty, " router-id %s%s", buf, VTY_NEWLINE); | |
692 | ||
693 | ospf6_redistribute_config_write (vty); | |
694 | ospf6_damp_config_write (vty); | |
695 | ||
696 | for (j = listhead (ospf6->area_list); j; nextnode (j)) | |
697 | { | |
698 | area = (struct ospf6_area *)getdata (j); | |
699 | for (k = listhead (area->if_list); k; nextnode (k)) | |
700 | { | |
701 | o6i = (struct ospf6_interface *) getdata (k); | |
702 | vty_out (vty, " interface %s area %s%s", | |
703 | o6i->interface->name, area->str, VTY_NEWLINE); | |
704 | } | |
705 | } | |
706 | vty_out (vty, "!%s", VTY_NEWLINE); | |
707 | return 0; | |
708 | } | |
709 | ||
710 | /* OSPF6 node structure. */ | |
711 | struct cmd_node ospf6_node = | |
712 | { | |
713 | OSPF6_NODE, | |
714 | "%s(config-ospf6)# ", | |
733e8102 | 715 | vtysh: 1 |
718e3744 | 716 | }; |
717 | ||
718 | /* Install ospf related commands. */ | |
719 | void | |
720 | ospf6_init () | |
721 | { | |
722 | /* Install ospf6 top node. */ | |
723 | install_node (&ospf6_node, ospf6_config_write); | |
724 | ||
725 | install_element (VIEW_NODE, &show_ipv6_ospf6_cmd); | |
726 | install_element (VIEW_NODE, &show_version_ospf6_cmd); | |
727 | install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd); | |
728 | install_element (ENABLE_NODE, &show_version_ospf6_cmd); | |
729 | install_element (ENABLE_NODE, &reload_cmd); | |
730 | install_element (CONFIG_NODE, &router_ospf6_cmd); | |
731 | install_element (CONFIG_NODE, &interface_cmd); | |
32d2463c | 732 | install_element (CONFIG_NODE, &no_interface_cmd); |
718e3744 | 733 | #ifdef OSPF6_STATISTICS |
734 | install_element (VIEW_NODE, &show_ipv6_ospf6_statistics_cmd); | |
735 | install_element (ENABLE_NODE, &show_ipv6_ospf6_statistics_cmd); | |
736 | #endif /* OSPF6_STATISTICS */ | |
737 | #ifdef OSPF6_GARBAGE_COLLECT | |
738 | install_element (ENABLE_NODE, &garbage_collection_cmd); | |
739 | #endif /* OSPF6_GARBAGE_COLLECT */ | |
740 | #ifdef HAVE_SETPROCTITLE | |
741 | install_element (CONFIG_NODE, &set_proctitle_cmd); | |
742 | #endif /* HAVE_SETPROCTITLE */ | |
743 | ||
744 | install_default (OSPF6_NODE); | |
a2c62831 | 745 | install_element (OSPF6_NODE, &ospf6_router_id_cmd); |
746 | install_element (OSPF6_NODE, &ospf6_interface_area_cmd); | |
747 | install_element (OSPF6_NODE, &ospf6_interface_area_passive_cmd); | |
748 | install_element (OSPF6_NODE, &ospf6_interface_area_plist_cmd); | |
749 | install_element (OSPF6_NODE, &ospf6_interface_area_plist_passive_cmd); | |
750 | install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd); | |
751 | install_element (OSPF6_NODE, &ospf6_passive_interface_cmd); | |
752 | install_element (OSPF6_NODE, &no_ospf6_passive_interface_cmd); | |
753 | install_element (OSPF6_NODE, &ospf6_area_range_cmd); | |
718e3744 | 754 | |
755 | /* Make empty list of top list. */ | |
756 | if_init (); | |
757 | ||
758 | /* Install access list */ | |
759 | access_list_init (); | |
760 | ||
761 | /* Install prefix list */ | |
762 | prefix_list_init (); | |
763 | ||
764 | ospf6_dump_init (); | |
765 | ||
766 | #ifdef HAVE_OSPF6_DAMP | |
767 | ospf6_damp_init (); | |
768 | #endif /*HAVE_OSPF6_DAMP*/ | |
769 | ||
770 | ospf6_hook_init (); | |
771 | ospf6_lsa_init (); | |
772 | ||
773 | ospf6_top_init (); | |
774 | ospf6_area_init (); | |
775 | ospf6_interface_init (); | |
776 | ospf6_neighbor_init (); | |
777 | ospf6_zebra_init (); | |
778 | ||
779 | ospf6_routemap_init (); | |
780 | ospf6_lsdb_init (); | |
781 | ||
782 | ospf6_spf_init (); | |
783 | ||
784 | ospf6_intra_init (); | |
785 | ospf6_abr_init (); | |
786 | ospf6_asbr_init (); | |
787 | } | |
788 | ||
789 | void | |
790 | ospf6_terminate () | |
791 | { | |
792 | /* stop ospf6 */ | |
793 | ospf6_stop (); | |
794 | ||
795 | /* log */ | |
796 | zlog (NULL, LOG_INFO, "OSPF6d terminated"); | |
797 | } | |
798 | ||
799 | void | |
800 | ospf6_maxage_remover () | |
801 | { | |
802 | #if 0 | |
803 | if (IS_OSPF6_DUMP_LSDB) | |
804 | zlog_info ("MaxAge Remover"); | |
805 | #endif | |
806 | ||
807 | ospf6_top_schedule_maxage_remover (NULL, 0, ospf6); | |
808 | (*ospf6->foreach_area) (ospf6, NULL, 0, | |
809 | ospf6_area_schedule_maxage_remover); | |
810 | (*ospf6->foreach_if) (ospf6, NULL, 0, | |
811 | ospf6_interface_schedule_maxage_remover); | |
812 | } | |
813 | ||
814 | ||
815 | ||
816 | void * | |
817 | ospf6_lsa_get_scope (u_int16_t type, struct ospf6_interface *o6i) | |
818 | { | |
819 | if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (type))) | |
820 | return o6i; | |
821 | else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (type))) | |
822 | return o6i->area; | |
823 | else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (type))) | |
824 | return o6i->area->ospf6; | |
825 | else | |
826 | return NULL; | |
827 | } | |
828 |