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