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