]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* Interface related function for RIP. |
2 | * Copyright (C) 1997, 98 Kunihiro Ishiguro <kunihiro@zebra.org> | |
3 | * | |
4 | * This file is part of GNU Zebra. | |
5 | * | |
6 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2, or (at your option) any | |
9 | * later version. | |
10 | * | |
11 | * GNU Zebra is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | * 02111-1307, USA. | |
20 | */ | |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "command.h" | |
25 | #include "if.h" | |
26 | #include "sockunion.h" | |
27 | #include "prefix.h" | |
28 | #include "memory.h" | |
29 | #include "network.h" | |
30 | #include "table.h" | |
31 | #include "log.h" | |
32 | #include "stream.h" | |
33 | #include "thread.h" | |
34 | #include "zclient.h" | |
35 | #include "filter.h" | |
36 | #include "sockopt.h" | |
edd7c245 | 37 | #include "privs.h" |
718e3744 | 38 | |
39 | #include "zebra/connected.h" | |
40 | ||
41 | #include "ripd/ripd.h" | |
42 | #include "ripd/rip_debug.h" | |
43 | ||
44 | void rip_enable_apply (struct interface *); | |
45 | void rip_passive_interface_apply (struct interface *); | |
46 | int rip_if_down(struct interface *ifp); | |
16705130 | 47 | int rip_enable_if_lookup (char *ifname); |
48 | int rip_enable_network_lookup2 (struct connected *connected); | |
49 | void rip_enable_apply_all (); | |
50 | ||
718e3744 | 51 | |
52 | struct message ri_version_msg[] = | |
53 | { | |
54 | {RI_RIP_VERSION_1, "1"}, | |
55 | {RI_RIP_VERSION_2, "2"}, | |
56 | {RI_RIP_VERSION_1_AND_2, "1 2"}, | |
57 | {0, NULL} | |
58 | }; | |
59 | ||
edd7c245 | 60 | extern struct zebra_privs_t ripd_privs; |
61 | ||
718e3744 | 62 | /* RIP enabled network vector. */ |
63 | vector rip_enable_interface; | |
64 | ||
65 | /* RIP enabled interface table. */ | |
66 | struct route_table *rip_enable_network; | |
67 | ||
68 | /* Vector to store passive-interface name. */ | |
4aaff3f8 | 69 | static int passive_default; /* are we in passive-interface default mode? */ |
70 | vector Vrip_passive_nondefault; | |
718e3744 | 71 | \f |
72 | /* Join to the RIP version 2 multicast group. */ | |
73 | int | |
74 | ipv4_multicast_join (int sock, | |
75 | struct in_addr group, | |
76 | struct in_addr ifa, | |
77 | unsigned int ifindex) | |
78 | { | |
79 | int ret; | |
80 | ||
81 | ret = setsockopt_multicast_ipv4 (sock, | |
82 | IP_ADD_MEMBERSHIP, | |
83 | ifa, | |
84 | group.s_addr, | |
85 | ifindex); | |
86 | ||
87 | if (ret < 0) | |
88 | zlog (NULL, LOG_INFO, "can't setsockopt IP_ADD_MEMBERSHIP %s", | |
89 | strerror (errno)); | |
90 | ||
91 | return ret; | |
92 | } | |
93 | ||
94 | /* Leave from the RIP version 2 multicast group. */ | |
95 | int | |
96 | ipv4_multicast_leave (int sock, | |
97 | struct in_addr group, | |
98 | struct in_addr ifa, | |
99 | unsigned int ifindex) | |
100 | { | |
101 | int ret; | |
102 | ||
103 | ret = setsockopt_multicast_ipv4 (sock, | |
104 | IP_DROP_MEMBERSHIP, | |
105 | ifa, | |
106 | group.s_addr, | |
107 | ifindex); | |
108 | ||
109 | if (ret < 0) | |
110 | zlog (NULL, LOG_INFO, "can't setsockopt IP_DROP_MEMBERSHIP"); | |
111 | ||
112 | return ret; | |
113 | } | |
114 | \f | |
115 | /* Allocate new RIP's interface configuration. */ | |
116 | struct rip_interface * | |
117 | rip_interface_new () | |
118 | { | |
119 | struct rip_interface *ri; | |
120 | ||
121 | ri = XMALLOC (MTYPE_RIP_INTERFACE, sizeof (struct rip_interface)); | |
122 | memset (ri, 0, sizeof (struct rip_interface)); | |
123 | ||
124 | /* Default authentication type is simple password for Cisco | |
125 | compatibility. */ | |
126 | /* ri->auth_type = RIP_NO_AUTH; */ | |
127 | ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD; | |
ca5e516c | 128 | ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; |
718e3744 | 129 | |
130 | /* Set default split-horizon behavior. If the interface is Frame | |
131 | Relay or SMDS is enabled, the default value for split-horizon is | |
132 | off. But currently Zebra does detect Frame Relay or SMDS | |
133 | interface. So all interface is set to split horizon. */ | |
16705130 | 134 | ri->split_horizon_default = RIP_SPLIT_HORIZON; |
718e3744 | 135 | ri->split_horizon = ri->split_horizon_default; |
136 | ||
137 | return ri; | |
138 | } | |
139 | ||
140 | void | |
1a51786a | 141 | rip_interface_multicast_set (int sock, struct connected *connected) |
718e3744 | 142 | { |
143 | int ret; | |
718e3744 | 144 | struct servent *sp; |
145 | struct sockaddr_in from; | |
718e3744 | 146 | struct in_addr addr; |
cc1131ab | 147 | struct prefix_ipv4 *p; |
718e3744 | 148 | |
931cd54d | 149 | if (connected != NULL) |
150 | { | |
1a51786a | 151 | if (if_is_pointopoint(connected->ifp)) |
cc1131ab | 152 | p = (struct prefix_ipv4 *) connected->destination; |
153 | else | |
718e3744 | 154 | p = (struct prefix_ipv4 *) connected->address; |
718e3744 | 155 | addr = p->prefix; |
931cd54d | 156 | } |
157 | else | |
158 | { | |
159 | addr.s_addr = INADDR_ANY; | |
160 | } | |
718e3744 | 161 | |
1a51786a | 162 | if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0, |
163 | connected->ifp->ifindex) < 0) | |
718e3744 | 164 | { |
1a51786a | 165 | zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d, ifindex %d", |
166 | sock, connected->ifp->ifindex); | |
718e3744 | 167 | return; |
168 | } | |
169 | ||
170 | /* Bind myself. */ | |
171 | memset (&from, 0, sizeof (struct sockaddr_in)); | |
172 | ||
173 | /* Set RIP port. */ | |
174 | sp = getservbyname ("router", "udp"); | |
175 | if (sp) | |
176 | from.sin_port = sp->s_port; | |
177 | else | |
178 | from.sin_port = htons (RIP_PORT_DEFAULT); | |
179 | ||
931cd54d | 180 | /* Address should be any address. */ |
718e3744 | 181 | from.sin_family = AF_INET; |
931cd54d | 182 | if (connected) |
cc1131ab | 183 | addr = ((struct prefix_ipv4 *) connected->address)->prefix; |
718e3744 | 184 | from.sin_addr = addr; |
185 | #ifdef HAVE_SIN_LEN | |
186 | from.sin_len = sizeof (struct sockaddr_in); | |
187 | #endif /* HAVE_SIN_LEN */ | |
188 | ||
edd7c245 | 189 | if (ripd_privs.change (ZPRIVS_RAISE)) |
190 | zlog_err ("rip_interface_multicast_set: could not raise privs"); | |
191 | ||
cc1131ab | 192 | ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in)); |
718e3744 | 193 | if (ret < 0) |
194 | { | |
195 | zlog_warn ("Can't bind socket: %s", strerror (errno)); | |
718e3744 | 196 | } |
197 | ||
edd7c245 | 198 | if (ripd_privs.change (ZPRIVS_LOWER)) |
199 | zlog_err ("rip_interface_multicast_set: could not lower privs"); | |
200 | ||
718e3744 | 201 | return; |
202 | ||
203 | } | |
718e3744 | 204 | |
205 | /* Send RIP request packet to specified interface. */ | |
206 | void | |
207 | rip_request_interface_send (struct interface *ifp, u_char version) | |
208 | { | |
209 | struct sockaddr_in to; | |
210 | ||
211 | /* RIPv2 support multicast. */ | |
212 | if (version == RIPv2 && if_is_multicast (ifp)) | |
213 | { | |
214 | ||
215 | if (IS_RIP_DEBUG_EVENT) | |
216 | zlog_info ("multicast request on %s", ifp->name); | |
217 | ||
931cd54d | 218 | rip_request_send (NULL, ifp, version, NULL); |
718e3744 | 219 | return; |
220 | } | |
221 | ||
222 | /* RIPv1 and non multicast interface. */ | |
223 | if (if_is_pointopoint (ifp) || if_is_broadcast (ifp)) | |
224 | { | |
225 | listnode cnode; | |
226 | ||
227 | if (IS_RIP_DEBUG_EVENT) | |
228 | zlog_info ("broadcast request to %s", ifp->name); | |
229 | ||
230 | for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) | |
231 | { | |
232 | struct prefix_ipv4 *p; | |
233 | struct connected *connected; | |
234 | ||
235 | connected = getdata (cnode); | |
236 | p = (struct prefix_ipv4 *) connected->destination; | |
237 | ||
238 | if (p->family == AF_INET) | |
239 | { | |
240 | memset (&to, 0, sizeof (struct sockaddr_in)); | |
241 | to.sin_port = htons (RIP_PORT_DEFAULT); | |
242 | to.sin_addr = p->prefix; | |
243 | ||
718e3744 | 244 | if (IS_RIP_DEBUG_EVENT) |
245 | zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr)); | |
718e3744 | 246 | |
931cd54d | 247 | rip_request_send (&to, ifp, version, connected); |
718e3744 | 248 | } |
249 | } | |
250 | } | |
251 | } | |
252 | ||
253 | /* This will be executed when interface goes up. */ | |
254 | void | |
255 | rip_request_interface (struct interface *ifp) | |
256 | { | |
257 | struct rip_interface *ri; | |
258 | ||
259 | /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */ | |
260 | if (if_is_loopback (ifp)) | |
261 | return; | |
262 | ||
263 | /* If interface is down, don't send RIP packet. */ | |
2e3b2e47 | 264 | if (! if_is_operative (ifp)) |
718e3744 | 265 | return; |
266 | ||
267 | /* Fetch RIP interface information. */ | |
268 | ri = ifp->info; | |
269 | ||
270 | ||
271 | /* If there is no version configuration in the interface, | |
272 | use rip's version setting. */ | |
f38a471c | 273 | { |
274 | int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? | |
275 | rip->version_send : ri->ri_send); | |
276 | if (vsend & RIPv1) | |
277 | rip_request_interface_send (ifp, RIPv1); | |
278 | if (vsend & RIPv2) | |
279 | rip_request_interface_send (ifp, RIPv2); | |
280 | } | |
718e3744 | 281 | } |
282 | ||
283 | /* Send RIP request to the neighbor. */ | |
284 | void | |
285 | rip_request_neighbor (struct in_addr addr) | |
286 | { | |
287 | struct sockaddr_in to; | |
288 | ||
289 | memset (&to, 0, sizeof (struct sockaddr_in)); | |
290 | to.sin_port = htons (RIP_PORT_DEFAULT); | |
291 | to.sin_addr = addr; | |
292 | ||
931cd54d | 293 | rip_request_send (&to, NULL, rip->version_send, NULL); |
718e3744 | 294 | } |
295 | ||
296 | /* Request routes at all interfaces. */ | |
297 | void | |
298 | rip_request_neighbor_all () | |
299 | { | |
300 | struct route_node *rp; | |
301 | ||
302 | if (! rip) | |
303 | return; | |
304 | ||
305 | if (IS_RIP_DEBUG_EVENT) | |
306 | zlog_info ("request to the all neighbor"); | |
307 | ||
308 | /* Send request to all neighbor. */ | |
309 | for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) | |
310 | if (rp->info) | |
311 | rip_request_neighbor (rp->p.u.prefix4); | |
312 | } | |
313 | ||
314 | /* Multicast packet receive socket. */ | |
315 | int | |
316 | rip_multicast_join (struct interface *ifp, int sock) | |
317 | { | |
318 | listnode cnode; | |
319 | ||
2e3b2e47 | 320 | if (if_is_operative (ifp) && if_is_multicast (ifp)) |
718e3744 | 321 | { |
322 | if (IS_RIP_DEBUG_EVENT) | |
323 | zlog_info ("multicast join at %s", ifp->name); | |
324 | ||
325 | for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) | |
326 | { | |
327 | struct prefix_ipv4 *p; | |
328 | struct connected *connected; | |
329 | struct in_addr group; | |
330 | ||
331 | connected = getdata (cnode); | |
332 | p = (struct prefix_ipv4 *) connected->address; | |
333 | ||
334 | if (p->family != AF_INET) | |
335 | continue; | |
336 | ||
337 | group.s_addr = htonl (INADDR_RIP_GROUP); | |
338 | if (ipv4_multicast_join (sock, group, p->prefix, ifp->ifindex) < 0) | |
339 | return -1; | |
340 | else | |
341 | return 0; | |
342 | } | |
343 | } | |
344 | return 0; | |
345 | } | |
346 | ||
347 | /* Leave from multicast group. */ | |
348 | void | |
349 | rip_multicast_leave (struct interface *ifp, int sock) | |
350 | { | |
351 | listnode cnode; | |
352 | ||
353 | if (if_is_up (ifp) && if_is_multicast (ifp)) | |
354 | { | |
355 | if (IS_RIP_DEBUG_EVENT) | |
356 | zlog_info ("multicast leave from %s", ifp->name); | |
357 | ||
358 | for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) | |
359 | { | |
360 | struct prefix_ipv4 *p; | |
361 | struct connected *connected; | |
362 | struct in_addr group; | |
363 | ||
364 | connected = getdata (cnode); | |
365 | p = (struct prefix_ipv4 *) connected->address; | |
366 | ||
367 | if (p->family != AF_INET) | |
368 | continue; | |
369 | ||
370 | group.s_addr = htonl (INADDR_RIP_GROUP); | |
371 | if (ipv4_multicast_leave (sock, group, p->prefix, ifp->ifindex) == 0) | |
372 | return; | |
373 | } | |
374 | } | |
375 | } | |
376 | ||
377 | /* Is there and address on interface that I could use ? */ | |
378 | int | |
379 | rip_if_ipv4_address_check (struct interface *ifp) | |
380 | { | |
381 | struct listnode *nn; | |
382 | struct connected *connected; | |
383 | int count = 0; | |
384 | ||
385 | for (nn = listhead (ifp->connected); nn; nextnode (nn)) | |
386 | if ((connected = getdata (nn)) != NULL) | |
387 | { | |
388 | struct prefix *p; | |
389 | ||
390 | p = connected->address; | |
391 | ||
392 | if (p->family == AF_INET) | |
393 | { | |
394 | count++; | |
395 | } | |
396 | } | |
397 | ||
398 | return count; | |
399 | } | |
31a476c7 | 400 | |
401 | ||
402 | ||
403 | ||
404 | /* Does this address belongs to me ? */ | |
405 | int | |
406 | if_check_address (struct in_addr addr) | |
407 | { | |
408 | listnode node; | |
409 | ||
410 | for (node = listhead (iflist); node; nextnode (node)) | |
411 | { | |
412 | listnode cnode; | |
413 | struct interface *ifp; | |
414 | ||
415 | ifp = getdata (node); | |
416 | ||
417 | for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) | |
418 | { | |
419 | struct connected *connected; | |
420 | struct prefix_ipv4 *p; | |
421 | ||
422 | connected = getdata (cnode); | |
423 | p = (struct prefix_ipv4 *) connected->address; | |
424 | ||
425 | if (p->family != AF_INET) | |
426 | continue; | |
427 | ||
428 | if (IPV4_ADDR_CMP (&p->prefix, &addr) == 0) | |
429 | return 1; | |
430 | } | |
431 | } | |
432 | return 0; | |
433 | } | |
434 | ||
435 | /* is this address from a valid neighbor? (RFC2453 - Sec. 3.9.2) */ | |
436 | int | |
437 | if_valid_neighbor (struct in_addr addr) | |
438 | { | |
439 | listnode node; | |
440 | struct connected *connected = NULL; | |
441 | struct prefix_ipv4 *p; | |
442 | ||
443 | for (node = listhead (iflist); node; nextnode (node)) | |
444 | { | |
445 | listnode cnode; | |
446 | struct interface *ifp; | |
447 | ||
448 | ifp = getdata (node); | |
449 | ||
450 | for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) | |
451 | { | |
452 | struct prefix *pxn = NULL; /* Prefix of the neighbor */ | |
453 | struct prefix *pxc = NULL; /* Prefix of the connected network */ | |
454 | ||
455 | connected = getdata (cnode); | |
456 | ||
457 | if (if_is_pointopoint (ifp)) | |
458 | { | |
459 | p = (struct prefix_ipv4 *) connected->address; | |
460 | ||
461 | if (p && p->family == AF_INET) | |
462 | { | |
463 | if (IPV4_ADDR_SAME (&p->prefix, &addr)) | |
464 | return 1; | |
465 | ||
466 | p = (struct prefix_ipv4 *) connected->destination; | |
467 | if (p && IPV4_ADDR_SAME (&p->prefix, &addr)) | |
468 | return 1; | |
469 | } | |
470 | } | |
471 | else | |
472 | { | |
473 | p = (struct prefix_ipv4 *) connected->address; | |
474 | ||
475 | if (p->family != AF_INET) | |
476 | continue; | |
477 | ||
478 | pxn = prefix_new(); | |
479 | pxn->family = AF_INET; | |
480 | pxn->prefixlen = 32; | |
481 | pxn->u.prefix4 = addr; | |
482 | ||
483 | pxc = prefix_new(); | |
484 | prefix_copy(pxc, (struct prefix *) p); | |
485 | apply_mask(pxc); | |
486 | ||
487 | if (prefix_match (pxc, pxn)) | |
488 | { | |
489 | prefix_free (pxn); | |
490 | prefix_free (pxc); | |
491 | return 1; | |
492 | } | |
493 | prefix_free(pxc); | |
494 | prefix_free(pxn); | |
495 | } | |
496 | } | |
497 | } | |
498 | return 0; | |
499 | } | |
718e3744 | 500 | |
501 | /* Inteface link down message processing. */ | |
502 | int | |
503 | rip_interface_down (int command, struct zclient *zclient, zebra_size_t length) | |
504 | { | |
505 | struct interface *ifp; | |
506 | struct stream *s; | |
507 | ||
508 | s = zclient->ibuf; | |
509 | ||
510 | /* zebra_interface_state_read() updates interface structure in | |
511 | iflist. */ | |
512 | ifp = zebra_interface_state_read(s); | |
513 | ||
514 | if (ifp == NULL) | |
515 | return 0; | |
516 | ||
517 | rip_if_down(ifp); | |
518 | ||
519 | if (IS_RIP_DEBUG_ZEBRA) | |
520 | zlog_info ("interface %s index %d flags %ld metric %d mtu %d is down", | |
521 | ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); | |
522 | ||
523 | return 0; | |
524 | } | |
525 | ||
526 | /* Inteface link up message processing */ | |
527 | int | |
528 | rip_interface_up (int command, struct zclient *zclient, zebra_size_t length) | |
529 | { | |
530 | struct interface *ifp; | |
531 | ||
532 | /* zebra_interface_state_read () updates interface structure in | |
533 | iflist. */ | |
534 | ifp = zebra_interface_state_read (zclient->ibuf); | |
535 | ||
536 | if (ifp == NULL) | |
537 | return 0; | |
538 | ||
539 | if (IS_RIP_DEBUG_ZEBRA) | |
540 | zlog_info ("interface %s index %d flags %ld metric %d mtu %d is up", | |
541 | ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); | |
542 | ||
543 | /* Check if this interface is RIP enabled or not.*/ | |
544 | rip_enable_apply (ifp); | |
545 | ||
546 | /* Check for a passive interface */ | |
547 | rip_passive_interface_apply (ifp); | |
548 | ||
549 | /* Apply distribute list to the all interface. */ | |
550 | rip_distribute_update_interface (ifp); | |
551 | ||
552 | return 0; | |
553 | } | |
554 | ||
555 | /* Inteface addition message from zebra. */ | |
556 | int | |
557 | rip_interface_add (int command, struct zclient *zclient, zebra_size_t length) | |
558 | { | |
559 | struct interface *ifp; | |
560 | ||
561 | ifp = zebra_interface_add_read (zclient->ibuf); | |
562 | ||
563 | if (IS_RIP_DEBUG_ZEBRA) | |
564 | zlog_info ("interface add %s index %d flags %ld metric %d mtu %d", | |
565 | ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); | |
566 | ||
567 | /* Check if this interface is RIP enabled or not.*/ | |
568 | rip_enable_apply (ifp); | |
569 | ||
570 | /* Apply distribute list to the all interface. */ | |
571 | rip_distribute_update_interface (ifp); | |
572 | ||
573 | /* rip_request_neighbor_all (); */ | |
574 | ||
16705130 | 575 | /* Check interface routemap. */ |
576 | rip_if_rmap_update_interface (ifp); | |
577 | ||
718e3744 | 578 | return 0; |
579 | } | |
580 | ||
581 | int | |
582 | rip_interface_delete (int command, struct zclient *zclient, | |
583 | zebra_size_t length) | |
584 | { | |
585 | struct interface *ifp; | |
586 | struct stream *s; | |
587 | ||
588 | ||
589 | s = zclient->ibuf; | |
590 | /* zebra_interface_state_read() updates interface structure in iflist */ | |
591 | ifp = zebra_interface_state_read(s); | |
592 | ||
593 | if (ifp == NULL) | |
594 | return 0; | |
595 | ||
596 | if (if_is_up (ifp)) { | |
597 | rip_if_down(ifp); | |
598 | } | |
599 | ||
600 | zlog_info("interface delete %s index %d flags %ld metric %d mtu %d", | |
601 | ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); | |
602 | ||
603 | /* To support pseudo interface do not free interface structure. */ | |
604 | /* if_delete(ifp); */ | |
605 | ||
606 | return 0; | |
607 | } | |
608 | ||
609 | void | |
610 | rip_interface_clean () | |
611 | { | |
612 | listnode node; | |
613 | struct interface *ifp; | |
614 | struct rip_interface *ri; | |
615 | ||
616 | for (node = listhead (iflist); node; nextnode (node)) | |
617 | { | |
618 | ifp = getdata (node); | |
619 | ri = ifp->info; | |
620 | ||
621 | ri->enable_network = 0; | |
622 | ri->enable_interface = 0; | |
623 | ri->running = 0; | |
624 | ||
625 | if (ri->t_wakeup) | |
626 | { | |
627 | thread_cancel (ri->t_wakeup); | |
628 | ri->t_wakeup = NULL; | |
629 | } | |
630 | } | |
631 | } | |
632 | ||
633 | void | |
634 | rip_interface_reset () | |
635 | { | |
636 | listnode node; | |
637 | struct interface *ifp; | |
638 | struct rip_interface *ri; | |
639 | ||
640 | for (node = listhead (iflist); node; nextnode (node)) | |
641 | { | |
642 | ifp = getdata (node); | |
643 | ri = ifp->info; | |
644 | ||
645 | ri->enable_network = 0; | |
646 | ri->enable_interface = 0; | |
647 | ri->running = 0; | |
648 | ||
649 | ri->ri_send = RI_RIP_UNSPEC; | |
650 | ri->ri_receive = RI_RIP_UNSPEC; | |
651 | ||
652 | /* ri->auth_type = RIP_NO_AUTH; */ | |
653 | ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD; | |
654 | ||
655 | if (ri->auth_str) | |
656 | { | |
657 | free (ri->auth_str); | |
658 | ri->auth_str = NULL; | |
659 | } | |
660 | if (ri->key_chain) | |
661 | { | |
662 | free (ri->key_chain); | |
663 | ri->key_chain = NULL; | |
664 | } | |
665 | ||
16705130 | 666 | ri->split_horizon = RIP_NO_SPLIT_HORIZON; |
667 | ri->split_horizon_default = RIP_NO_SPLIT_HORIZON; | |
718e3744 | 668 | |
669 | ri->list[RIP_FILTER_IN] = NULL; | |
670 | ri->list[RIP_FILTER_OUT] = NULL; | |
671 | ||
672 | ri->prefix[RIP_FILTER_IN] = NULL; | |
673 | ri->prefix[RIP_FILTER_OUT] = NULL; | |
674 | ||
675 | if (ri->t_wakeup) | |
676 | { | |
677 | thread_cancel (ri->t_wakeup); | |
678 | ri->t_wakeup = NULL; | |
679 | } | |
680 | ||
681 | ri->recv_badpackets = 0; | |
682 | ri->recv_badroutes = 0; | |
683 | ri->sent_updates = 0; | |
684 | ||
685 | ri->passive = 0; | |
686 | } | |
687 | } | |
688 | ||
689 | int | |
690 | rip_if_down(struct interface *ifp) | |
691 | { | |
692 | struct route_node *rp; | |
693 | struct rip_info *rinfo; | |
694 | struct rip_interface *ri = NULL; | |
695 | if (rip) | |
696 | { | |
697 | for (rp = route_top (rip->table); rp; rp = route_next (rp)) | |
698 | if ((rinfo = rp->info) != NULL) | |
699 | { | |
700 | /* Routes got through this interface. */ | |
701 | if (rinfo->ifindex == ifp->ifindex && | |
702 | rinfo->type == ZEBRA_ROUTE_RIP && | |
703 | rinfo->sub_type == RIP_ROUTE_RTE) | |
704 | { | |
705 | rip_zebra_ipv4_delete ((struct prefix_ipv4 *) &rp->p, | |
706 | &rinfo->nexthop, | |
707 | rinfo->ifindex); | |
708 | ||
709 | rip_redistribute_delete (rinfo->type,rinfo->sub_type, | |
710 | (struct prefix_ipv4 *)&rp->p, | |
711 | rinfo->ifindex); | |
712 | } | |
713 | else | |
714 | { | |
715 | /* All redistributed routes but static and system */ | |
716 | if ((rinfo->ifindex == ifp->ifindex) && | |
2e3b2e47 | 717 | /* (rinfo->type != ZEBRA_ROUTE_STATIC) && */ |
718e3744 | 718 | (rinfo->type != ZEBRA_ROUTE_SYSTEM)) |
719 | rip_redistribute_delete (rinfo->type,rinfo->sub_type, | |
720 | (struct prefix_ipv4 *)&rp->p, | |
721 | rinfo->ifindex); | |
722 | } | |
723 | } | |
724 | } | |
725 | ||
726 | ri = ifp->info; | |
727 | ||
728 | if (ri->running) | |
729 | { | |
730 | if (IS_RIP_DEBUG_EVENT) | |
731 | zlog_info ("turn off %s", ifp->name); | |
732 | ||
733 | /* Leave from multicast group. */ | |
734 | rip_multicast_leave (ifp, rip->sock); | |
735 | ||
736 | ri->running = 0; | |
737 | } | |
738 | ||
739 | return 0; | |
740 | } | |
741 | ||
742 | /* Needed for stop RIP process. */ | |
743 | void | |
744 | rip_if_down_all () | |
745 | { | |
746 | struct interface *ifp; | |
747 | listnode node; | |
748 | ||
749 | for (node = listhead (iflist); node; nextnode (node)) | |
750 | { | |
751 | ifp = getdata (node); | |
752 | rip_if_down (ifp); | |
753 | } | |
754 | } | |
755 | ||
16705130 | 756 | static void |
757 | rip_apply_address_add (struct connected *ifc) { | |
758 | struct prefix_ipv4 address; | |
759 | struct prefix *p; | |
760 | ||
761 | if (!rip) | |
762 | return; | |
763 | ||
764 | if (! if_is_up(ifc->ifp)) | |
765 | return; | |
766 | ||
767 | p = ifc->address; | |
768 | ||
769 | memset (&address, 0, sizeof (address)); | |
770 | address.family = p->family; | |
771 | address.prefix = p->u.prefix4; | |
772 | address.prefixlen = p->prefixlen; | |
773 | apply_mask_ipv4(&address); | |
774 | ||
775 | /* Check if this interface is RIP enabled or not | |
776 | or Check if this address's prefix is RIP enabled */ | |
777 | if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) || | |
778 | (rip_enable_network_lookup2(ifc) >= 0)) | |
779 | rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, | |
780 | &address, ifc->ifp->ifindex, NULL); | |
781 | ||
782 | } | |
783 | ||
718e3744 | 784 | int |
785 | rip_interface_address_add (int command, struct zclient *zclient, | |
786 | zebra_size_t length) | |
787 | { | |
788 | struct connected *ifc; | |
789 | struct prefix *p; | |
790 | ||
0a589359 | 791 | ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, |
792 | zclient->ibuf); | |
718e3744 | 793 | |
794 | if (ifc == NULL) | |
795 | return 0; | |
796 | ||
797 | p = ifc->address; | |
798 | ||
799 | if (p->family == AF_INET) | |
800 | { | |
801 | if (IS_RIP_DEBUG_ZEBRA) | |
802 | zlog_info ("connected address %s/%d is added", | |
803 | inet_ntoa (p->u.prefix4), p->prefixlen); | |
16705130 | 804 | |
878ef2e7 | 805 | rip_enable_apply(ifc->ifp); |
16705130 | 806 | /* Check if this prefix needs to be redistributed */ |
807 | rip_apply_address_add(ifc); | |
718e3744 | 808 | |
809 | #ifdef HAVE_SNMP | |
810 | rip_ifaddr_add (ifc->ifp, ifc); | |
811 | #endif /* HAVE_SNMP */ | |
812 | } | |
813 | ||
814 | return 0; | |
815 | } | |
816 | ||
16705130 | 817 | static void |
818 | rip_apply_address_del (struct connected *ifc) { | |
819 | struct prefix_ipv4 address; | |
820 | struct prefix *p; | |
821 | ||
822 | if (!rip) | |
823 | return; | |
824 | ||
825 | if (! if_is_up(ifc->ifp)) | |
826 | return; | |
827 | ||
828 | p = ifc->address; | |
829 | ||
830 | memset (&address, 0, sizeof (address)); | |
831 | address.family = p->family; | |
832 | address.prefix = p->u.prefix4; | |
833 | address.prefixlen = p->prefixlen; | |
834 | apply_mask_ipv4(&address); | |
835 | ||
836 | rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, | |
837 | &address, ifc->ifp->ifindex); | |
838 | } | |
839 | ||
718e3744 | 840 | int |
841 | rip_interface_address_delete (int command, struct zclient *zclient, | |
842 | zebra_size_t length) | |
843 | { | |
844 | struct connected *ifc; | |
845 | struct prefix *p; | |
846 | ||
0a589359 | 847 | ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, |
848 | zclient->ibuf); | |
718e3744 | 849 | |
850 | if (ifc) | |
851 | { | |
852 | p = ifc->address; | |
853 | if (p->family == AF_INET) | |
854 | { | |
855 | if (IS_RIP_DEBUG_ZEBRA) | |
856 | ||
857 | zlog_info ("connected address %s/%d is deleted", | |
858 | inet_ntoa (p->u.prefix4), p->prefixlen); | |
859 | ||
860 | #ifdef HAVE_SNMP | |
861 | rip_ifaddr_delete (ifc->ifp, ifc); | |
862 | #endif /* HAVE_SNMP */ | |
863 | ||
16705130 | 864 | /* Chech wether this prefix needs to be removed */ |
865 | rip_apply_address_del(ifc); | |
866 | ||
718e3744 | 867 | } |
868 | ||
869 | connected_free (ifc); | |
870 | ||
871 | } | |
872 | ||
873 | return 0; | |
874 | } | |
875 | \f | |
876 | /* Check interface is enabled by network statement. */ | |
16705130 | 877 | /* Check wether the interface has at least a connected prefix that |
878 | * is within the ripng_enable_network table. */ | |
718e3744 | 879 | int |
16705130 | 880 | rip_enable_network_lookup_if (struct interface *ifp) |
718e3744 | 881 | { |
882 | struct listnode *nn; | |
883 | struct connected *connected; | |
884 | struct prefix_ipv4 address; | |
885 | ||
886 | for (nn = listhead (ifp->connected); nn; nextnode (nn)) | |
887 | if ((connected = getdata (nn)) != NULL) | |
888 | { | |
889 | struct prefix *p; | |
890 | struct route_node *node; | |
891 | ||
892 | p = connected->address; | |
893 | ||
894 | if (p->family == AF_INET) | |
895 | { | |
896 | address.family = AF_INET; | |
897 | address.prefix = p->u.prefix4; | |
898 | address.prefixlen = IPV4_MAX_BITLEN; | |
899 | ||
900 | node = route_node_match (rip_enable_network, | |
901 | (struct prefix *)&address); | |
902 | if (node) | |
903 | { | |
904 | route_unlock_node (node); | |
905 | return 1; | |
906 | } | |
907 | } | |
908 | } | |
909 | return -1; | |
910 | } | |
911 | ||
16705130 | 912 | /* Check wether connected is within the ripng_enable_network table. */ |
913 | int | |
914 | rip_enable_network_lookup2 (struct connected *connected) | |
915 | { | |
916 | struct prefix_ipv4 address; | |
917 | struct prefix *p; | |
918 | ||
919 | p = connected->address; | |
920 | ||
921 | if (p->family == AF_INET) { | |
922 | struct route_node *node; | |
923 | ||
924 | address.family = p->family; | |
925 | address.prefix = p->u.prefix4; | |
926 | address.prefixlen = IPV4_MAX_BITLEN; | |
927 | ||
928 | /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */ | |
929 | node = route_node_match (rip_enable_network, | |
930 | (struct prefix *)&address); | |
931 | ||
932 | if (node) { | |
933 | route_unlock_node (node); | |
934 | return 1; | |
935 | } | |
936 | } | |
937 | ||
938 | return -1; | |
939 | } | |
718e3744 | 940 | /* Add RIP enable network. */ |
941 | int | |
942 | rip_enable_network_add (struct prefix *p) | |
943 | { | |
944 | struct route_node *node; | |
945 | ||
946 | node = route_node_get (rip_enable_network, p); | |
947 | ||
948 | if (node->info) | |
949 | { | |
950 | route_unlock_node (node); | |
951 | return -1; | |
952 | } | |
953 | else | |
954 | node->info = "enabled"; | |
955 | ||
16705130 | 956 | /* XXX: One should find a better solution than a generic one */ |
957 | rip_enable_apply_all(); | |
958 | ||
718e3744 | 959 | return 1; |
960 | } | |
961 | ||
962 | /* Delete RIP enable network. */ | |
963 | int | |
964 | rip_enable_network_delete (struct prefix *p) | |
965 | { | |
966 | struct route_node *node; | |
967 | ||
968 | node = route_node_lookup (rip_enable_network, p); | |
969 | if (node) | |
970 | { | |
971 | node->info = NULL; | |
972 | ||
973 | /* Unlock info lock. */ | |
974 | route_unlock_node (node); | |
975 | ||
976 | /* Unlock lookup lock. */ | |
977 | route_unlock_node (node); | |
978 | ||
16705130 | 979 | /* XXX: One should find a better solution than a generic one */ |
980 | rip_enable_apply_all (); | |
981 | ||
718e3744 | 982 | return 1; |
983 | } | |
984 | return -1; | |
985 | } | |
986 | ||
987 | /* Check interface is enabled by ifname statement. */ | |
988 | int | |
989 | rip_enable_if_lookup (char *ifname) | |
990 | { | |
991 | int i; | |
992 | char *str; | |
993 | ||
994 | for (i = 0; i < vector_max (rip_enable_interface); i++) | |
995 | if ((str = vector_slot (rip_enable_interface, i)) != NULL) | |
996 | if (strcmp (str, ifname) == 0) | |
997 | return i; | |
998 | return -1; | |
999 | } | |
1000 | ||
1001 | /* Add interface to rip_enable_if. */ | |
1002 | int | |
1003 | rip_enable_if_add (char *ifname) | |
1004 | { | |
1005 | int ret; | |
1006 | ||
1007 | ret = rip_enable_if_lookup (ifname); | |
1008 | if (ret >= 0) | |
1009 | return -1; | |
1010 | ||
1011 | vector_set (rip_enable_interface, strdup (ifname)); | |
1012 | ||
16705130 | 1013 | rip_enable_apply_all(); /* TODOVJ */ |
1014 | ||
718e3744 | 1015 | return 1; |
1016 | } | |
1017 | ||
1018 | /* Delete interface from rip_enable_if. */ | |
1019 | int | |
1020 | rip_enable_if_delete (char *ifname) | |
1021 | { | |
1022 | int index; | |
1023 | char *str; | |
1024 | ||
1025 | index = rip_enable_if_lookup (ifname); | |
1026 | if (index < 0) | |
1027 | return -1; | |
1028 | ||
1029 | str = vector_slot (rip_enable_interface, index); | |
1030 | free (str); | |
1031 | vector_unset (rip_enable_interface, index); | |
1032 | ||
16705130 | 1033 | rip_enable_apply_all(); /* TODOVJ */ |
1034 | ||
718e3744 | 1035 | return 1; |
1036 | } | |
1037 | ||
1038 | /* Join to multicast group and send request to the interface. */ | |
1039 | int | |
1040 | rip_interface_wakeup (struct thread *t) | |
1041 | { | |
1042 | struct interface *ifp; | |
1043 | struct rip_interface *ri; | |
1044 | ||
1045 | /* Get interface. */ | |
1046 | ifp = THREAD_ARG (t); | |
1047 | ||
1048 | ri = ifp->info; | |
1049 | ri->t_wakeup = NULL; | |
1050 | ||
1051 | /* Join to multicast group. */ | |
1052 | if (rip_multicast_join (ifp, rip->sock) < 0) | |
1053 | { | |
1054 | zlog_err ("multicast join failed, interface %s not running", ifp->name); | |
1055 | return 0; | |
1056 | } | |
1057 | ||
1058 | /* Set running flag. */ | |
1059 | ri->running = 1; | |
1060 | ||
1061 | /* Send RIP request to the interface. */ | |
1062 | rip_request_interface (ifp); | |
1063 | ||
1064 | return 0; | |
1065 | } | |
1066 | ||
1067 | int rip_redistribute_check (int); | |
1068 | ||
1069 | void | |
1070 | rip_connect_set (struct interface *ifp, int set) | |
1071 | { | |
1072 | struct listnode *nn; | |
1073 | struct connected *connected; | |
1074 | struct prefix_ipv4 address; | |
1075 | ||
1076 | for (nn = listhead (ifp->connected); nn; nextnode (nn)) | |
1077 | if ((connected = getdata (nn)) != NULL) | |
1078 | { | |
1079 | struct prefix *p; | |
1080 | p = connected->address; | |
1081 | ||
1082 | if (p->family != AF_INET) | |
1083 | continue; | |
1084 | ||
1085 | address.family = AF_INET; | |
1086 | address.prefix = p->u.prefix4; | |
1087 | address.prefixlen = p->prefixlen; | |
1088 | apply_mask_ipv4 (&address); | |
1089 | ||
16705130 | 1090 | if (set) { |
1091 | /* Check once more wether this prefix is within a "network IF_OR_PREF" one */ | |
1092 | if ((rip_enable_if_lookup(connected->ifp->name) >= 0) || | |
1093 | (rip_enable_network_lookup2(connected) >= 0)) | |
1094 | rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, | |
1095 | &address, connected->ifp->ifindex, NULL); | |
1096 | } else | |
718e3744 | 1097 | { |
1098 | rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, | |
1099 | &address, connected->ifp->ifindex); | |
1100 | if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT)) | |
1101 | rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE, | |
1102 | &address, connected->ifp->ifindex, NULL); | |
1103 | } | |
1104 | } | |
1105 | } | |
1106 | ||
1107 | /* Update interface status. */ | |
1108 | void | |
1109 | rip_enable_apply (struct interface *ifp) | |
1110 | { | |
1111 | int ret; | |
1112 | struct rip_interface *ri = NULL; | |
1113 | ||
1114 | /* Check interface. */ | |
2e3b2e47 | 1115 | if (! if_is_operative (ifp)) |
718e3744 | 1116 | return; |
1117 | ||
1118 | ri = ifp->info; | |
1119 | ||
1120 | /* Check network configuration. */ | |
16705130 | 1121 | ret = rip_enable_network_lookup_if (ifp); |
718e3744 | 1122 | |
1123 | /* If the interface is matched. */ | |
1124 | if (ret > 0) | |
1125 | ri->enable_network = 1; | |
1126 | else | |
1127 | ri->enable_network = 0; | |
1128 | ||
1129 | /* Check interface name configuration. */ | |
1130 | ret = rip_enable_if_lookup (ifp->name); | |
1131 | if (ret >= 0) | |
1132 | ri->enable_interface = 1; | |
1133 | else | |
1134 | ri->enable_interface = 0; | |
1135 | ||
1136 | /* any interface MUST have an IPv4 address */ | |
1137 | if ( ! rip_if_ipv4_address_check (ifp) ) | |
1138 | { | |
1139 | ri->enable_network = 0; | |
1140 | ri->enable_interface = 0; | |
1141 | } | |
1142 | ||
1143 | /* Update running status of the interface. */ | |
1144 | if (ri->enable_network || ri->enable_interface) | |
1145 | { | |
718e3744 | 1146 | { |
1147 | if (IS_RIP_DEBUG_EVENT) | |
1148 | zlog_info ("turn on %s", ifp->name); | |
1149 | ||
1150 | /* Add interface wake up thread. */ | |
1151 | if (! ri->t_wakeup) | |
1152 | ri->t_wakeup = thread_add_timer (master, rip_interface_wakeup, | |
1153 | ifp, 1); | |
1154 | rip_connect_set (ifp, 1); | |
1155 | } | |
1156 | } | |
1157 | else | |
1158 | { | |
1159 | if (ri->running) | |
1160 | { | |
16705130 | 1161 | /* Might as well clean up the route table as well |
1162 | * rip_if_down sets to 0 ri->running, and displays "turn off %s" | |
1163 | **/ | |
718e3744 | 1164 | rip_if_down(ifp); |
1165 | ||
718e3744 | 1166 | rip_connect_set (ifp, 0); |
1167 | } | |
1168 | } | |
1169 | } | |
1170 | ||
1171 | /* Apply network configuration to all interface. */ | |
1172 | void | |
1173 | rip_enable_apply_all () | |
1174 | { | |
1175 | struct interface *ifp; | |
1176 | listnode node; | |
1177 | ||
1178 | /* Check each interface. */ | |
1179 | for (node = listhead (iflist); node; nextnode (node)) | |
1180 | { | |
1181 | ifp = getdata (node); | |
1182 | rip_enable_apply (ifp); | |
1183 | } | |
1184 | } | |
1185 | ||
1186 | int | |
1187 | rip_neighbor_lookup (struct sockaddr_in *from) | |
1188 | { | |
1189 | struct prefix_ipv4 p; | |
1190 | struct route_node *node; | |
1191 | ||
1192 | memset (&p, 0, sizeof (struct prefix_ipv4)); | |
1193 | p.family = AF_INET; | |
1194 | p.prefix = from->sin_addr; | |
1195 | p.prefixlen = IPV4_MAX_BITLEN; | |
1196 | ||
1197 | node = route_node_lookup (rip->neighbor, (struct prefix *) &p); | |
1198 | if (node) | |
1199 | { | |
1200 | route_unlock_node (node); | |
1201 | return 1; | |
1202 | } | |
1203 | return 0; | |
1204 | } | |
1205 | ||
1206 | /* Add new RIP neighbor to the neighbor tree. */ | |
1207 | int | |
1208 | rip_neighbor_add (struct prefix_ipv4 *p) | |
1209 | { | |
1210 | struct route_node *node; | |
1211 | ||
1212 | node = route_node_get (rip->neighbor, (struct prefix *) p); | |
1213 | ||
1214 | if (node->info) | |
1215 | return -1; | |
1216 | ||
1217 | node->info = rip->neighbor; | |
1218 | ||
1219 | return 0; | |
1220 | } | |
1221 | ||
1222 | /* Delete RIP neighbor from the neighbor tree. */ | |
1223 | int | |
1224 | rip_neighbor_delete (struct prefix_ipv4 *p) | |
1225 | { | |
1226 | struct route_node *node; | |
1227 | ||
1228 | /* Lock for look up. */ | |
1229 | node = route_node_lookup (rip->neighbor, (struct prefix *) p); | |
1230 | if (! node) | |
1231 | return -1; | |
1232 | ||
1233 | node->info = NULL; | |
1234 | ||
1235 | /* Unlock lookup lock. */ | |
1236 | route_unlock_node (node); | |
1237 | ||
1238 | /* Unlock real neighbor information lock. */ | |
1239 | route_unlock_node (node); | |
1240 | ||
1241 | return 0; | |
1242 | } | |
1243 | ||
1244 | /* Clear all network and neighbor configuration. */ | |
1245 | void | |
1246 | rip_clean_network () | |
1247 | { | |
1248 | int i; | |
1249 | char *str; | |
1250 | struct route_node *rn; | |
1251 | ||
1252 | /* rip_enable_network. */ | |
1253 | for (rn = route_top (rip_enable_network); rn; rn = route_next (rn)) | |
1254 | if (rn->info) | |
1255 | { | |
1256 | rn->info = NULL; | |
1257 | route_unlock_node (rn); | |
1258 | } | |
1259 | ||
1260 | /* rip_enable_interface. */ | |
1261 | for (i = 0; i < vector_max (rip_enable_interface); i++) | |
1262 | if ((str = vector_slot (rip_enable_interface, i)) != NULL) | |
1263 | { | |
1264 | free (str); | |
1265 | vector_slot (rip_enable_interface, i) = NULL; | |
1266 | } | |
1267 | } | |
1268 | \f | |
1269 | /* Utility function for looking up passive interface settings. */ | |
1270 | int | |
4aaff3f8 | 1271 | rip_passive_nondefault_lookup (char *ifname) |
718e3744 | 1272 | { |
1273 | int i; | |
1274 | char *str; | |
1275 | ||
4aaff3f8 | 1276 | for (i = 0; i < vector_max (Vrip_passive_nondefault); i++) |
1277 | if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL) | |
718e3744 | 1278 | if (strcmp (str, ifname) == 0) |
1279 | return i; | |
1280 | return -1; | |
1281 | } | |
1282 | ||
1283 | void | |
1284 | rip_passive_interface_apply (struct interface *ifp) | |
1285 | { | |
718e3744 | 1286 | struct rip_interface *ri; |
1287 | ||
1288 | ri = ifp->info; | |
1289 | ||
4aaff3f8 | 1290 | ri->passive = ((rip_passive_nondefault_lookup (ifp->name) < 0) ? |
1291 | passive_default : !passive_default); | |
1292 | ||
1293 | if (IS_RIP_DEBUG_ZEBRA) | |
1294 | zlog_info ("interface %s: passive = %d",ifp->name,ri->passive); | |
718e3744 | 1295 | } |
1296 | ||
1297 | void | |
1298 | rip_passive_interface_apply_all () | |
1299 | { | |
1300 | struct interface *ifp; | |
1301 | listnode node; | |
1302 | ||
1303 | for (node = listhead (iflist); node; nextnode (node)) | |
1304 | { | |
1305 | ifp = getdata (node); | |
1306 | rip_passive_interface_apply (ifp); | |
1307 | } | |
1308 | } | |
1309 | ||
1310 | /* Passive interface. */ | |
1311 | int | |
4aaff3f8 | 1312 | rip_passive_nondefault_set (struct vty *vty, char *ifname) |
718e3744 | 1313 | { |
4aaff3f8 | 1314 | if (rip_passive_nondefault_lookup (ifname) >= 0) |
718e3744 | 1315 | return CMD_WARNING; |
1316 | ||
4aaff3f8 | 1317 | vector_set (Vrip_passive_nondefault, strdup (ifname)); |
718e3744 | 1318 | |
1319 | rip_passive_interface_apply_all (); | |
1320 | ||
1321 | return CMD_SUCCESS; | |
1322 | } | |
1323 | ||
1324 | int | |
4aaff3f8 | 1325 | rip_passive_nondefault_unset (struct vty *vty, char *ifname) |
718e3744 | 1326 | { |
1327 | int i; | |
1328 | char *str; | |
1329 | ||
4aaff3f8 | 1330 | i = rip_passive_nondefault_lookup (ifname); |
718e3744 | 1331 | if (i < 0) |
1332 | return CMD_WARNING; | |
1333 | ||
4aaff3f8 | 1334 | str = vector_slot (Vrip_passive_nondefault, i); |
718e3744 | 1335 | free (str); |
4aaff3f8 | 1336 | vector_unset (Vrip_passive_nondefault, i); |
718e3744 | 1337 | |
1338 | rip_passive_interface_apply_all (); | |
1339 | ||
1340 | return CMD_SUCCESS; | |
1341 | } | |
1342 | ||
1343 | /* Free all configured RIP passive-interface settings. */ | |
1344 | void | |
4aaff3f8 | 1345 | rip_passive_nondefault_clean () |
718e3744 | 1346 | { |
1347 | int i; | |
1348 | char *str; | |
1349 | ||
4aaff3f8 | 1350 | for (i = 0; i < vector_max (Vrip_passive_nondefault); i++) |
1351 | if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL) | |
718e3744 | 1352 | { |
1353 | free (str); | |
4aaff3f8 | 1354 | vector_slot (Vrip_passive_nondefault, i) = NULL; |
718e3744 | 1355 | } |
1356 | rip_passive_interface_apply_all (); | |
1357 | } | |
1358 | \f | |
1359 | /* RIP enable network or interface configuration. */ | |
1360 | DEFUN (rip_network, | |
1361 | rip_network_cmd, | |
1362 | "network (A.B.C.D/M|WORD)", | |
1363 | "Enable routing on an IP network\n" | |
1364 | "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" | |
1365 | "Interface name\n") | |
1366 | { | |
1367 | int ret; | |
1368 | struct prefix_ipv4 p; | |
1369 | ||
1370 | ret = str2prefix_ipv4 (argv[0], &p); | |
1371 | ||
1372 | if (ret) | |
1373 | ret = rip_enable_network_add ((struct prefix *) &p); | |
1374 | else | |
1375 | ret = rip_enable_if_add (argv[0]); | |
1376 | ||
1377 | if (ret < 0) | |
1378 | { | |
1379 | vty_out (vty, "There is a same network configuration %s%s", argv[0], | |
1380 | VTY_NEWLINE); | |
1381 | return CMD_WARNING; | |
1382 | } | |
1383 | ||
718e3744 | 1384 | return CMD_SUCCESS; |
1385 | } | |
1386 | ||
1387 | /* RIP enable network or interface configuration. */ | |
1388 | DEFUN (no_rip_network, | |
1389 | no_rip_network_cmd, | |
1390 | "no network (A.B.C.D/M|WORD)", | |
1391 | NO_STR | |
1392 | "Enable routing on an IP network\n" | |
1393 | "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" | |
1394 | "Interface name\n") | |
1395 | { | |
1396 | int ret; | |
1397 | struct prefix_ipv4 p; | |
1398 | ||
1399 | ret = str2prefix_ipv4 (argv[0], &p); | |
1400 | ||
1401 | if (ret) | |
1402 | ret = rip_enable_network_delete ((struct prefix *) &p); | |
1403 | else | |
1404 | ret = rip_enable_if_delete (argv[0]); | |
1405 | ||
1406 | if (ret < 0) | |
1407 | { | |
1408 | vty_out (vty, "Can't find network configuration %s%s", argv[0], | |
1409 | VTY_NEWLINE); | |
1410 | return CMD_WARNING; | |
1411 | } | |
1412 | ||
718e3744 | 1413 | return CMD_SUCCESS; |
1414 | } | |
1415 | ||
1416 | /* RIP neighbor configuration set. */ | |
1417 | DEFUN (rip_neighbor, | |
1418 | rip_neighbor_cmd, | |
1419 | "neighbor A.B.C.D", | |
1420 | "Specify a neighbor router\n" | |
1421 | "Neighbor address\n") | |
1422 | { | |
1423 | int ret; | |
1424 | struct prefix_ipv4 p; | |
1425 | ||
1426 | ret = str2prefix_ipv4 (argv[0], &p); | |
1427 | ||
1428 | if (ret <= 0) | |
1429 | { | |
1430 | vty_out (vty, "Please specify address by A.B.C.D%s", VTY_NEWLINE); | |
1431 | return CMD_WARNING; | |
1432 | } | |
1433 | ||
1434 | rip_neighbor_add (&p); | |
1435 | ||
1436 | return CMD_SUCCESS; | |
1437 | } | |
1438 | ||
1439 | /* RIP neighbor configuration unset. */ | |
1440 | DEFUN (no_rip_neighbor, | |
1441 | no_rip_neighbor_cmd, | |
1442 | "no neighbor A.B.C.D", | |
1443 | NO_STR | |
1444 | "Specify a neighbor router\n" | |
1445 | "Neighbor address\n") | |
1446 | { | |
1447 | int ret; | |
1448 | struct prefix_ipv4 p; | |
1449 | ||
1450 | ret = str2prefix_ipv4 (argv[0], &p); | |
1451 | ||
1452 | if (ret <= 0) | |
1453 | { | |
1454 | vty_out (vty, "Please specify address by A.B.C.D%s", VTY_NEWLINE); | |
1455 | return CMD_WARNING; | |
1456 | } | |
1457 | ||
1458 | rip_neighbor_delete (&p); | |
1459 | ||
1460 | return CMD_SUCCESS; | |
1461 | } | |
1462 | ||
1463 | DEFUN (ip_rip_receive_version, | |
1464 | ip_rip_receive_version_cmd, | |
1465 | "ip rip receive version (1|2)", | |
1466 | IP_STR | |
1467 | "Routing Information Protocol\n" | |
1468 | "Advertisement reception\n" | |
1469 | "Version control\n" | |
1470 | "RIP version 1\n" | |
1471 | "RIP version 2\n") | |
1472 | { | |
1473 | struct interface *ifp; | |
1474 | struct rip_interface *ri; | |
1475 | ||
1476 | ifp = (struct interface *)vty->index; | |
1477 | ri = ifp->info; | |
1478 | ||
1479 | /* Version 1. */ | |
1480 | if (atoi (argv[0]) == 1) | |
1481 | { | |
1482 | ri->ri_receive = RI_RIP_VERSION_1; | |
1483 | return CMD_SUCCESS; | |
1484 | } | |
1485 | if (atoi (argv[0]) == 2) | |
1486 | { | |
1487 | ri->ri_receive = RI_RIP_VERSION_2; | |
1488 | return CMD_SUCCESS; | |
1489 | } | |
1490 | return CMD_WARNING; | |
1491 | } | |
1492 | ||
1493 | DEFUN (ip_rip_receive_version_1, | |
1494 | ip_rip_receive_version_1_cmd, | |
1495 | "ip rip receive version 1 2", | |
1496 | IP_STR | |
1497 | "Routing Information Protocol\n" | |
1498 | "Advertisement reception\n" | |
1499 | "Version control\n" | |
1500 | "RIP version 1\n" | |
1501 | "RIP version 2\n") | |
1502 | { | |
1503 | struct interface *ifp; | |
1504 | struct rip_interface *ri; | |
1505 | ||
1506 | ifp = (struct interface *)vty->index; | |
1507 | ri = ifp->info; | |
1508 | ||
1509 | /* Version 1 and 2. */ | |
1510 | ri->ri_receive = RI_RIP_VERSION_1_AND_2; | |
1511 | return CMD_SUCCESS; | |
1512 | } | |
1513 | ||
1514 | DEFUN (ip_rip_receive_version_2, | |
1515 | ip_rip_receive_version_2_cmd, | |
1516 | "ip rip receive version 2 1", | |
1517 | IP_STR | |
1518 | "Routing Information Protocol\n" | |
1519 | "Advertisement reception\n" | |
1520 | "Version control\n" | |
1521 | "RIP version 2\n" | |
1522 | "RIP version 1\n") | |
1523 | { | |
1524 | struct interface *ifp; | |
1525 | struct rip_interface *ri; | |
1526 | ||
1527 | ifp = (struct interface *)vty->index; | |
1528 | ri = ifp->info; | |
1529 | ||
1530 | /* Version 1 and 2. */ | |
1531 | ri->ri_receive = RI_RIP_VERSION_1_AND_2; | |
1532 | return CMD_SUCCESS; | |
1533 | } | |
1534 | ||
1535 | DEFUN (no_ip_rip_receive_version, | |
1536 | no_ip_rip_receive_version_cmd, | |
1537 | "no ip rip receive version", | |
1538 | NO_STR | |
1539 | IP_STR | |
1540 | "Routing Information Protocol\n" | |
1541 | "Advertisement reception\n" | |
1542 | "Version control\n") | |
1543 | { | |
1544 | struct interface *ifp; | |
1545 | struct rip_interface *ri; | |
1546 | ||
1547 | ifp = (struct interface *)vty->index; | |
1548 | ri = ifp->info; | |
1549 | ||
1550 | ri->ri_receive = RI_RIP_UNSPEC; | |
1551 | return CMD_SUCCESS; | |
1552 | } | |
1553 | ||
1554 | ALIAS (no_ip_rip_receive_version, | |
1555 | no_ip_rip_receive_version_num_cmd, | |
1556 | "no ip rip receive version (1|2)", | |
1557 | NO_STR | |
1558 | IP_STR | |
1559 | "Routing Information Protocol\n" | |
1560 | "Advertisement reception\n" | |
1561 | "Version control\n" | |
1562 | "Version 1\n" | |
1563 | "Version 2\n") | |
1564 | ||
1565 | DEFUN (ip_rip_send_version, | |
1566 | ip_rip_send_version_cmd, | |
1567 | "ip rip send version (1|2)", | |
1568 | IP_STR | |
1569 | "Routing Information Protocol\n" | |
1570 | "Advertisement transmission\n" | |
1571 | "Version control\n" | |
1572 | "RIP version 1\n" | |
1573 | "RIP version 2\n") | |
1574 | { | |
1575 | struct interface *ifp; | |
1576 | struct rip_interface *ri; | |
1577 | ||
1578 | ifp = (struct interface *)vty->index; | |
1579 | ri = ifp->info; | |
1580 | ||
1581 | /* Version 1. */ | |
1582 | if (atoi (argv[0]) == 1) | |
1583 | { | |
1584 | ri->ri_send = RI_RIP_VERSION_1; | |
1585 | return CMD_SUCCESS; | |
1586 | } | |
1587 | if (atoi (argv[0]) == 2) | |
1588 | { | |
1589 | ri->ri_send = RI_RIP_VERSION_2; | |
1590 | return CMD_SUCCESS; | |
1591 | } | |
1592 | return CMD_WARNING; | |
1593 | } | |
1594 | ||
1595 | DEFUN (ip_rip_send_version_1, | |
1596 | ip_rip_send_version_1_cmd, | |
1597 | "ip rip send version 1 2", | |
1598 | IP_STR | |
1599 | "Routing Information Protocol\n" | |
1600 | "Advertisement transmission\n" | |
1601 | "Version control\n" | |
1602 | "RIP version 1\n" | |
1603 | "RIP version 2\n") | |
1604 | { | |
1605 | struct interface *ifp; | |
1606 | struct rip_interface *ri; | |
1607 | ||
1608 | ifp = (struct interface *)vty->index; | |
1609 | ri = ifp->info; | |
1610 | ||
1611 | /* Version 1 and 2. */ | |
1612 | ri->ri_send = RI_RIP_VERSION_1_AND_2; | |
1613 | return CMD_SUCCESS; | |
1614 | } | |
1615 | ||
1616 | DEFUN (ip_rip_send_version_2, | |
1617 | ip_rip_send_version_2_cmd, | |
1618 | "ip rip send version 2 1", | |
1619 | IP_STR | |
1620 | "Routing Information Protocol\n" | |
1621 | "Advertisement transmission\n" | |
1622 | "Version control\n" | |
1623 | "RIP version 2\n" | |
1624 | "RIP version 1\n") | |
1625 | { | |
1626 | struct interface *ifp; | |
1627 | struct rip_interface *ri; | |
1628 | ||
1629 | ifp = (struct interface *)vty->index; | |
1630 | ri = ifp->info; | |
1631 | ||
1632 | /* Version 1 and 2. */ | |
1633 | ri->ri_send = RI_RIP_VERSION_1_AND_2; | |
1634 | return CMD_SUCCESS; | |
1635 | } | |
1636 | ||
1637 | DEFUN (no_ip_rip_send_version, | |
1638 | no_ip_rip_send_version_cmd, | |
1639 | "no ip rip send version", | |
1640 | NO_STR | |
1641 | IP_STR | |
1642 | "Routing Information Protocol\n" | |
1643 | "Advertisement transmission\n" | |
1644 | "Version control\n") | |
1645 | { | |
1646 | struct interface *ifp; | |
1647 | struct rip_interface *ri; | |
1648 | ||
1649 | ifp = (struct interface *)vty->index; | |
1650 | ri = ifp->info; | |
1651 | ||
1652 | ri->ri_send = RI_RIP_UNSPEC; | |
1653 | return CMD_SUCCESS; | |
1654 | } | |
1655 | ||
1656 | ALIAS (no_ip_rip_send_version, | |
1657 | no_ip_rip_send_version_num_cmd, | |
1658 | "no ip rip send version (1|2)", | |
1659 | NO_STR | |
1660 | IP_STR | |
1661 | "Routing Information Protocol\n" | |
1662 | "Advertisement transmission\n" | |
1663 | "Version control\n" | |
1664 | "Version 1\n" | |
1665 | "Version 2\n") | |
1666 | ||
1667 | DEFUN (ip_rip_authentication_mode, | |
1668 | ip_rip_authentication_mode_cmd, | |
1669 | "ip rip authentication mode (md5|text)", | |
1670 | IP_STR | |
1671 | "Routing Information Protocol\n" | |
1672 | "Authentication control\n" | |
1673 | "Authentication mode\n" | |
1674 | "Keyed message digest\n" | |
1675 | "Clear text authentication\n") | |
1676 | { | |
1677 | struct interface *ifp; | |
1678 | struct rip_interface *ri; | |
1679 | ||
1680 | ifp = (struct interface *)vty->index; | |
1681 | ri = ifp->info; | |
1682 | ||
ca5e516c | 1683 | if ( (argc < 1) || (argc > 2) ) |
1684 | { | |
1685 | vty_out (vty, "incorrect argument count%s", VTY_NEWLINE); | |
1686 | return CMD_WARNING; | |
1687 | } | |
1688 | ||
718e3744 | 1689 | if (strncmp ("md5", argv[0], strlen (argv[0])) == 0) |
1690 | ri->auth_type = RIP_AUTH_MD5; | |
1691 | else if (strncmp ("text", argv[0], strlen (argv[0])) == 0) | |
1692 | ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD; | |
1693 | else | |
1694 | { | |
1695 | vty_out (vty, "mode should be md5 or text%s", VTY_NEWLINE); | |
1696 | return CMD_WARNING; | |
1697 | } | |
1698 | ||
ca5e516c | 1699 | if (argc == 1) |
1700 | return CMD_SUCCESS; | |
1701 | ||
1702 | if ( (argc == 2) && (ri->auth_type != RIP_AUTH_MD5) ) | |
1703 | { | |
1704 | vty_out (vty, "auth length argument only valid for md5%s", VTY_NEWLINE); | |
1705 | return CMD_WARNING; | |
1706 | } | |
1707 | ||
1708 | if (strncmp ("r", argv[1], 1) == 0) | |
1709 | ri->md5_auth_len = RIP_AUTH_MD5_SIZE; | |
1710 | else if (strncmp ("o", argv[1], 1) == 0) | |
1711 | ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; | |
1712 | else | |
1713 | return CMD_WARNING; | |
1714 | ||
718e3744 | 1715 | return CMD_SUCCESS; |
1716 | } | |
1717 | ||
ca5e516c | 1718 | ALIAS (ip_rip_authentication_mode, |
1719 | ip_rip_authentication_mode_authlen_cmd, | |
1720 | "ip rip authentication mode (md5|text) auth-length (rfc|old-ripd)", | |
1721 | IP_STR | |
1722 | "Routing Information Protocol\n" | |
1723 | "Authentication control\n" | |
1724 | "Authentication mode\n" | |
1725 | "Keyed message digest\n" | |
1726 | "Clear text authentication\n" | |
1727 | "MD5 authentication data length\n" | |
1728 | "RFC compatible\n" | |
1729 | "Old ripd compatible\n") | |
1730 | ||
718e3744 | 1731 | DEFUN (no_ip_rip_authentication_mode, |
1732 | no_ip_rip_authentication_mode_cmd, | |
1733 | "no ip rip authentication mode", | |
1734 | NO_STR | |
1735 | IP_STR | |
1736 | "Routing Information Protocol\n" | |
1737 | "Authentication control\n" | |
1738 | "Authentication mode\n") | |
1739 | { | |
1740 | struct interface *ifp; | |
1741 | struct rip_interface *ri; | |
1742 | ||
1743 | ifp = (struct interface *)vty->index; | |
1744 | ri = ifp->info; | |
1745 | ||
1746 | /* ri->auth_type = RIP_NO_AUTH; */ | |
1747 | ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD; | |
ca5e516c | 1748 | ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; |
718e3744 | 1749 | |
1750 | return CMD_SUCCESS; | |
1751 | } | |
1752 | ||
1753 | ALIAS (no_ip_rip_authentication_mode, | |
1754 | no_ip_rip_authentication_mode_type_cmd, | |
1755 | "no ip rip authentication mode (md5|text)", | |
1756 | NO_STR | |
1757 | IP_STR | |
1758 | "Routing Information Protocol\n" | |
1759 | "Authentication control\n" | |
1760 | "Authentication mode\n" | |
1761 | "Keyed message digest\n" | |
1762 | "Clear text authentication\n") | |
1763 | ||
ca5e516c | 1764 | ALIAS (no_ip_rip_authentication_mode, |
1765 | no_ip_rip_authentication_mode_type_authlen_cmd, | |
1766 | "no ip rip authentication mode (md5|text) auth-length (rfc|old-ripd)", | |
1767 | NO_STR | |
1768 | IP_STR | |
1769 | "Routing Information Protocol\n" | |
1770 | "Authentication control\n" | |
1771 | "Authentication mode\n" | |
1772 | "Keyed message digest\n" | |
1773 | "Clear text authentication\n" | |
1774 | "MD5 authentication data length\n" | |
1775 | "RFC compatible\n" | |
1776 | "Old ripd compatible\n") | |
1777 | ||
718e3744 | 1778 | DEFUN (ip_rip_authentication_string, |
1779 | ip_rip_authentication_string_cmd, | |
1780 | "ip rip authentication string LINE", | |
1781 | IP_STR | |
1782 | "Routing Information Protocol\n" | |
1783 | "Authentication control\n" | |
1784 | "Authentication string\n" | |
1785 | "Authentication string\n") | |
1786 | { | |
1787 | struct interface *ifp; | |
1788 | struct rip_interface *ri; | |
1789 | ||
1790 | ifp = (struct interface *)vty->index; | |
1791 | ri = ifp->info; | |
1792 | ||
1793 | if (strlen (argv[0]) > 16) | |
1794 | { | |
1795 | vty_out (vty, "%% RIPv2 authentication string must be shorter than 16%s", | |
1796 | VTY_NEWLINE); | |
1797 | return CMD_WARNING; | |
1798 | } | |
1799 | ||
1800 | if (ri->key_chain) | |
1801 | { | |
1802 | vty_out (vty, "%% key-chain configuration exists%s", VTY_NEWLINE); | |
1803 | return CMD_WARNING; | |
1804 | } | |
1805 | ||
1806 | if (ri->auth_str) | |
1807 | free (ri->auth_str); | |
1808 | ||
1809 | ri->auth_str = strdup (argv[0]); | |
1810 | ||
1811 | return CMD_SUCCESS; | |
1812 | } | |
1813 | ||
1814 | DEFUN (no_ip_rip_authentication_string, | |
1815 | no_ip_rip_authentication_string_cmd, | |
1816 | "no ip rip authentication string", | |
1817 | NO_STR | |
1818 | IP_STR | |
1819 | "Routing Information Protocol\n" | |
1820 | "Authentication control\n" | |
1821 | "Authentication string\n") | |
1822 | { | |
1823 | struct interface *ifp; | |
1824 | struct rip_interface *ri; | |
1825 | ||
1826 | ifp = (struct interface *)vty->index; | |
1827 | ri = ifp->info; | |
1828 | ||
1829 | if (ri->auth_str) | |
1830 | free (ri->auth_str); | |
1831 | ||
1832 | ri->auth_str = NULL; | |
1833 | ||
1834 | return CMD_SUCCESS; | |
1835 | } | |
1836 | ||
1837 | ALIAS (no_ip_rip_authentication_string, | |
1838 | no_ip_rip_authentication_string2_cmd, | |
1839 | "no ip rip authentication string LINE", | |
1840 | NO_STR | |
1841 | IP_STR | |
1842 | "Routing Information Protocol\n" | |
1843 | "Authentication control\n" | |
1844 | "Authentication string\n" | |
1845 | "Authentication string\n") | |
1846 | ||
1847 | DEFUN (ip_rip_authentication_key_chain, | |
1848 | ip_rip_authentication_key_chain_cmd, | |
1849 | "ip rip authentication key-chain LINE", | |
1850 | IP_STR | |
1851 | "Routing Information Protocol\n" | |
1852 | "Authentication control\n" | |
1853 | "Authentication key-chain\n" | |
1854 | "name of key-chain\n") | |
1855 | { | |
1856 | struct interface *ifp; | |
1857 | struct rip_interface *ri; | |
1858 | ||
1859 | ifp = (struct interface *) vty->index; | |
1860 | ri = ifp->info; | |
1861 | ||
1862 | if (ri->auth_str) | |
1863 | { | |
1864 | vty_out (vty, "%% authentication string configuration exists%s", | |
1865 | VTY_NEWLINE); | |
1866 | return CMD_WARNING; | |
1867 | } | |
1868 | ||
1869 | if (ri->key_chain) | |
1870 | free (ri->key_chain); | |
1871 | ||
1872 | ri->key_chain = strdup (argv[0]); | |
1873 | ||
1874 | return CMD_SUCCESS; | |
1875 | } | |
1876 | ||
1877 | DEFUN (no_ip_rip_authentication_key_chain, | |
1878 | no_ip_rip_authentication_key_chain_cmd, | |
1879 | "no ip rip authentication key-chain", | |
1880 | NO_STR | |
1881 | IP_STR | |
1882 | "Routing Information Protocol\n" | |
1883 | "Authentication control\n" | |
1884 | "Authentication key-chain\n") | |
1885 | { | |
1886 | struct interface *ifp; | |
1887 | struct rip_interface *ri; | |
1888 | ||
1889 | ifp = (struct interface *) vty->index; | |
1890 | ri = ifp->info; | |
1891 | ||
1892 | if (ri->key_chain) | |
1893 | free (ri->key_chain); | |
1894 | ||
1895 | ri->key_chain = NULL; | |
1896 | ||
1897 | return CMD_SUCCESS; | |
1898 | } | |
1899 | ||
1900 | ALIAS (no_ip_rip_authentication_key_chain, | |
1901 | no_ip_rip_authentication_key_chain2_cmd, | |
1902 | "no ip rip authentication key-chain LINE", | |
1903 | NO_STR | |
1904 | IP_STR | |
1905 | "Routing Information Protocol\n" | |
1906 | "Authentication control\n" | |
1907 | "Authentication key-chain\n" | |
1908 | "name of key-chain\n") | |
1909 | ||
16705130 | 1910 | /* CHANGED: ip rip split-horizon |
1911 | Cisco and Zebra's command is | |
1912 | ip split-horizon | |
1913 | */ | |
1914 | DEFUN (ip_rip_split_horizon, | |
1915 | ip_rip_split_horizon_cmd, | |
1916 | "ip rip split-horizon", | |
718e3744 | 1917 | IP_STR |
16705130 | 1918 | "Routing Information Protocol\n" |
718e3744 | 1919 | "Perform split horizon\n") |
1920 | { | |
1921 | struct interface *ifp; | |
1922 | struct rip_interface *ri; | |
1923 | ||
1924 | ifp = vty->index; | |
1925 | ri = ifp->info; | |
1926 | ||
16705130 | 1927 | ri->split_horizon = RIP_SPLIT_HORIZON; |
718e3744 | 1928 | return CMD_SUCCESS; |
1929 | } | |
1930 | ||
16705130 | 1931 | DEFUN (ip_rip_split_horizon_poisoned_reverse, |
1932 | ip_rip_split_horizon_poisoned_reverse_cmd, | |
1933 | "ip rip split-horizon poisoned-reverse", | |
1934 | IP_STR | |
1935 | "Routing Information Protocol\n" | |
1936 | "Perform split horizon\n" | |
1937 | "With poisoned-reverse\n") | |
1938 | { | |
1939 | struct interface *ifp; | |
1940 | struct rip_interface *ri; | |
1941 | ||
1942 | ifp = vty->index; | |
1943 | ri = ifp->info; | |
1944 | ||
1945 | ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE; | |
1946 | return CMD_SUCCESS; | |
1947 | } | |
1948 | ||
1949 | /* CHANGED: no ip rip split-horizon | |
1950 | Cisco and Zebra's command is | |
1951 | no ip split-horizon | |
1952 | */ | |
1953 | DEFUN (no_ip_rip_split_horizon, | |
1954 | no_ip_rip_split_horizon_cmd, | |
1955 | "no ip rip split-horizon", | |
718e3744 | 1956 | NO_STR |
1957 | IP_STR | |
16705130 | 1958 | "Routing Information Protocol\n" |
718e3744 | 1959 | "Perform split horizon\n") |
1960 | { | |
1961 | struct interface *ifp; | |
1962 | struct rip_interface *ri; | |
1963 | ||
1964 | ifp = vty->index; | |
1965 | ri = ifp->info; | |
1966 | ||
16705130 | 1967 | ri->split_horizon = RIP_NO_SPLIT_HORIZON; |
718e3744 | 1968 | return CMD_SUCCESS; |
1969 | } | |
1970 | ||
16705130 | 1971 | ALIAS (no_ip_rip_split_horizon, |
1972 | no_ip_rip_split_horizon_poisoned_reverse_cmd, | |
1973 | "no ip rip split-horizon poisoned-reverse", | |
1974 | NO_STR | |
1975 | IP_STR | |
1976 | "Routing Information Protocol\n" | |
1977 | "Perform split horizon\n" | |
1978 | "With poisoned-reverse\n") | |
1979 | ||
718e3744 | 1980 | DEFUN (rip_passive_interface, |
1981 | rip_passive_interface_cmd, | |
56e475cb | 1982 | "passive-interface (IFNAME|default)", |
718e3744 | 1983 | "Suppress routing updates on an interface\n" |
56e475cb | 1984 | "Interface name\n" |
1985 | "default for all interfaces\n") | |
718e3744 | 1986 | { |
4aaff3f8 | 1987 | char *ifname = argv[0]; |
1988 | ||
1989 | if (!strcmp(ifname,"default")) { | |
1990 | passive_default = 1; | |
1991 | rip_passive_nondefault_clean(); | |
1992 | return CMD_SUCCESS; | |
1993 | } | |
1994 | if (passive_default) | |
1995 | return rip_passive_nondefault_unset (vty, ifname); | |
1996 | else | |
1997 | return rip_passive_nondefault_set (vty, ifname); | |
718e3744 | 1998 | } |
1999 | ||
2000 | DEFUN (no_rip_passive_interface, | |
2001 | no_rip_passive_interface_cmd, | |
56e475cb | 2002 | "no passive-interface (IFNAME|default)", |
718e3744 | 2003 | NO_STR |
2004 | "Suppress routing updates on an interface\n" | |
56e475cb | 2005 | "Interface name\n" |
2006 | "default for all interfaces\n") | |
718e3744 | 2007 | { |
4aaff3f8 | 2008 | char *ifname = argv[0]; |
2009 | ||
2010 | if (!strcmp(ifname,"default")) { | |
2011 | passive_default = 0; | |
2012 | rip_passive_nondefault_clean(); | |
2013 | return CMD_SUCCESS; | |
2014 | } | |
2015 | if (passive_default) | |
2016 | return rip_passive_nondefault_set (vty, ifname); | |
2017 | else | |
2018 | return rip_passive_nondefault_unset (vty, ifname); | |
718e3744 | 2019 | } |
2020 | \f | |
2021 | /* Write rip configuration of each interface. */ | |
2022 | int | |
2023 | rip_interface_config_write (struct vty *vty) | |
2024 | { | |
2025 | listnode node; | |
2026 | struct interface *ifp; | |
2027 | ||
2028 | for (node = listhead (iflist); node; nextnode (node)) | |
2029 | { | |
2030 | struct rip_interface *ri; | |
2031 | ||
2032 | ifp = getdata (node); | |
2033 | ri = ifp->info; | |
2034 | ||
16705130 | 2035 | /* Do not display the interface if there is no |
2036 | * configuration about it. | |
2037 | **/ | |
2038 | if ((!ifp->desc) && | |
2039 | (ri->split_horizon == ri->split_horizon_default) && | |
2040 | (ri->ri_send == RI_RIP_UNSPEC) && | |
2041 | (ri->ri_receive == RI_RIP_UNSPEC) && | |
2042 | (ri->auth_type != RIP_AUTH_MD5) && | |
ca5e516c | 2043 | (ri->md5_auth_len != RIP_AUTH_MD5_SIZE) && |
16705130 | 2044 | (!ri->auth_str) && |
2045 | (!ri->key_chain) ) | |
2046 | continue; | |
2047 | ||
718e3744 | 2048 | vty_out (vty, "interface %s%s", ifp->name, |
2049 | VTY_NEWLINE); | |
2050 | ||
2051 | if (ifp->desc) | |
2052 | vty_out (vty, " description %s%s", ifp->desc, | |
2053 | VTY_NEWLINE); | |
2054 | ||
2055 | /* Split horizon. */ | |
2056 | if (ri->split_horizon != ri->split_horizon_default) | |
2057 | { | |
16705130 | 2058 | switch (ri->split_horizon) { |
2059 | case RIP_SPLIT_HORIZON: | |
2060 | vty_out (vty, " ip rip split-horizon%s", VTY_NEWLINE); | |
2061 | break; | |
2062 | case RIP_SPLIT_HORIZON_POISONED_REVERSE: | |
2063 | vty_out (vty, " ip rip split-horizon poisoned-reverse%s", | |
2064 | VTY_NEWLINE); | |
2065 | break; | |
2066 | case RIP_NO_SPLIT_HORIZON: | |
2067 | default: | |
2068 | vty_out (vty, " no ip rip split-horizon%s", VTY_NEWLINE); | |
2069 | break; | |
2070 | } | |
718e3744 | 2071 | } |
2072 | ||
2073 | /* RIP version setting. */ | |
2074 | if (ri->ri_send != RI_RIP_UNSPEC) | |
2075 | vty_out (vty, " ip rip send version %s%s", | |
2076 | lookup (ri_version_msg, ri->ri_send), | |
2077 | VTY_NEWLINE); | |
2078 | ||
2079 | if (ri->ri_receive != RI_RIP_UNSPEC) | |
2080 | vty_out (vty, " ip rip receive version %s%s", | |
2081 | lookup (ri_version_msg, ri->ri_receive), | |
2082 | VTY_NEWLINE); | |
2083 | ||
2084 | /* RIP authentication. */ | |
2085 | #if 0 | |
2086 | /* RIP_AUTH_SIMPLE_PASSWORD becomes default mode. */ | |
2087 | if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) | |
2088 | vty_out (vty, " ip rip authentication mode text%s", VTY_NEWLINE); | |
2089 | #endif /* 0 */ | |
ca5e516c | 2090 | |
718e3744 | 2091 | if (ri->auth_type == RIP_AUTH_MD5) |
ca5e516c | 2092 | { |
2093 | vty_out (vty, " ip rip authentication mode md5"); | |
2094 | if (ri->md5_auth_len == RIP_AUTH_MD5_COMPAT_SIZE) | |
2095 | vty_out (vty, " auth-length old-ripd"); | |
2096 | else | |
2097 | vty_out (vty, " auth-length rfc"); | |
2098 | vty_out (vty, "%s", VTY_NEWLINE); | |
2099 | } | |
718e3744 | 2100 | |
2101 | if (ri->auth_str) | |
2102 | vty_out (vty, " ip rip authentication string %s%s", | |
2103 | ri->auth_str, VTY_NEWLINE); | |
2104 | ||
2105 | if (ri->key_chain) | |
2106 | vty_out (vty, " ip rip authentication key-chain %s%s", | |
2107 | ri->key_chain, VTY_NEWLINE); | |
2108 | ||
2109 | vty_out (vty, "!%s", VTY_NEWLINE); | |
2110 | } | |
2111 | return 0; | |
2112 | } | |
2113 | ||
2114 | int | |
2115 | config_write_rip_network (struct vty *vty, int config_mode) | |
2116 | { | |
2117 | int i; | |
2118 | char *ifname; | |
2119 | struct route_node *node; | |
2120 | ||
2121 | /* Network type RIP enable interface statement. */ | |
2122 | for (node = route_top (rip_enable_network); node; node = route_next (node)) | |
2123 | if (node->info) | |
2124 | vty_out (vty, "%s%s/%d%s", | |
2125 | config_mode ? " network " : " ", | |
2126 | inet_ntoa (node->p.u.prefix4), | |
2127 | node->p.prefixlen, | |
2128 | VTY_NEWLINE); | |
2129 | ||
2130 | /* Interface name RIP enable statement. */ | |
2131 | for (i = 0; i < vector_max (rip_enable_interface); i++) | |
2132 | if ((ifname = vector_slot (rip_enable_interface, i)) != NULL) | |
2133 | vty_out (vty, "%s%s%s", | |
2134 | config_mode ? " network " : " ", | |
2135 | ifname, | |
2136 | VTY_NEWLINE); | |
2137 | ||
2138 | /* RIP neighbors listing. */ | |
2139 | for (node = route_top (rip->neighbor); node; node = route_next (node)) | |
2140 | if (node->info) | |
2141 | vty_out (vty, "%s%s%s", | |
2142 | config_mode ? " neighbor " : " ", | |
2143 | inet_ntoa (node->p.u.prefix4), | |
2144 | VTY_NEWLINE); | |
2145 | ||
2146 | /* RIP passive interface listing. */ | |
4aaff3f8 | 2147 | if (config_mode) { |
2148 | if (passive_default) | |
01d0908a | 2149 | vty_out (vty, " passive-interface default%s", VTY_NEWLINE); |
4aaff3f8 | 2150 | for (i = 0; i < vector_max (Vrip_passive_nondefault); i++) |
2151 | if ((ifname = vector_slot (Vrip_passive_nondefault, i)) != NULL) | |
2152 | vty_out (vty, " %spassive-interface %s%s", | |
2153 | (passive_default ? "no " : ""), ifname, VTY_NEWLINE); | |
2154 | } | |
718e3744 | 2155 | |
2156 | return 0; | |
2157 | } | |
2158 | ||
2159 | struct cmd_node interface_node = | |
2160 | { | |
2161 | INTERFACE_NODE, | |
2162 | "%s(config-if)# ", | |
2163 | 1, | |
2164 | }; | |
2165 | ||
2166 | /* Called when interface structure allocated. */ | |
2167 | int | |
2168 | rip_interface_new_hook (struct interface *ifp) | |
2169 | { | |
2170 | ifp->info = rip_interface_new (); | |
2171 | return 0; | |
2172 | } | |
2173 | ||
2174 | /* Called when interface structure deleted. */ | |
2175 | int | |
2176 | rip_interface_delete_hook (struct interface *ifp) | |
2177 | { | |
2178 | XFREE (MTYPE_RIP_INTERFACE, ifp->info); | |
16705130 | 2179 | ifp->info = NULL; |
718e3744 | 2180 | return 0; |
2181 | } | |
2182 | ||
2183 | /* Allocate and initialize interface vector. */ | |
2184 | void | |
2185 | rip_if_init () | |
2186 | { | |
2187 | /* Default initial size of interface vector. */ | |
2188 | if_init(); | |
2189 | if_add_hook (IF_NEW_HOOK, rip_interface_new_hook); | |
2190 | if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook); | |
2191 | ||
2192 | /* RIP network init. */ | |
2193 | rip_enable_interface = vector_init (1); | |
2194 | rip_enable_network = route_table_init (); | |
2195 | ||
2196 | /* RIP passive interface. */ | |
4aaff3f8 | 2197 | Vrip_passive_nondefault = vector_init (1); |
718e3744 | 2198 | |
2199 | /* Install interface node. */ | |
2200 | install_node (&interface_node, rip_interface_config_write); | |
2201 | ||
2202 | /* Install commands. */ | |
2203 | install_element (CONFIG_NODE, &interface_cmd); | |
034489de | 2204 | install_element (CONFIG_NODE, &no_interface_cmd); |
718e3744 | 2205 | install_default (INTERFACE_NODE); |
2206 | install_element (INTERFACE_NODE, &interface_desc_cmd); | |
2207 | install_element (INTERFACE_NODE, &no_interface_desc_cmd); | |
2208 | install_element (RIP_NODE, &rip_network_cmd); | |
2209 | install_element (RIP_NODE, &no_rip_network_cmd); | |
2210 | install_element (RIP_NODE, &rip_neighbor_cmd); | |
2211 | install_element (RIP_NODE, &no_rip_neighbor_cmd); | |
2212 | ||
2213 | install_element (RIP_NODE, &rip_passive_interface_cmd); | |
2214 | install_element (RIP_NODE, &no_rip_passive_interface_cmd); | |
2215 | ||
2216 | install_element (INTERFACE_NODE, &ip_rip_send_version_cmd); | |
2217 | install_element (INTERFACE_NODE, &ip_rip_send_version_1_cmd); | |
2218 | install_element (INTERFACE_NODE, &ip_rip_send_version_2_cmd); | |
2219 | install_element (INTERFACE_NODE, &no_ip_rip_send_version_cmd); | |
2220 | install_element (INTERFACE_NODE, &no_ip_rip_send_version_num_cmd); | |
2221 | ||
2222 | install_element (INTERFACE_NODE, &ip_rip_receive_version_cmd); | |
2223 | install_element (INTERFACE_NODE, &ip_rip_receive_version_1_cmd); | |
2224 | install_element (INTERFACE_NODE, &ip_rip_receive_version_2_cmd); | |
2225 | install_element (INTERFACE_NODE, &no_ip_rip_receive_version_cmd); | |
2226 | install_element (INTERFACE_NODE, &no_ip_rip_receive_version_num_cmd); | |
2227 | ||
2228 | install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd); | |
ca5e516c | 2229 | install_element (INTERFACE_NODE, &ip_rip_authentication_mode_authlen_cmd); |
718e3744 | 2230 | install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); |
2231 | install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_type_cmd); | |
ca5e516c | 2232 | install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_type_authlen_cmd); |
718e3744 | 2233 | |
2234 | install_element (INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd); | |
2235 | install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain_cmd); | |
2236 | install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain2_cmd); | |
2237 | ||
2238 | install_element (INTERFACE_NODE, &ip_rip_authentication_string_cmd); | |
2239 | install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd); | |
2240 | install_element (INTERFACE_NODE, &no_ip_rip_authentication_string2_cmd); | |
2241 | ||
16705130 | 2242 | install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd); |
2243 | install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd); | |
2244 | install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd); | |
2245 | install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd); | |
718e3744 | 2246 | } |