]>
Commit | Line | Data |
---|---|---|
ca776988 | 1 | /* |
2 | * | |
43e52561 QY |
3 | * Copyright (C) 1997, 2000 |
4 | * Portions: | |
5 | * Swedish University of Agricultural Sciences | |
6 | * Robert Olsson | |
7 | * Kunihiro Ishiguro | |
8 | * | |
9 | * Thanks to Jens Laas at Swedish University of Agricultural Sciences | |
10 | * for reviewing and tests. | |
ca776988 | 11 | * |
12 | * This file is part of GNU Zebra. | |
13 | * | |
14 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
15 | * under the terms of the GNU General Public License as published by the | |
16 | * Free Software Foundation; either version 2, or (at your option) any | |
17 | * later version. | |
18 | * | |
19 | * GNU Zebra is distributed in the hope that it will be useful, but | |
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
22 | * General Public License for more details. | |
23 | * | |
896014f4 DL |
24 | * You should have received a copy of the GNU General Public License along |
25 | * with this program; see the file COPYING; if not, write to the Free Software | |
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
ca776988 | 27 | */ |
28 | ||
ca776988 | 29 | #include <zebra.h> |
30 | ||
ca776988 | 31 | #include "if.h" |
32 | #include "vty.h" | |
33 | #include "sockunion.h" | |
34 | #include "prefix.h" | |
35 | #include "command.h" | |
36 | #include "memory.h" | |
4a1ab8e4 | 37 | #include "zebra_memory.h" |
ca776988 | 38 | #include "stream.h" |
39 | #include "ioctl.h" | |
40 | #include "connected.h" | |
41 | #include "log.h" | |
42 | #include "zclient.h" | |
43 | #include "thread.h" | |
44 | #include "zebra/interface.h" | |
45 | #include "zebra/rtadv.h" | |
46 | #include "zebra/rib.h" | |
47 | #include "zebra/zserv.h" | |
48 | #include "zebra/redistribute.h" | |
49 | #include "zebra/irdp.h" | |
50 | #include <netinet/ip_icmp.h> | |
51 | #include "if.h" | |
52 | #include "sockunion.h" | |
53 | #include "log.h" | |
54 | ||
ca776988 | 55 | extern int irdp_sock; |
ca776988 | 56 | |
ead4ee99 DL |
57 | DEFINE_MTYPE_STATIC(ZEBRA, IRDP_IF, "IRDP interface data") |
58 | ||
996c9314 LB |
59 | #define IRDP_CONFIGED \ |
60 | do { \ | |
61 | if (!irdp) { \ | |
62 | vty_out(vty, \ | |
63 | "Please Configure IRDP before using this command\n"); \ | |
64 | return CMD_WARNING_CONFIG_FAILED; \ | |
65 | } \ | |
66 | } while (0) | |
e92044cd | 67 | |
ead4ee99 DL |
68 | static struct irdp_interface *irdp_if_get(struct interface *ifp) |
69 | { | |
70 | struct zebra_if *zi = ifp->info; | |
e92044cd DS |
71 | |
72 | if (!zi) | |
73 | return NULL; | |
74 | ||
ead4ee99 DL |
75 | if (!zi->irdp) |
76 | zi->irdp = XCALLOC(MTYPE_IRDP_IF, sizeof(*zi->irdp)); | |
e92044cd DS |
77 | |
78 | if (!zi->irdp->started) | |
79 | return NULL; | |
80 | ||
ead4ee99 DL |
81 | return zi->irdp; |
82 | } | |
83 | ||
84 | static int irdp_if_delete(struct interface *ifp) | |
85 | { | |
86 | struct zebra_if *zi = ifp->info; | |
87 | if (!zi) | |
88 | return 0; | |
89 | XFREE(MTYPE_IRDP_IF, zi->irdp); | |
90 | return 0; | |
91 | } | |
92 | ||
d7c0a89a | 93 | static const char *inet_2a(uint32_t a, char *b) |
ab0f6155 | 94 | { |
d62a17ae | 95 | sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF, |
96 | (a >> 24) & 0xFF); | |
97 | return b; | |
ab0f6155 | 98 | } |
ca776988 | 99 | |
ca776988 | 100 | |
d62a17ae | 101 | static struct prefix *irdp_get_prefix(struct interface *ifp) |
ca776988 | 102 | { |
d62a17ae | 103 | struct listnode *node; |
104 | struct connected *ifc; | |
e52702f2 | 105 | |
d62a17ae | 106 | if (ifp->connected) |
107 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) | |
108 | return ifc->address; | |
0c0f9112 | 109 | |
d62a17ae | 110 | return NULL; |
ca776988 | 111 | } |
112 | ||
113 | /* Join to the add/leave multicast group. */ | |
d7c0a89a | 114 | static int if_group(struct interface *ifp, int sock, uint32_t group, |
d62a17ae | 115 | int add_leave) |
ca776988 | 116 | { |
d62a17ae | 117 | struct ip_mreq m; |
118 | struct prefix *p; | |
119 | int ret; | |
120 | char b1[INET_ADDRSTRLEN]; | |
121 | ||
122 | memset(&m, 0, sizeof(m)); | |
123 | m.imr_multiaddr.s_addr = htonl(group); | |
124 | p = irdp_get_prefix(ifp); | |
125 | ||
126 | if (!p) { | |
127 | zlog_warn("IRDP: can't get address for %s", ifp->name); | |
128 | return 1; | |
129 | } | |
130 | ||
131 | m.imr_interface = p->u.prefix4; | |
132 | ||
133 | ret = setsockopt(sock, IPPROTO_IP, add_leave, (char *)&m, | |
134 | sizeof(struct ip_mreq)); | |
135 | if (ret < 0) | |
136 | zlog_warn("IRDP: %s can't setsockopt %s: %s", | |
137 | add_leave == IP_ADD_MEMBERSHIP ? "join group" | |
138 | : "leave group", | |
139 | inet_2a(group, b1), safe_strerror(errno)); | |
140 | ||
141 | return ret; | |
ca776988 | 142 | } |
143 | ||
d62a17ae | 144 | static int if_add_group(struct interface *ifp) |
ca776988 | 145 | { |
d62a17ae | 146 | struct zebra_if *zi = ifp->info; |
ead4ee99 | 147 | struct irdp_interface *irdp = zi->irdp; |
d62a17ae | 148 | int ret; |
149 | char b1[INET_ADDRSTRLEN]; | |
150 | ||
ead4ee99 DL |
151 | if (!irdp) |
152 | return -1; | |
153 | ||
d62a17ae | 154 | ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP); |
155 | if (ret < 0) { | |
156 | return ret; | |
157 | } | |
158 | ||
159 | if (irdp->flags & IF_DEBUG_MISC) | |
160 | zlog_debug("IRDP: Adding group %s for %s", | |
161 | inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name); | |
162 | return 0; | |
ca776988 | 163 | } |
2da40f49 | 164 | |
d62a17ae | 165 | static int if_drop_group(struct interface *ifp) |
ca776988 | 166 | { |
d62a17ae | 167 | struct zebra_if *zi = ifp->info; |
ead4ee99 | 168 | struct irdp_interface *irdp = zi->irdp; |
d62a17ae | 169 | int ret; |
170 | char b1[INET_ADDRSTRLEN]; | |
171 | ||
ead4ee99 DL |
172 | if (!irdp) |
173 | return -1; | |
174 | ||
d62a17ae | 175 | ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, |
176 | IP_DROP_MEMBERSHIP); | |
177 | if (ret < 0) | |
178 | return ret; | |
179 | ||
180 | if (irdp->flags & IF_DEBUG_MISC) | |
181 | zlog_debug("IRDP: Leaving group %s for %s", | |
182 | inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name); | |
183 | return 0; | |
ca776988 | 184 | } |
185 | ||
ead4ee99 | 186 | static void if_set_defaults(struct irdp_interface *irdp) |
ca776988 | 187 | { |
d62a17ae | 188 | irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL; |
189 | irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL; | |
190 | irdp->Preference = IRDP_PREFERENCE; | |
191 | irdp->Lifetime = IRDP_LIFETIME; | |
ca776988 | 192 | } |
193 | ||
194 | ||
d62a17ae | 195 | static struct Adv *Adv_new(void) |
ca776988 | 196 | { |
d62a17ae | 197 | return XCALLOC(MTYPE_TMP, sizeof(struct Adv)); |
ca776988 | 198 | } |
199 | ||
d62a17ae | 200 | static void Adv_free(struct Adv *adv) |
ca776988 | 201 | { |
d62a17ae | 202 | XFREE(MTYPE_TMP, adv); |
ca776988 | 203 | } |
204 | ||
d62a17ae | 205 | static void irdp_if_start(struct interface *ifp, int multicast, |
206 | int set_defaults) | |
ca776988 | 207 | { |
d62a17ae | 208 | struct zebra_if *zi = ifp->info; |
ead4ee99 | 209 | struct irdp_interface *irdp = zi->irdp; |
d62a17ae | 210 | struct listnode *node; |
211 | struct connected *ifc; | |
d7c0a89a | 212 | uint32_t timer, seed; |
ca776988 | 213 | |
ead4ee99 DL |
214 | assert(irdp); |
215 | ||
e92044cd | 216 | irdp->started = true; |
d62a17ae | 217 | if (irdp->flags & IF_ACTIVE) { |
218 | zlog_warn("IRDP: Interface is already active %s", ifp->name); | |
219 | return; | |
220 | } | |
221 | if ((irdp_sock < 0) && ((irdp_sock = irdp_sock_init()) < 0)) { | |
222 | zlog_warn( | |
223 | "IRDP: Cannot activate interface %s (cannot create " | |
224 | "IRDP socket)", | |
225 | ifp->name); | |
226 | return; | |
227 | } | |
228 | irdp->flags |= IF_ACTIVE; | |
ca776988 | 229 | |
d62a17ae | 230 | if (!multicast) |
231 | irdp->flags |= IF_BROADCAST; | |
ca776988 | 232 | |
d62a17ae | 233 | if_add_update(ifp); |
ca776988 | 234 | |
d62a17ae | 235 | if (!(ifp->flags & IFF_UP)) { |
236 | zlog_warn("IRDP: Interface is down %s", ifp->name); | |
237 | } | |
ca776988 | 238 | |
d62a17ae | 239 | /* Shall we cancel if_start if if_add_group fails? */ |
ca776988 | 240 | |
d62a17ae | 241 | if (multicast) { |
242 | if_add_group(ifp); | |
e52702f2 | 243 | |
d62a17ae | 244 | if (!(ifp->flags & (IFF_MULTICAST | IFF_ALLMULTI))) { |
245 | zlog_warn("IRDP: Interface not multicast enabled %s", | |
246 | ifp->name); | |
247 | } | |
248 | } | |
ca776988 | 249 | |
d62a17ae | 250 | if (set_defaults) |
ead4ee99 | 251 | if_set_defaults(irdp); |
ca776988 | 252 | |
d62a17ae | 253 | irdp->irdp_sent = 0; |
ca776988 | 254 | |
d62a17ae | 255 | /* The spec suggests this for randomness */ |
ca776988 | 256 | |
d62a17ae | 257 | seed = 0; |
258 | if (ifp->connected) | |
259 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { | |
260 | seed = ifc->address->u.prefix4.s_addr; | |
261 | break; | |
262 | } | |
e52702f2 | 263 | |
d62a17ae | 264 | srandom(seed); |
265 | timer = (random() % IRDP_DEFAULT_INTERVAL) + 1; | |
ca776988 | 266 | |
d62a17ae | 267 | irdp->AdvPrefList = list_new(); |
268 | irdp->AdvPrefList->del = (void (*)(void *))Adv_free; /* Destructor */ | |
ca776988 | 269 | |
270 | ||
d62a17ae | 271 | /* And this for startup. Speed limit from 1991 :-). But it's OK*/ |
ca776988 | 272 | |
d62a17ae | 273 | if (irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS |
274 | && timer > MAX_INITIAL_ADVERT_INTERVAL) | |
275 | timer = MAX_INITIAL_ADVERT_INTERVAL; | |
ca776988 | 276 | |
e52702f2 | 277 | |
d62a17ae | 278 | if (irdp->flags & IF_DEBUG_MISC) |
279 | zlog_debug("IRDP: Init timer for %s set to %u", ifp->name, | |
280 | timer); | |
ca776988 | 281 | |
d62a17ae | 282 | irdp->t_advertise = NULL; |
283 | thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, | |
284 | &irdp->t_advertise); | |
ca776988 | 285 | } |
286 | ||
d62a17ae | 287 | static void irdp_if_stop(struct interface *ifp) |
ca776988 | 288 | { |
d62a17ae | 289 | struct zebra_if *zi = ifp->info; |
ead4ee99 | 290 | struct irdp_interface *irdp = zi->irdp; |
e52702f2 | 291 | |
d62a17ae | 292 | if (irdp == NULL) { |
293 | zlog_warn("Interface %s structure is NULL", ifp->name); | |
294 | return; | |
295 | } | |
ca776988 | 296 | |
d62a17ae | 297 | if (!(irdp->flags & IF_ACTIVE)) { |
298 | zlog_warn("Interface is not active %s", ifp->name); | |
299 | return; | |
300 | } | |
ca776988 | 301 | |
d62a17ae | 302 | if (!(irdp->flags & IF_BROADCAST)) |
303 | if_drop_group(ifp); | |
ca776988 | 304 | |
d62a17ae | 305 | irdp_advert_off(ifp); |
ca776988 | 306 | |
affe9e99 | 307 | list_delete_and_null(&irdp->AdvPrefList); |
ca776988 | 308 | |
d62a17ae | 309 | irdp->flags = 0; |
ca776988 | 310 | } |
311 | ||
312 | ||
d62a17ae | 313 | static void irdp_if_shutdown(struct interface *ifp) |
ca776988 | 314 | { |
d62a17ae | 315 | struct zebra_if *zi = ifp->info; |
ead4ee99 | 316 | struct irdp_interface *irdp = zi->irdp; |
ca776988 | 317 | |
ead4ee99 DL |
318 | if (!irdp) |
319 | return; | |
e92044cd | 320 | |
d62a17ae | 321 | if (irdp->flags & IF_SHUTDOWN) { |
322 | zlog_warn("IRDP: Interface is already shutdown %s", ifp->name); | |
323 | return; | |
324 | } | |
ca776988 | 325 | |
d62a17ae | 326 | irdp->flags |= IF_SHUTDOWN; |
327 | irdp->flags &= ~IF_ACTIVE; | |
ca776988 | 328 | |
d62a17ae | 329 | if (!(irdp->flags & IF_BROADCAST)) |
330 | if_drop_group(ifp); | |
e52702f2 | 331 | |
d62a17ae | 332 | /* Tell the hosts we are out of service */ |
333 | irdp_advert_off(ifp); | |
ca776988 | 334 | } |
335 | ||
d62a17ae | 336 | static void irdp_if_no_shutdown(struct interface *ifp) |
ca776988 | 337 | { |
ead4ee99 | 338 | struct irdp_interface *irdp = irdp_if_get(ifp); |
ca776988 | 339 | |
e92044cd DS |
340 | if (!irdp) |
341 | return; | |
342 | ||
d62a17ae | 343 | if (!(irdp->flags & IF_SHUTDOWN)) { |
344 | zlog_warn("IRDP: Interface is not shutdown %s", ifp->name); | |
345 | return; | |
346 | } | |
ca776988 | 347 | |
d62a17ae | 348 | irdp->flags &= ~IF_SHUTDOWN; |
ca776988 | 349 | |
d62a17ae | 350 | irdp_if_start(ifp, irdp->flags & IF_BROADCAST ? FALSE : TRUE, FALSE); |
ca776988 | 351 | } |
352 | ||
353 | ||
354 | /* Write configuration to user */ | |
355 | ||
2eb27eec | 356 | int irdp_config_write(struct vty *vty, struct interface *ifp) |
ca776988 | 357 | { |
d62a17ae | 358 | struct zebra_if *zi = ifp->info; |
ead4ee99 | 359 | struct irdp_interface *irdp = zi->irdp; |
d62a17ae | 360 | struct Adv *adv; |
361 | struct listnode *node; | |
362 | char b1[INET_ADDRSTRLEN]; | |
ca776988 | 363 | |
ead4ee99 DL |
364 | if (!irdp) |
365 | return 0; | |
366 | ||
d62a17ae | 367 | if (irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) { |
ca776988 | 368 | |
d62a17ae | 369 | if (irdp->flags & IF_SHUTDOWN) |
370 | vty_out(vty, " ip irdp shutdown \n"); | |
ca776988 | 371 | |
d62a17ae | 372 | if (irdp->flags & IF_BROADCAST) |
373 | vty_out(vty, " ip irdp broadcast\n"); | |
374 | else | |
375 | vty_out(vty, " ip irdp multicast\n"); | |
ca776988 | 376 | |
d62a17ae | 377 | vty_out(vty, " ip irdp preference %ld\n", irdp->Preference); |
ca776988 | 378 | |
d62a17ae | 379 | for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) |
380 | vty_out(vty, " ip irdp address %s preference %d\n", | |
381 | inet_2a(adv->ip.s_addr, b1), adv->pref); | |
ca776988 | 382 | |
d62a17ae | 383 | vty_out(vty, " ip irdp holdtime %d\n", irdp->Lifetime); |
ca776988 | 384 | |
d62a17ae | 385 | vty_out(vty, " ip irdp minadvertinterval %ld\n", |
386 | irdp->MinAdvertInterval); | |
ca776988 | 387 | |
d62a17ae | 388 | vty_out(vty, " ip irdp maxadvertinterval %ld\n", |
389 | irdp->MaxAdvertInterval); | |
390 | } | |
2eb27eec | 391 | return 0; |
ca776988 | 392 | } |
393 | ||
394 | ||
395 | DEFUN (ip_irdp_multicast, | |
396 | ip_irdp_multicast_cmd, | |
397 | "ip irdp multicast", | |
398 | IP_STR | |
3a2d747c QY |
399 | "ICMP Router discovery on this interface\n" |
400 | "Use multicast mode\n") | |
ca776988 | 401 | { |
d62a17ae | 402 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ead4ee99 | 403 | irdp_if_get(ifp); |
ca776988 | 404 | |
d62a17ae | 405 | irdp_if_start(ifp, TRUE, TRUE); |
406 | return CMD_SUCCESS; | |
ca776988 | 407 | } |
408 | ||
409 | DEFUN (ip_irdp_broadcast, | |
410 | ip_irdp_broadcast_cmd, | |
411 | "ip irdp broadcast", | |
412 | IP_STR | |
3a2d747c QY |
413 | "ICMP Router discovery on this interface\n" |
414 | "Use broadcast mode\n") | |
ca776988 | 415 | { |
d62a17ae | 416 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ead4ee99 | 417 | irdp_if_get(ifp); |
ca776988 | 418 | |
d62a17ae | 419 | irdp_if_start(ifp, FALSE, TRUE); |
420 | return CMD_SUCCESS; | |
ca776988 | 421 | } |
422 | ||
996933fd | 423 | DEFUN (no_ip_irdp, |
424 | no_ip_irdp_cmd, | |
ca776988 | 425 | "no ip irdp", |
8d0f15fd | 426 | NO_STR |
ca776988 | 427 | IP_STR |
428 | "Disable ICMP Router discovery on this interface\n") | |
429 | { | |
d62a17ae | 430 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ca776988 | 431 | |
d62a17ae | 432 | irdp_if_stop(ifp); |
433 | return CMD_SUCCESS; | |
ca776988 | 434 | } |
435 | ||
436 | DEFUN (ip_irdp_shutdown, | |
437 | ip_irdp_shutdown_cmd, | |
438 | "ip irdp shutdown", | |
439 | IP_STR | |
d7fa34c1 | 440 | "ICMP Router discovery on this interface\n" |
ca776988 | 441 | "ICMP Router discovery shutdown on this interface\n") |
442 | { | |
d62a17ae | 443 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ca776988 | 444 | |
d62a17ae | 445 | irdp_if_shutdown(ifp); |
446 | return CMD_SUCCESS; | |
ca776988 | 447 | } |
448 | ||
996933fd | 449 | DEFUN (no_ip_irdp_shutdown, |
450 | no_ip_irdp_shutdown_cmd, | |
ca776988 | 451 | "no ip irdp shutdown", |
8d0f15fd | 452 | NO_STR |
ca776988 | 453 | IP_STR |
d7fa34c1 | 454 | "ICMP Router discovery on this interface\n" |
ca776988 | 455 | "ICMP Router discovery no shutdown on this interface\n") |
456 | { | |
d62a17ae | 457 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ca776988 | 458 | |
d62a17ae | 459 | irdp_if_no_shutdown(ifp); |
460 | return CMD_SUCCESS; | |
ca776988 | 461 | } |
462 | ||
463 | DEFUN (ip_irdp_holdtime, | |
464 | ip_irdp_holdtime_cmd, | |
6147e2c6 | 465 | "ip irdp holdtime (0-9000)", |
ca776988 | 466 | IP_STR |
467 | "ICMP Router discovery on this interface\n" | |
468 | "Set holdtime value\n" | |
469 | "Holdtime value in seconds. Default is 1800 seconds\n") | |
470 | { | |
d62a17ae | 471 | int idx_number = 3; |
472 | VTY_DECLVAR_CONTEXT(interface, ifp); | |
ead4ee99 | 473 | struct irdp_interface *irdp = irdp_if_get(ifp); |
ca776988 | 474 | |
e92044cd DS |
475 | IRDP_CONFIGED; |
476 | ||
d62a17ae | 477 | irdp->Lifetime = atoi(argv[idx_number]->arg); |
478 | return CMD_SUCCESS; | |
ca776988 | 479 | } |
480 | ||
481 | DEFUN (ip_irdp_minadvertinterval, | |
482 | ip_irdp_minadvertinterval_cmd, | |
6147e2c6 | 483 | "ip irdp minadvertinterval (3-1800)", |
ca776988 | 484 | IP_STR |
485 | "ICMP Router discovery on this interface\n" | |
486 | "Set minimum time between advertisement\n" | |
487 | "Minimum advertisement interval in seconds\n") | |
488 | { | |
d62a17ae | 489 | int idx_number = 3; |
490 | VTY_DECLVAR_CONTEXT(interface, ifp); | |
ead4ee99 | 491 | struct irdp_interface *irdp = irdp_if_get(ifp); |
d62a17ae | 492 | |
e92044cd DS |
493 | IRDP_CONFIGED; |
494 | ||
d62a17ae | 495 | if ((unsigned)atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) { |
496 | irdp->MinAdvertInterval = atoi(argv[idx_number]->arg); | |
497 | return CMD_SUCCESS; | |
498 | } else { | |
499 | vty_out(vty, | |
500 | "%% MinAdvertInterval must be less than or equal to " | |
501 | "MaxAdvertInterval\n"); | |
502 | return CMD_WARNING_CONFIG_FAILED; | |
503 | } | |
ca776988 | 504 | } |
505 | ||
506 | DEFUN (ip_irdp_maxadvertinterval, | |
507 | ip_irdp_maxadvertinterval_cmd, | |
6147e2c6 | 508 | "ip irdp maxadvertinterval (4-1800)", |
ca776988 | 509 | IP_STR |
510 | "ICMP Router discovery on this interface\n" | |
511 | "Set maximum time between advertisement\n" | |
512 | "Maximum advertisement interval in seconds\n") | |
513 | { | |
d62a17ae | 514 | int idx_number = 3; |
515 | VTY_DECLVAR_CONTEXT(interface, ifp); | |
ead4ee99 | 516 | struct irdp_interface *irdp = irdp_if_get(ifp); |
d62a17ae | 517 | |
e92044cd DS |
518 | IRDP_CONFIGED; |
519 | ||
d62a17ae | 520 | if (irdp->MinAdvertInterval <= (unsigned)atoi(argv[idx_number]->arg)) { |
521 | irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg); | |
522 | return CMD_SUCCESS; | |
523 | } else { | |
524 | vty_out(vty, | |
525 | "%% MaxAdvertInterval must be greater than or equal to " | |
526 | "MinAdvertInterval\n"); | |
527 | return CMD_WARNING_CONFIG_FAILED; | |
528 | } | |
ca776988 | 529 | } |
530 | ||
accb156b | 531 | /* DEFUN needs to be fixed for negative ranages... |
532 | * "ip irdp preference <-2147483648-2147483647>", | |
533 | * Be positive for now. :-) | |
534 | */ | |
535 | ||
ca776988 | 536 | DEFUN (ip_irdp_preference, |
537 | ip_irdp_preference_cmd, | |
6147e2c6 | 538 | "ip irdp preference (0-2147483647)", |
ca776988 | 539 | IP_STR |
540 | "ICMP Router discovery on this interface\n" | |
541 | "Set default preference level for this interface\n" | |
542 | "Preference level\n") | |
543 | { | |
d62a17ae | 544 | int idx_number = 3; |
545 | VTY_DECLVAR_CONTEXT(interface, ifp); | |
ead4ee99 | 546 | struct irdp_interface *irdp = irdp_if_get(ifp); |
ca776988 | 547 | |
e92044cd DS |
548 | IRDP_CONFIGED; |
549 | ||
d62a17ae | 550 | irdp->Preference = atoi(argv[idx_number]->arg); |
551 | return CMD_SUCCESS; | |
ca776988 | 552 | } |
553 | ||
554 | DEFUN (ip_irdp_address_preference, | |
555 | ip_irdp_address_preference_cmd, | |
6147e2c6 | 556 | "ip irdp address A.B.C.D preference (0-2147483647)", |
ca776988 | 557 | IP_STR |
3a2d747c | 558 | "Alter ICMP Router discovery preference on this interface\n" |
ca776988 | 559 | "Set IRDP address for advertise\n" |
3a2d747c QY |
560 | "IPv4 address\n" |
561 | "Specify IRDP non-default preference to advertise\n" | |
ca776988 | 562 | "Preference level\n") |
563 | { | |
d62a17ae | 564 | int idx_ipv4 = 3; |
565 | int idx_number = 5; | |
566 | VTY_DECLVAR_CONTEXT(interface, ifp); | |
ead4ee99 | 567 | struct irdp_interface *irdp = irdp_if_get(ifp); |
d62a17ae | 568 | struct listnode *node; |
569 | struct in_addr ip; | |
570 | int pref; | |
571 | int ret; | |
d62a17ae | 572 | struct Adv *adv; |
573 | ||
e92044cd DS |
574 | IRDP_CONFIGED; |
575 | ||
d62a17ae | 576 | ret = inet_aton(argv[idx_ipv4]->arg, &ip); |
577 | if (!ret) | |
578 | return CMD_WARNING_CONFIG_FAILED; | |
579 | ||
580 | pref = atoi(argv[idx_number]->arg); | |
581 | ||
582 | for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) | |
583 | if (adv->ip.s_addr == ip.s_addr) | |
584 | return CMD_SUCCESS; | |
585 | ||
586 | adv = Adv_new(); | |
587 | adv->ip = ip; | |
588 | adv->pref = pref; | |
589 | listnode_add(irdp->AdvPrefList, adv); | |
590 | ||
591 | return CMD_SUCCESS; | |
ca776988 | 592 | } |
593 | ||
996933fd | 594 | DEFUN (no_ip_irdp_address_preference, |
595 | no_ip_irdp_address_preference_cmd, | |
6147e2c6 | 596 | "no ip irdp address A.B.C.D preference (0-2147483647)", |
8d0f15fd | 597 | NO_STR |
ca776988 | 598 | IP_STR |
3a2d747c | 599 | "Alter ICMP Router discovery preference on this interface\n" |
ca776988 | 600 | "Select IRDP address\n" |
3a2d747c QY |
601 | "IPv4 address\n" |
602 | "Reset ICMP Router discovery preference on this interface\n" | |
ca776988 | 603 | "Old preference level\n") |
604 | { | |
d62a17ae | 605 | int idx_ipv4 = 4; |
606 | VTY_DECLVAR_CONTEXT(interface, ifp); | |
ead4ee99 | 607 | struct irdp_interface *irdp = irdp_if_get(ifp); |
d62a17ae | 608 | struct listnode *node, *nnode; |
609 | struct in_addr ip; | |
610 | int ret; | |
d62a17ae | 611 | struct Adv *adv; |
612 | ||
e92044cd DS |
613 | IRDP_CONFIGED; |
614 | ||
d62a17ae | 615 | ret = inet_aton(argv[idx_ipv4]->arg, &ip); |
616 | if (!ret) | |
617 | return CMD_WARNING_CONFIG_FAILED; | |
618 | ||
619 | for (ALL_LIST_ELEMENTS(irdp->AdvPrefList, node, nnode, adv)) { | |
620 | if (adv->ip.s_addr == ip.s_addr) { | |
621 | listnode_delete(irdp->AdvPrefList, adv); | |
622 | break; | |
623 | } | |
624 | } | |
625 | ||
626 | return CMD_SUCCESS; | |
ca776988 | 627 | } |
628 | ||
629 | DEFUN (ip_irdp_debug_messages, | |
630 | ip_irdp_debug_messages_cmd, | |
631 | "ip irdp debug messages", | |
632 | IP_STR | |
3a2d747c QY |
633 | "ICMP Router discovery debug Averts. and Solicits (short)\n" |
634 | "IRDP debugging options\n" | |
635 | "Enable debugging for IRDP messages\n") | |
ca776988 | 636 | { |
d62a17ae | 637 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ead4ee99 | 638 | struct irdp_interface *irdp = irdp_if_get(ifp); |
ca776988 | 639 | |
e92044cd DS |
640 | IRDP_CONFIGED; |
641 | ||
d62a17ae | 642 | irdp->flags |= IF_DEBUG_MESSAGES; |
ca776988 | 643 | |
d62a17ae | 644 | return CMD_SUCCESS; |
ca776988 | 645 | } |
646 | ||
647 | DEFUN (ip_irdp_debug_misc, | |
648 | ip_irdp_debug_misc_cmd, | |
649 | "ip irdp debug misc", | |
650 | IP_STR | |
3a2d747c QY |
651 | "ICMP Router discovery debug Averts. and Solicits (short)\n" |
652 | "IRDP debugging options\n" | |
653 | "Enable debugging for miscellaneous IRDP events\n") | |
ca776988 | 654 | { |
d62a17ae | 655 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ead4ee99 | 656 | struct irdp_interface *irdp = irdp_if_get(ifp); |
ca776988 | 657 | |
e92044cd DS |
658 | IRDP_CONFIGED; |
659 | ||
d62a17ae | 660 | irdp->flags |= IF_DEBUG_MISC; |
ca776988 | 661 | |
d62a17ae | 662 | return CMD_SUCCESS; |
ca776988 | 663 | } |
664 | ||
665 | DEFUN (ip_irdp_debug_packet, | |
666 | ip_irdp_debug_packet_cmd, | |
667 | "ip irdp debug packet", | |
668 | IP_STR | |
3a2d747c QY |
669 | "ICMP Router discovery debug Averts. and Solicits (short)\n" |
670 | "IRDP debugging options\n" | |
671 | "Enable debugging for IRDP packets\n") | |
ca776988 | 672 | { |
d62a17ae | 673 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ead4ee99 | 674 | struct irdp_interface *irdp = irdp_if_get(ifp); |
ca776988 | 675 | |
e92044cd DS |
676 | IRDP_CONFIGED; |
677 | ||
d62a17ae | 678 | irdp->flags |= IF_DEBUG_PACKET; |
ca776988 | 679 | |
d62a17ae | 680 | return CMD_SUCCESS; |
ca776988 | 681 | } |
682 | ||
683 | ||
684 | DEFUN (ip_irdp_debug_disable, | |
685 | ip_irdp_debug_disable_cmd, | |
686 | "ip irdp debug disable", | |
687 | IP_STR | |
3a2d747c QY |
688 | "ICMP Router discovery debug Averts. and Solicits (short)\n" |
689 | "IRDP debugging options\n" | |
690 | "Disable debugging for all IRDP events\n") | |
ca776988 | 691 | { |
d62a17ae | 692 | VTY_DECLVAR_CONTEXT(interface, ifp); |
ead4ee99 | 693 | struct irdp_interface *irdp = irdp_if_get(ifp); |
ca776988 | 694 | |
e92044cd DS |
695 | IRDP_CONFIGED; |
696 | ||
d62a17ae | 697 | irdp->flags &= ~IF_DEBUG_PACKET; |
698 | irdp->flags &= ~IF_DEBUG_MESSAGES; | |
699 | irdp->flags &= ~IF_DEBUG_MISC; | |
ca776988 | 700 | |
d62a17ae | 701 | return CMD_SUCCESS; |
ca776988 | 702 | } |
703 | ||
2eb27eec | 704 | void irdp_if_init() |
ca776988 | 705 | { |
2eb27eec | 706 | hook_register(zebra_if_config_wr, irdp_config_write); |
ead4ee99 | 707 | hook_register(if_del, irdp_if_delete); |
2eb27eec | 708 | |
d62a17ae | 709 | install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd); |
710 | install_element(INTERFACE_NODE, &ip_irdp_multicast_cmd); | |
711 | install_element(INTERFACE_NODE, &no_ip_irdp_cmd); | |
712 | install_element(INTERFACE_NODE, &ip_irdp_shutdown_cmd); | |
713 | install_element(INTERFACE_NODE, &no_ip_irdp_shutdown_cmd); | |
714 | install_element(INTERFACE_NODE, &ip_irdp_holdtime_cmd); | |
715 | install_element(INTERFACE_NODE, &ip_irdp_maxadvertinterval_cmd); | |
716 | install_element(INTERFACE_NODE, &ip_irdp_minadvertinterval_cmd); | |
717 | install_element(INTERFACE_NODE, &ip_irdp_preference_cmd); | |
718 | install_element(INTERFACE_NODE, &ip_irdp_address_preference_cmd); | |
719 | install_element(INTERFACE_NODE, &no_ip_irdp_address_preference_cmd); | |
720 | ||
721 | install_element(INTERFACE_NODE, &ip_irdp_debug_messages_cmd); | |
722 | install_element(INTERFACE_NODE, &ip_irdp_debug_misc_cmd); | |
723 | install_element(INTERFACE_NODE, &ip_irdp_debug_packet_cmd); | |
724 | install_element(INTERFACE_NODE, &ip_irdp_debug_disable_cmd); | |
ca776988 | 725 | } |