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