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