blob: b47252253d4726df1915dfd48bb9913f69b7b247 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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"
pauledd7c242003-06-04 13:59:38 +000037#include "privs.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "zebra/connected.h"
40
41#include "ripd/ripd.h"
42#include "ripd/rip_debug.h"
43
44void rip_enable_apply (struct interface *);
45void rip_passive_interface_apply (struct interface *);
46int rip_if_down(struct interface *ifp);
hasso16705132003-05-25 14:49:19 +000047int rip_enable_if_lookup (char *ifname);
48int rip_enable_network_lookup2 (struct connected *connected);
49void rip_enable_apply_all ();
50
paul718e3742002-12-13 20:15:29 +000051
52struct 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
pauledd7c242003-06-04 13:59:38 +000060extern struct zebra_privs_t ripd_privs;
61
paul718e3742002-12-13 20:15:29 +000062/* RIP enabled network vector. */
63vector rip_enable_interface;
64
65/* RIP enabled interface table. */
66struct route_table *rip_enable_network;
67
68/* Vector to store passive-interface name. */
paul4aaff3f2003-06-07 01:04:45 +000069static int passive_default; /* are we in passive-interface default mode? */
70vector Vrip_passive_nondefault;
paul718e3742002-12-13 20:15:29 +000071
72/* Join to the RIP version 2 multicast group. */
73int
74ipv4_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. */
95int
96ipv4_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
115/* Allocate new RIP's interface configuration. */
116struct rip_interface *
117rip_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;
128
129 /* Set default split-horizon behavior. If the interface is Frame
130 Relay or SMDS is enabled, the default value for split-horizon is
131 off. But currently Zebra does detect Frame Relay or SMDS
132 interface. So all interface is set to split horizon. */
hasso16705132003-05-25 14:49:19 +0000133 ri->split_horizon_default = RIP_SPLIT_HORIZON;
paul718e3742002-12-13 20:15:29 +0000134 ri->split_horizon = ri->split_horizon_default;
135
136 return ri;
137}
138
139void
140rip_interface_multicast_set (int sock, struct interface *ifp)
141{
142 int ret;
143 listnode node;
144 struct servent *sp;
145 struct sockaddr_in from;
146
147 for (node = listhead (ifp->connected); node; nextnode (node))
148 {
149 struct prefix_ipv4 *p;
150 struct connected *connected;
151 struct in_addr addr;
152
153 connected = getdata (node);
154 p = (struct prefix_ipv4 *) connected->address;
155
156 if (p->family == AF_INET)
157 {
158 addr = p->prefix;
159
160 if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF,
161 addr, 0, ifp->ifindex) < 0)
162 {
163 zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);
164 return;
165 }
166
167 /* Bind myself. */
168 memset (&from, 0, sizeof (struct sockaddr_in));
169
170 /* Set RIP port. */
171 sp = getservbyname ("router", "udp");
172 if (sp)
173 from.sin_port = sp->s_port;
174 else
175 from.sin_port = htons (RIP_PORT_DEFAULT);
176
177 /* Address shoud be any address. */
178 from.sin_family = AF_INET;
179 from.sin_addr = addr;
180#ifdef HAVE_SIN_LEN
181 from.sin_len = sizeof (struct sockaddr_in);
182#endif /* HAVE_SIN_LEN */
183
pauledd7c242003-06-04 13:59:38 +0000184 if (ripd_privs.change (ZPRIVS_RAISE))
185 zlog_err ("rip_interface_multicast_set: could not raise privs");
186
paul718e3742002-12-13 20:15:29 +0000187 ret = bind (sock, (struct sockaddr *) & from,
188 sizeof (struct sockaddr_in));
189 if (ret < 0)
190 {
191 zlog_warn ("Can't bind socket: %s", strerror (errno));
192 return;
193 }
194
pauledd7c242003-06-04 13:59:38 +0000195 if (ripd_privs.change (ZPRIVS_LOWER))
196 zlog_err ("rip_interface_multicast_set: could not lower privs");
197
paul718e3742002-12-13 20:15:29 +0000198 return;
199
200 }
201 }
202}
203
204/* Send RIP request packet to specified interface. */
205void
206rip_request_interface_send (struct interface *ifp, u_char version)
207{
208 struct sockaddr_in to;
209
210 /* RIPv2 support multicast. */
211 if (version == RIPv2 && if_is_multicast (ifp))
212 {
213
214 if (IS_RIP_DEBUG_EVENT)
215 zlog_info ("multicast request on %s", ifp->name);
216
217 rip_request_send (NULL, ifp, version);
218 return;
219 }
220
221 /* RIPv1 and non multicast interface. */
222 if (if_is_pointopoint (ifp) || if_is_broadcast (ifp))
223 {
224 listnode cnode;
225
226 if (IS_RIP_DEBUG_EVENT)
227 zlog_info ("broadcast request to %s", ifp->name);
228
229 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
230 {
231 struct prefix_ipv4 *p;
232 struct connected *connected;
233
234 connected = getdata (cnode);
235 p = (struct prefix_ipv4 *) connected->destination;
236
237 if (p->family == AF_INET)
238 {
239 memset (&to, 0, sizeof (struct sockaddr_in));
240 to.sin_port = htons (RIP_PORT_DEFAULT);
241 to.sin_addr = p->prefix;
242
paul718e3742002-12-13 20:15:29 +0000243 if (IS_RIP_DEBUG_EVENT)
244 zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));
paul718e3742002-12-13 20:15:29 +0000245
246 rip_request_send (&to, ifp, version);
247 }
248 }
249 }
250}
251
252/* This will be executed when interface goes up. */
253void
254rip_request_interface (struct interface *ifp)
255{
256 struct rip_interface *ri;
257
258 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
259 if (if_is_loopback (ifp))
260 return;
261
262 /* If interface is down, don't send RIP packet. */
paul2e3b2e42002-12-13 21:03:13 +0000263 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000264 return;
265
266 /* Fetch RIP interface information. */
267 ri = ifp->info;
268
269
270 /* If there is no version configuration in the interface,
271 use rip's version setting. */
paulf38a4712003-06-07 01:10:00 +0000272 {
273 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
274 rip->version_send : ri->ri_send);
275 if (vsend & RIPv1)
276 rip_request_interface_send (ifp, RIPv1);
277 if (vsend & RIPv2)
278 rip_request_interface_send (ifp, RIPv2);
279 }
paul718e3742002-12-13 20:15:29 +0000280}
281
282/* Send RIP request to the neighbor. */
283void
284rip_request_neighbor (struct in_addr addr)
285{
286 struct sockaddr_in to;
287
288 memset (&to, 0, sizeof (struct sockaddr_in));
289 to.sin_port = htons (RIP_PORT_DEFAULT);
290 to.sin_addr = addr;
291
paulf38a4712003-06-07 01:10:00 +0000292 rip_request_send (&to, NULL, rip->version_send);
paul718e3742002-12-13 20:15:29 +0000293}
294
295/* Request routes at all interfaces. */
296void
297rip_request_neighbor_all ()
298{
299 struct route_node *rp;
300
301 if (! rip)
302 return;
303
304 if (IS_RIP_DEBUG_EVENT)
305 zlog_info ("request to the all neighbor");
306
307 /* Send request to all neighbor. */
308 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
309 if (rp->info)
310 rip_request_neighbor (rp->p.u.prefix4);
311}
312
313/* Multicast packet receive socket. */
314int
315rip_multicast_join (struct interface *ifp, int sock)
316{
317 listnode cnode;
318
paul2e3b2e42002-12-13 21:03:13 +0000319 if (if_is_operative (ifp) && if_is_multicast (ifp))
paul718e3742002-12-13 20:15:29 +0000320 {
321 if (IS_RIP_DEBUG_EVENT)
322 zlog_info ("multicast join at %s", ifp->name);
323
324 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
325 {
326 struct prefix_ipv4 *p;
327 struct connected *connected;
328 struct in_addr group;
329
330 connected = getdata (cnode);
331 p = (struct prefix_ipv4 *) connected->address;
332
333 if (p->family != AF_INET)
334 continue;
335
336 group.s_addr = htonl (INADDR_RIP_GROUP);
337 if (ipv4_multicast_join (sock, group, p->prefix, ifp->ifindex) < 0)
338 return -1;
339 else
340 return 0;
341 }
342 }
343 return 0;
344}
345
346/* Leave from multicast group. */
347void
348rip_multicast_leave (struct interface *ifp, int sock)
349{
350 listnode cnode;
351
352 if (if_is_up (ifp) && if_is_multicast (ifp))
353 {
354 if (IS_RIP_DEBUG_EVENT)
355 zlog_info ("multicast leave from %s", ifp->name);
356
357 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
358 {
359 struct prefix_ipv4 *p;
360 struct connected *connected;
361 struct in_addr group;
362
363 connected = getdata (cnode);
364 p = (struct prefix_ipv4 *) connected->address;
365
366 if (p->family != AF_INET)
367 continue;
368
369 group.s_addr = htonl (INADDR_RIP_GROUP);
370 if (ipv4_multicast_leave (sock, group, p->prefix, ifp->ifindex) == 0)
371 return;
372 }
373 }
374}
375
376/* Is there and address on interface that I could use ? */
377int
378rip_if_ipv4_address_check (struct interface *ifp)
379{
380 struct listnode *nn;
381 struct connected *connected;
382 int count = 0;
383
384 for (nn = listhead (ifp->connected); nn; nextnode (nn))
385 if ((connected = getdata (nn)) != NULL)
386 {
387 struct prefix *p;
388
389 p = connected->address;
390
391 if (p->family == AF_INET)
392 {
393 count++;
394 }
395 }
396
397 return count;
398}
paul718e3742002-12-13 20:15:29 +0000399
400/* Inteface link down message processing. */
401int
402rip_interface_down (int command, struct zclient *zclient, zebra_size_t length)
403{
404 struct interface *ifp;
405 struct stream *s;
406
407 s = zclient->ibuf;
408
409 /* zebra_interface_state_read() updates interface structure in
410 iflist. */
411 ifp = zebra_interface_state_read(s);
412
413 if (ifp == NULL)
414 return 0;
415
416 rip_if_down(ifp);
417
418 if (IS_RIP_DEBUG_ZEBRA)
419 zlog_info ("interface %s index %d flags %ld metric %d mtu %d is down",
420 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
421
422 return 0;
423}
424
425/* Inteface link up message processing */
426int
427rip_interface_up (int command, struct zclient *zclient, zebra_size_t length)
428{
429 struct interface *ifp;
430
431 /* zebra_interface_state_read () updates interface structure in
432 iflist. */
433 ifp = zebra_interface_state_read (zclient->ibuf);
434
435 if (ifp == NULL)
436 return 0;
437
438 if (IS_RIP_DEBUG_ZEBRA)
439 zlog_info ("interface %s index %d flags %ld metric %d mtu %d is up",
440 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
441
442 /* Check if this interface is RIP enabled or not.*/
443 rip_enable_apply (ifp);
444
445 /* Check for a passive interface */
446 rip_passive_interface_apply (ifp);
447
448 /* Apply distribute list to the all interface. */
449 rip_distribute_update_interface (ifp);
450
451 return 0;
452}
453
454/* Inteface addition message from zebra. */
455int
456rip_interface_add (int command, struct zclient *zclient, zebra_size_t length)
457{
458 struct interface *ifp;
459
460 ifp = zebra_interface_add_read (zclient->ibuf);
461
462 if (IS_RIP_DEBUG_ZEBRA)
463 zlog_info ("interface add %s index %d flags %ld metric %d mtu %d",
464 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
465
466 /* Check if this interface is RIP enabled or not.*/
467 rip_enable_apply (ifp);
468
469 /* Apply distribute list to the all interface. */
470 rip_distribute_update_interface (ifp);
471
472 /* rip_request_neighbor_all (); */
473
hasso16705132003-05-25 14:49:19 +0000474 /* Check interface routemap. */
475 rip_if_rmap_update_interface (ifp);
476
paul718e3742002-12-13 20:15:29 +0000477 return 0;
478}
479
480int
481rip_interface_delete (int command, struct zclient *zclient,
482 zebra_size_t length)
483{
484 struct interface *ifp;
485 struct stream *s;
486
487
488 s = zclient->ibuf;
489 /* zebra_interface_state_read() updates interface structure in iflist */
490 ifp = zebra_interface_state_read(s);
491
492 if (ifp == NULL)
493 return 0;
494
495 if (if_is_up (ifp)) {
496 rip_if_down(ifp);
497 }
498
499 zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
500 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
501
502 /* To support pseudo interface do not free interface structure. */
503 /* if_delete(ifp); */
504
505 return 0;
506}
507
508void
509rip_interface_clean ()
510{
511 listnode node;
512 struct interface *ifp;
513 struct rip_interface *ri;
514
515 for (node = listhead (iflist); node; nextnode (node))
516 {
517 ifp = getdata (node);
518 ri = ifp->info;
519
520 ri->enable_network = 0;
521 ri->enable_interface = 0;
522 ri->running = 0;
523
524 if (ri->t_wakeup)
525 {
526 thread_cancel (ri->t_wakeup);
527 ri->t_wakeup = NULL;
528 }
529 }
530}
531
532void
533rip_interface_reset ()
534{
535 listnode node;
536 struct interface *ifp;
537 struct rip_interface *ri;
538
539 for (node = listhead (iflist); node; nextnode (node))
540 {
541 ifp = getdata (node);
542 ri = ifp->info;
543
544 ri->enable_network = 0;
545 ri->enable_interface = 0;
546 ri->running = 0;
547
548 ri->ri_send = RI_RIP_UNSPEC;
549 ri->ri_receive = RI_RIP_UNSPEC;
550
551 /* ri->auth_type = RIP_NO_AUTH; */
552 ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;
553
554 if (ri->auth_str)
555 {
556 free (ri->auth_str);
557 ri->auth_str = NULL;
558 }
559 if (ri->key_chain)
560 {
561 free (ri->key_chain);
562 ri->key_chain = NULL;
563 }
564
hasso16705132003-05-25 14:49:19 +0000565 ri->split_horizon = RIP_NO_SPLIT_HORIZON;
566 ri->split_horizon_default = RIP_NO_SPLIT_HORIZON;
paul718e3742002-12-13 20:15:29 +0000567
568 ri->list[RIP_FILTER_IN] = NULL;
569 ri->list[RIP_FILTER_OUT] = NULL;
570
571 ri->prefix[RIP_FILTER_IN] = NULL;
572 ri->prefix[RIP_FILTER_OUT] = NULL;
573
574 if (ri->t_wakeup)
575 {
576 thread_cancel (ri->t_wakeup);
577 ri->t_wakeup = NULL;
578 }
579
580 ri->recv_badpackets = 0;
581 ri->recv_badroutes = 0;
582 ri->sent_updates = 0;
583
584 ri->passive = 0;
585 }
586}
587
588int
589rip_if_down(struct interface *ifp)
590{
591 struct route_node *rp;
592 struct rip_info *rinfo;
593 struct rip_interface *ri = NULL;
594 if (rip)
595 {
596 for (rp = route_top (rip->table); rp; rp = route_next (rp))
597 if ((rinfo = rp->info) != NULL)
598 {
599 /* Routes got through this interface. */
600 if (rinfo->ifindex == ifp->ifindex &&
601 rinfo->type == ZEBRA_ROUTE_RIP &&
602 rinfo->sub_type == RIP_ROUTE_RTE)
603 {
604 rip_zebra_ipv4_delete ((struct prefix_ipv4 *) &rp->p,
605 &rinfo->nexthop,
606 rinfo->ifindex);
607
608 rip_redistribute_delete (rinfo->type,rinfo->sub_type,
609 (struct prefix_ipv4 *)&rp->p,
610 rinfo->ifindex);
611 }
612 else
613 {
614 /* All redistributed routes but static and system */
615 if ((rinfo->ifindex == ifp->ifindex) &&
paul2e3b2e42002-12-13 21:03:13 +0000616 /* (rinfo->type != ZEBRA_ROUTE_STATIC) && */
paul718e3742002-12-13 20:15:29 +0000617 (rinfo->type != ZEBRA_ROUTE_SYSTEM))
618 rip_redistribute_delete (rinfo->type,rinfo->sub_type,
619 (struct prefix_ipv4 *)&rp->p,
620 rinfo->ifindex);
621 }
622 }
623 }
624
625 ri = ifp->info;
626
627 if (ri->running)
628 {
629 if (IS_RIP_DEBUG_EVENT)
630 zlog_info ("turn off %s", ifp->name);
631
632 /* Leave from multicast group. */
633 rip_multicast_leave (ifp, rip->sock);
634
635 ri->running = 0;
636 }
637
638 return 0;
639}
640
641/* Needed for stop RIP process. */
642void
643rip_if_down_all ()
644{
645 struct interface *ifp;
646 listnode node;
647
648 for (node = listhead (iflist); node; nextnode (node))
649 {
650 ifp = getdata (node);
651 rip_if_down (ifp);
652 }
653}
654
hasso16705132003-05-25 14:49:19 +0000655static void
656rip_apply_address_add (struct connected *ifc) {
657 struct prefix_ipv4 address;
658 struct prefix *p;
659
660 if (!rip)
661 return;
662
663 if (! if_is_up(ifc->ifp))
664 return;
665
666 p = ifc->address;
667
668 memset (&address, 0, sizeof (address));
669 address.family = p->family;
670 address.prefix = p->u.prefix4;
671 address.prefixlen = p->prefixlen;
672 apply_mask_ipv4(&address);
673
674 /* Check if this interface is RIP enabled or not
675 or Check if this address's prefix is RIP enabled */
676 if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) ||
677 (rip_enable_network_lookup2(ifc) >= 0))
678 rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
679 &address, ifc->ifp->ifindex, NULL);
680
681}
682
paul718e3742002-12-13 20:15:29 +0000683int
684rip_interface_address_add (int command, struct zclient *zclient,
685 zebra_size_t length)
686{
687 struct connected *ifc;
688 struct prefix *p;
689
690 ifc = zebra_interface_address_add_read (zclient->ibuf);
691
692 if (ifc == NULL)
693 return 0;
694
695 p = ifc->address;
696
697 if (p->family == AF_INET)
698 {
699 if (IS_RIP_DEBUG_ZEBRA)
700 zlog_info ("connected address %s/%d is added",
701 inet_ntoa (p->u.prefix4), p->prefixlen);
hasso16705132003-05-25 14:49:19 +0000702
paul878ef2e2003-09-23 23:41:50 +0000703 rip_enable_apply(ifc->ifp);
hasso16705132003-05-25 14:49:19 +0000704 /* Check if this prefix needs to be redistributed */
705 rip_apply_address_add(ifc);
paul718e3742002-12-13 20:15:29 +0000706
707#ifdef HAVE_SNMP
708 rip_ifaddr_add (ifc->ifp, ifc);
709#endif /* HAVE_SNMP */
710 }
711
712 return 0;
713}
714
hasso16705132003-05-25 14:49:19 +0000715static void
716rip_apply_address_del (struct connected *ifc) {
717 struct prefix_ipv4 address;
718 struct prefix *p;
719
720 if (!rip)
721 return;
722
723 if (! if_is_up(ifc->ifp))
724 return;
725
726 p = ifc->address;
727
728 memset (&address, 0, sizeof (address));
729 address.family = p->family;
730 address.prefix = p->u.prefix4;
731 address.prefixlen = p->prefixlen;
732 apply_mask_ipv4(&address);
733
734 rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
735 &address, ifc->ifp->ifindex);
736}
737
paul718e3742002-12-13 20:15:29 +0000738int
739rip_interface_address_delete (int command, struct zclient *zclient,
740 zebra_size_t length)
741{
742 struct connected *ifc;
743 struct prefix *p;
744
745 ifc = zebra_interface_address_delete_read (zclient->ibuf);
746
747 if (ifc)
748 {
749 p = ifc->address;
750 if (p->family == AF_INET)
751 {
752 if (IS_RIP_DEBUG_ZEBRA)
753
754 zlog_info ("connected address %s/%d is deleted",
755 inet_ntoa (p->u.prefix4), p->prefixlen);
756
757#ifdef HAVE_SNMP
758 rip_ifaddr_delete (ifc->ifp, ifc);
759#endif /* HAVE_SNMP */
760
hasso16705132003-05-25 14:49:19 +0000761 /* Chech wether this prefix needs to be removed */
762 rip_apply_address_del(ifc);
763
paul718e3742002-12-13 20:15:29 +0000764 }
765
766 connected_free (ifc);
767
768 }
769
770 return 0;
771}
772
773/* Check interface is enabled by network statement. */
hasso16705132003-05-25 14:49:19 +0000774/* Check wether the interface has at least a connected prefix that
775 * is within the ripng_enable_network table. */
paul718e3742002-12-13 20:15:29 +0000776int
hasso16705132003-05-25 14:49:19 +0000777rip_enable_network_lookup_if (struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000778{
779 struct listnode *nn;
780 struct connected *connected;
781 struct prefix_ipv4 address;
782
783 for (nn = listhead (ifp->connected); nn; nextnode (nn))
784 if ((connected = getdata (nn)) != NULL)
785 {
786 struct prefix *p;
787 struct route_node *node;
788
789 p = connected->address;
790
791 if (p->family == AF_INET)
792 {
793 address.family = AF_INET;
794 address.prefix = p->u.prefix4;
795 address.prefixlen = IPV4_MAX_BITLEN;
796
797 node = route_node_match (rip_enable_network,
798 (struct prefix *)&address);
799 if (node)
800 {
801 route_unlock_node (node);
802 return 1;
803 }
804 }
805 }
806 return -1;
807}
808
hasso16705132003-05-25 14:49:19 +0000809/* Check wether connected is within the ripng_enable_network table. */
810int
811rip_enable_network_lookup2 (struct connected *connected)
812{
813 struct prefix_ipv4 address;
814 struct prefix *p;
815
816 p = connected->address;
817
818 if (p->family == AF_INET) {
819 struct route_node *node;
820
821 address.family = p->family;
822 address.prefix = p->u.prefix4;
823 address.prefixlen = IPV4_MAX_BITLEN;
824
825 /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */
826 node = route_node_match (rip_enable_network,
827 (struct prefix *)&address);
828
829 if (node) {
830 route_unlock_node (node);
831 return 1;
832 }
833 }
834
835 return -1;
836}
paul718e3742002-12-13 20:15:29 +0000837/* Add RIP enable network. */
838int
839rip_enable_network_add (struct prefix *p)
840{
841 struct route_node *node;
842
843 node = route_node_get (rip_enable_network, p);
844
845 if (node->info)
846 {
847 route_unlock_node (node);
848 return -1;
849 }
850 else
851 node->info = "enabled";
852
hasso16705132003-05-25 14:49:19 +0000853 /* XXX: One should find a better solution than a generic one */
854 rip_enable_apply_all();
855
paul718e3742002-12-13 20:15:29 +0000856 return 1;
857}
858
859/* Delete RIP enable network. */
860int
861rip_enable_network_delete (struct prefix *p)
862{
863 struct route_node *node;
864
865 node = route_node_lookup (rip_enable_network, p);
866 if (node)
867 {
868 node->info = NULL;
869
870 /* Unlock info lock. */
871 route_unlock_node (node);
872
873 /* Unlock lookup lock. */
874 route_unlock_node (node);
875
hasso16705132003-05-25 14:49:19 +0000876 /* XXX: One should find a better solution than a generic one */
877 rip_enable_apply_all ();
878
paul718e3742002-12-13 20:15:29 +0000879 return 1;
880 }
881 return -1;
882}
883
884/* Check interface is enabled by ifname statement. */
885int
886rip_enable_if_lookup (char *ifname)
887{
888 int i;
889 char *str;
890
891 for (i = 0; i < vector_max (rip_enable_interface); i++)
892 if ((str = vector_slot (rip_enable_interface, i)) != NULL)
893 if (strcmp (str, ifname) == 0)
894 return i;
895 return -1;
896}
897
898/* Add interface to rip_enable_if. */
899int
900rip_enable_if_add (char *ifname)
901{
902 int ret;
903
904 ret = rip_enable_if_lookup (ifname);
905 if (ret >= 0)
906 return -1;
907
908 vector_set (rip_enable_interface, strdup (ifname));
909
hasso16705132003-05-25 14:49:19 +0000910 rip_enable_apply_all(); /* TODOVJ */
911
paul718e3742002-12-13 20:15:29 +0000912 return 1;
913}
914
915/* Delete interface from rip_enable_if. */
916int
917rip_enable_if_delete (char *ifname)
918{
919 int index;
920 char *str;
921
922 index = rip_enable_if_lookup (ifname);
923 if (index < 0)
924 return -1;
925
926 str = vector_slot (rip_enable_interface, index);
927 free (str);
928 vector_unset (rip_enable_interface, index);
929
hasso16705132003-05-25 14:49:19 +0000930 rip_enable_apply_all(); /* TODOVJ */
931
paul718e3742002-12-13 20:15:29 +0000932 return 1;
933}
934
935/* Join to multicast group and send request to the interface. */
936int
937rip_interface_wakeup (struct thread *t)
938{
939 struct interface *ifp;
940 struct rip_interface *ri;
941
942 /* Get interface. */
943 ifp = THREAD_ARG (t);
944
945 ri = ifp->info;
946 ri->t_wakeup = NULL;
947
948 /* Join to multicast group. */
949 if (rip_multicast_join (ifp, rip->sock) < 0)
950 {
951 zlog_err ("multicast join failed, interface %s not running", ifp->name);
952 return 0;
953 }
954
955 /* Set running flag. */
956 ri->running = 1;
957
958 /* Send RIP request to the interface. */
959 rip_request_interface (ifp);
960
961 return 0;
962}
963
964int rip_redistribute_check (int);
965
966void
967rip_connect_set (struct interface *ifp, int set)
968{
969 struct listnode *nn;
970 struct connected *connected;
971 struct prefix_ipv4 address;
972
973 for (nn = listhead (ifp->connected); nn; nextnode (nn))
974 if ((connected = getdata (nn)) != NULL)
975 {
976 struct prefix *p;
977 p = connected->address;
978
979 if (p->family != AF_INET)
980 continue;
981
982 address.family = AF_INET;
983 address.prefix = p->u.prefix4;
984 address.prefixlen = p->prefixlen;
985 apply_mask_ipv4 (&address);
986
hasso16705132003-05-25 14:49:19 +0000987 if (set) {
988 /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
989 if ((rip_enable_if_lookup(connected->ifp->name) >= 0) ||
990 (rip_enable_network_lookup2(connected) >= 0))
991 rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
992 &address, connected->ifp->ifindex, NULL);
993 } else
paul718e3742002-12-13 20:15:29 +0000994 {
995 rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
996 &address, connected->ifp->ifindex);
997 if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT))
998 rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE,
999 &address, connected->ifp->ifindex, NULL);
1000 }
1001 }
1002}
1003
1004/* Update interface status. */
1005void
1006rip_enable_apply (struct interface *ifp)
1007{
1008 int ret;
1009 struct rip_interface *ri = NULL;
1010
1011 /* Check interface. */
paul2e3b2e42002-12-13 21:03:13 +00001012 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00001013 return;
1014
1015 ri = ifp->info;
1016
1017 /* Check network configuration. */
hasso16705132003-05-25 14:49:19 +00001018 ret = rip_enable_network_lookup_if (ifp);
paul718e3742002-12-13 20:15:29 +00001019
1020 /* If the interface is matched. */
1021 if (ret > 0)
1022 ri->enable_network = 1;
1023 else
1024 ri->enable_network = 0;
1025
1026 /* Check interface name configuration. */
1027 ret = rip_enable_if_lookup (ifp->name);
1028 if (ret >= 0)
1029 ri->enable_interface = 1;
1030 else
1031 ri->enable_interface = 0;
1032
1033 /* any interface MUST have an IPv4 address */
1034 if ( ! rip_if_ipv4_address_check (ifp) )
1035 {
1036 ri->enable_network = 0;
1037 ri->enable_interface = 0;
1038 }
1039
1040 /* Update running status of the interface. */
1041 if (ri->enable_network || ri->enable_interface)
1042 {
paul718e3742002-12-13 20:15:29 +00001043 {
1044 if (IS_RIP_DEBUG_EVENT)
1045 zlog_info ("turn on %s", ifp->name);
1046
1047 /* Add interface wake up thread. */
1048 if (! ri->t_wakeup)
1049 ri->t_wakeup = thread_add_timer (master, rip_interface_wakeup,
1050 ifp, 1);
1051 rip_connect_set (ifp, 1);
1052 }
1053 }
1054 else
1055 {
1056 if (ri->running)
1057 {
hasso16705132003-05-25 14:49:19 +00001058 /* Might as well clean up the route table as well
1059 * rip_if_down sets to 0 ri->running, and displays "turn off %s"
1060 **/
paul718e3742002-12-13 20:15:29 +00001061 rip_if_down(ifp);
1062
paul718e3742002-12-13 20:15:29 +00001063 rip_connect_set (ifp, 0);
1064 }
1065 }
1066}
1067
1068/* Apply network configuration to all interface. */
1069void
1070rip_enable_apply_all ()
1071{
1072 struct interface *ifp;
1073 listnode node;
1074
1075 /* Check each interface. */
1076 for (node = listhead (iflist); node; nextnode (node))
1077 {
1078 ifp = getdata (node);
1079 rip_enable_apply (ifp);
1080 }
1081}
1082
1083int
1084rip_neighbor_lookup (struct sockaddr_in *from)
1085{
1086 struct prefix_ipv4 p;
1087 struct route_node *node;
1088
1089 memset (&p, 0, sizeof (struct prefix_ipv4));
1090 p.family = AF_INET;
1091 p.prefix = from->sin_addr;
1092 p.prefixlen = IPV4_MAX_BITLEN;
1093
1094 node = route_node_lookup (rip->neighbor, (struct prefix *) &p);
1095 if (node)
1096 {
1097 route_unlock_node (node);
1098 return 1;
1099 }
1100 return 0;
1101}
1102
1103/* Add new RIP neighbor to the neighbor tree. */
1104int
1105rip_neighbor_add (struct prefix_ipv4 *p)
1106{
1107 struct route_node *node;
1108
1109 node = route_node_get (rip->neighbor, (struct prefix *) p);
1110
1111 if (node->info)
1112 return -1;
1113
1114 node->info = rip->neighbor;
1115
1116 return 0;
1117}
1118
1119/* Delete RIP neighbor from the neighbor tree. */
1120int
1121rip_neighbor_delete (struct prefix_ipv4 *p)
1122{
1123 struct route_node *node;
1124
1125 /* Lock for look up. */
1126 node = route_node_lookup (rip->neighbor, (struct prefix *) p);
1127 if (! node)
1128 return -1;
1129
1130 node->info = NULL;
1131
1132 /* Unlock lookup lock. */
1133 route_unlock_node (node);
1134
1135 /* Unlock real neighbor information lock. */
1136 route_unlock_node (node);
1137
1138 return 0;
1139}
1140
1141/* Clear all network and neighbor configuration. */
1142void
1143rip_clean_network ()
1144{
1145 int i;
1146 char *str;
1147 struct route_node *rn;
1148
1149 /* rip_enable_network. */
1150 for (rn = route_top (rip_enable_network); rn; rn = route_next (rn))
1151 if (rn->info)
1152 {
1153 rn->info = NULL;
1154 route_unlock_node (rn);
1155 }
1156
1157 /* rip_enable_interface. */
1158 for (i = 0; i < vector_max (rip_enable_interface); i++)
1159 if ((str = vector_slot (rip_enable_interface, i)) != NULL)
1160 {
1161 free (str);
1162 vector_slot (rip_enable_interface, i) = NULL;
1163 }
1164}
1165
1166/* Utility function for looking up passive interface settings. */
1167int
paul4aaff3f2003-06-07 01:04:45 +00001168rip_passive_nondefault_lookup (char *ifname)
paul718e3742002-12-13 20:15:29 +00001169{
1170 int i;
1171 char *str;
1172
paul4aaff3f2003-06-07 01:04:45 +00001173 for (i = 0; i < vector_max (Vrip_passive_nondefault); i++)
1174 if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL)
paul718e3742002-12-13 20:15:29 +00001175 if (strcmp (str, ifname) == 0)
1176 return i;
1177 return -1;
1178}
1179
1180void
1181rip_passive_interface_apply (struct interface *ifp)
1182{
paul718e3742002-12-13 20:15:29 +00001183 struct rip_interface *ri;
1184
1185 ri = ifp->info;
1186
paul4aaff3f2003-06-07 01:04:45 +00001187 ri->passive = ((rip_passive_nondefault_lookup (ifp->name) < 0) ?
1188 passive_default : !passive_default);
1189
1190 if (IS_RIP_DEBUG_ZEBRA)
1191 zlog_info ("interface %s: passive = %d",ifp->name,ri->passive);
paul718e3742002-12-13 20:15:29 +00001192}
1193
1194void
1195rip_passive_interface_apply_all ()
1196{
1197 struct interface *ifp;
1198 listnode node;
1199
1200 for (node = listhead (iflist); node; nextnode (node))
1201 {
1202 ifp = getdata (node);
1203 rip_passive_interface_apply (ifp);
1204 }
1205}
1206
1207/* Passive interface. */
1208int
paul4aaff3f2003-06-07 01:04:45 +00001209rip_passive_nondefault_set (struct vty *vty, char *ifname)
paul718e3742002-12-13 20:15:29 +00001210{
paul4aaff3f2003-06-07 01:04:45 +00001211 if (rip_passive_nondefault_lookup (ifname) >= 0)
paul718e3742002-12-13 20:15:29 +00001212 return CMD_WARNING;
1213
paul4aaff3f2003-06-07 01:04:45 +00001214 vector_set (Vrip_passive_nondefault, strdup (ifname));
paul718e3742002-12-13 20:15:29 +00001215
1216 rip_passive_interface_apply_all ();
1217
1218 return CMD_SUCCESS;
1219}
1220
1221int
paul4aaff3f2003-06-07 01:04:45 +00001222rip_passive_nondefault_unset (struct vty *vty, char *ifname)
paul718e3742002-12-13 20:15:29 +00001223{
1224 int i;
1225 char *str;
1226
paul4aaff3f2003-06-07 01:04:45 +00001227 i = rip_passive_nondefault_lookup (ifname);
paul718e3742002-12-13 20:15:29 +00001228 if (i < 0)
1229 return CMD_WARNING;
1230
paul4aaff3f2003-06-07 01:04:45 +00001231 str = vector_slot (Vrip_passive_nondefault, i);
paul718e3742002-12-13 20:15:29 +00001232 free (str);
paul4aaff3f2003-06-07 01:04:45 +00001233 vector_unset (Vrip_passive_nondefault, i);
paul718e3742002-12-13 20:15:29 +00001234
1235 rip_passive_interface_apply_all ();
1236
1237 return CMD_SUCCESS;
1238}
1239
1240/* Free all configured RIP passive-interface settings. */
1241void
paul4aaff3f2003-06-07 01:04:45 +00001242rip_passive_nondefault_clean ()
paul718e3742002-12-13 20:15:29 +00001243{
1244 int i;
1245 char *str;
1246
paul4aaff3f2003-06-07 01:04:45 +00001247 for (i = 0; i < vector_max (Vrip_passive_nondefault); i++)
1248 if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL)
paul718e3742002-12-13 20:15:29 +00001249 {
1250 free (str);
paul4aaff3f2003-06-07 01:04:45 +00001251 vector_slot (Vrip_passive_nondefault, i) = NULL;
paul718e3742002-12-13 20:15:29 +00001252 }
1253 rip_passive_interface_apply_all ();
1254}
1255
1256/* RIP enable network or interface configuration. */
1257DEFUN (rip_network,
1258 rip_network_cmd,
1259 "network (A.B.C.D/M|WORD)",
1260 "Enable routing on an IP network\n"
1261 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1262 "Interface name\n")
1263{
1264 int ret;
1265 struct prefix_ipv4 p;
1266
1267 ret = str2prefix_ipv4 (argv[0], &p);
1268
1269 if (ret)
1270 ret = rip_enable_network_add ((struct prefix *) &p);
1271 else
1272 ret = rip_enable_if_add (argv[0]);
1273
1274 if (ret < 0)
1275 {
1276 vty_out (vty, "There is a same network configuration %s%s", argv[0],
1277 VTY_NEWLINE);
1278 return CMD_WARNING;
1279 }
1280
paul718e3742002-12-13 20:15:29 +00001281 return CMD_SUCCESS;
1282}
1283
1284/* RIP enable network or interface configuration. */
1285DEFUN (no_rip_network,
1286 no_rip_network_cmd,
1287 "no network (A.B.C.D/M|WORD)",
1288 NO_STR
1289 "Enable routing on an IP network\n"
1290 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1291 "Interface name\n")
1292{
1293 int ret;
1294 struct prefix_ipv4 p;
1295
1296 ret = str2prefix_ipv4 (argv[0], &p);
1297
1298 if (ret)
1299 ret = rip_enable_network_delete ((struct prefix *) &p);
1300 else
1301 ret = rip_enable_if_delete (argv[0]);
1302
1303 if (ret < 0)
1304 {
1305 vty_out (vty, "Can't find network configuration %s%s", argv[0],
1306 VTY_NEWLINE);
1307 return CMD_WARNING;
1308 }
1309
paul718e3742002-12-13 20:15:29 +00001310 return CMD_SUCCESS;
1311}
1312
1313/* RIP neighbor configuration set. */
1314DEFUN (rip_neighbor,
1315 rip_neighbor_cmd,
1316 "neighbor A.B.C.D",
1317 "Specify a neighbor router\n"
1318 "Neighbor address\n")
1319{
1320 int ret;
1321 struct prefix_ipv4 p;
1322
1323 ret = str2prefix_ipv4 (argv[0], &p);
1324
1325 if (ret <= 0)
1326 {
1327 vty_out (vty, "Please specify address by A.B.C.D%s", VTY_NEWLINE);
1328 return CMD_WARNING;
1329 }
1330
1331 rip_neighbor_add (&p);
1332
1333 return CMD_SUCCESS;
1334}
1335
1336/* RIP neighbor configuration unset. */
1337DEFUN (no_rip_neighbor,
1338 no_rip_neighbor_cmd,
1339 "no neighbor A.B.C.D",
1340 NO_STR
1341 "Specify a neighbor router\n"
1342 "Neighbor address\n")
1343{
1344 int ret;
1345 struct prefix_ipv4 p;
1346
1347 ret = str2prefix_ipv4 (argv[0], &p);
1348
1349 if (ret <= 0)
1350 {
1351 vty_out (vty, "Please specify address by A.B.C.D%s", VTY_NEWLINE);
1352 return CMD_WARNING;
1353 }
1354
1355 rip_neighbor_delete (&p);
1356
1357 return CMD_SUCCESS;
1358}
1359
1360DEFUN (ip_rip_receive_version,
1361 ip_rip_receive_version_cmd,
1362 "ip rip receive version (1|2)",
1363 IP_STR
1364 "Routing Information Protocol\n"
1365 "Advertisement reception\n"
1366 "Version control\n"
1367 "RIP version 1\n"
1368 "RIP version 2\n")
1369{
1370 struct interface *ifp;
1371 struct rip_interface *ri;
1372
1373 ifp = (struct interface *)vty->index;
1374 ri = ifp->info;
1375
1376 /* Version 1. */
1377 if (atoi (argv[0]) == 1)
1378 {
1379 ri->ri_receive = RI_RIP_VERSION_1;
1380 return CMD_SUCCESS;
1381 }
1382 if (atoi (argv[0]) == 2)
1383 {
1384 ri->ri_receive = RI_RIP_VERSION_2;
1385 return CMD_SUCCESS;
1386 }
1387 return CMD_WARNING;
1388}
1389
1390DEFUN (ip_rip_receive_version_1,
1391 ip_rip_receive_version_1_cmd,
1392 "ip rip receive version 1 2",
1393 IP_STR
1394 "Routing Information Protocol\n"
1395 "Advertisement reception\n"
1396 "Version control\n"
1397 "RIP version 1\n"
1398 "RIP version 2\n")
1399{
1400 struct interface *ifp;
1401 struct rip_interface *ri;
1402
1403 ifp = (struct interface *)vty->index;
1404 ri = ifp->info;
1405
1406 /* Version 1 and 2. */
1407 ri->ri_receive = RI_RIP_VERSION_1_AND_2;
1408 return CMD_SUCCESS;
1409}
1410
1411DEFUN (ip_rip_receive_version_2,
1412 ip_rip_receive_version_2_cmd,
1413 "ip rip receive version 2 1",
1414 IP_STR
1415 "Routing Information Protocol\n"
1416 "Advertisement reception\n"
1417 "Version control\n"
1418 "RIP version 2\n"
1419 "RIP version 1\n")
1420{
1421 struct interface *ifp;
1422 struct rip_interface *ri;
1423
1424 ifp = (struct interface *)vty->index;
1425 ri = ifp->info;
1426
1427 /* Version 1 and 2. */
1428 ri->ri_receive = RI_RIP_VERSION_1_AND_2;
1429 return CMD_SUCCESS;
1430}
1431
1432DEFUN (no_ip_rip_receive_version,
1433 no_ip_rip_receive_version_cmd,
1434 "no ip rip receive version",
1435 NO_STR
1436 IP_STR
1437 "Routing Information Protocol\n"
1438 "Advertisement reception\n"
1439 "Version control\n")
1440{
1441 struct interface *ifp;
1442 struct rip_interface *ri;
1443
1444 ifp = (struct interface *)vty->index;
1445 ri = ifp->info;
1446
1447 ri->ri_receive = RI_RIP_UNSPEC;
1448 return CMD_SUCCESS;
1449}
1450
1451ALIAS (no_ip_rip_receive_version,
1452 no_ip_rip_receive_version_num_cmd,
1453 "no ip rip receive version (1|2)",
1454 NO_STR
1455 IP_STR
1456 "Routing Information Protocol\n"
1457 "Advertisement reception\n"
1458 "Version control\n"
1459 "Version 1\n"
1460 "Version 2\n")
1461
1462DEFUN (ip_rip_send_version,
1463 ip_rip_send_version_cmd,
1464 "ip rip send version (1|2)",
1465 IP_STR
1466 "Routing Information Protocol\n"
1467 "Advertisement transmission\n"
1468 "Version control\n"
1469 "RIP version 1\n"
1470 "RIP version 2\n")
1471{
1472 struct interface *ifp;
1473 struct rip_interface *ri;
1474
1475 ifp = (struct interface *)vty->index;
1476 ri = ifp->info;
1477
1478 /* Version 1. */
1479 if (atoi (argv[0]) == 1)
1480 {
1481 ri->ri_send = RI_RIP_VERSION_1;
1482 return CMD_SUCCESS;
1483 }
1484 if (atoi (argv[0]) == 2)
1485 {
1486 ri->ri_send = RI_RIP_VERSION_2;
1487 return CMD_SUCCESS;
1488 }
1489 return CMD_WARNING;
1490}
1491
1492DEFUN (ip_rip_send_version_1,
1493 ip_rip_send_version_1_cmd,
1494 "ip rip send version 1 2",
1495 IP_STR
1496 "Routing Information Protocol\n"
1497 "Advertisement transmission\n"
1498 "Version control\n"
1499 "RIP version 1\n"
1500 "RIP version 2\n")
1501{
1502 struct interface *ifp;
1503 struct rip_interface *ri;
1504
1505 ifp = (struct interface *)vty->index;
1506 ri = ifp->info;
1507
1508 /* Version 1 and 2. */
1509 ri->ri_send = RI_RIP_VERSION_1_AND_2;
1510 return CMD_SUCCESS;
1511}
1512
1513DEFUN (ip_rip_send_version_2,
1514 ip_rip_send_version_2_cmd,
1515 "ip rip send version 2 1",
1516 IP_STR
1517 "Routing Information Protocol\n"
1518 "Advertisement transmission\n"
1519 "Version control\n"
1520 "RIP version 2\n"
1521 "RIP version 1\n")
1522{
1523 struct interface *ifp;
1524 struct rip_interface *ri;
1525
1526 ifp = (struct interface *)vty->index;
1527 ri = ifp->info;
1528
1529 /* Version 1 and 2. */
1530 ri->ri_send = RI_RIP_VERSION_1_AND_2;
1531 return CMD_SUCCESS;
1532}
1533
1534DEFUN (no_ip_rip_send_version,
1535 no_ip_rip_send_version_cmd,
1536 "no ip rip send version",
1537 NO_STR
1538 IP_STR
1539 "Routing Information Protocol\n"
1540 "Advertisement transmission\n"
1541 "Version control\n")
1542{
1543 struct interface *ifp;
1544 struct rip_interface *ri;
1545
1546 ifp = (struct interface *)vty->index;
1547 ri = ifp->info;
1548
1549 ri->ri_send = RI_RIP_UNSPEC;
1550 return CMD_SUCCESS;
1551}
1552
1553ALIAS (no_ip_rip_send_version,
1554 no_ip_rip_send_version_num_cmd,
1555 "no ip rip send version (1|2)",
1556 NO_STR
1557 IP_STR
1558 "Routing Information Protocol\n"
1559 "Advertisement transmission\n"
1560 "Version control\n"
1561 "Version 1\n"
1562 "Version 2\n")
1563
1564DEFUN (ip_rip_authentication_mode,
1565 ip_rip_authentication_mode_cmd,
1566 "ip rip authentication mode (md5|text)",
1567 IP_STR
1568 "Routing Information Protocol\n"
1569 "Authentication control\n"
1570 "Authentication mode\n"
1571 "Keyed message digest\n"
1572 "Clear text authentication\n")
1573{
1574 struct interface *ifp;
1575 struct rip_interface *ri;
1576
1577 ifp = (struct interface *)vty->index;
1578 ri = ifp->info;
1579
1580 if (strncmp ("md5", argv[0], strlen (argv[0])) == 0)
1581 ri->auth_type = RIP_AUTH_MD5;
1582 else if (strncmp ("text", argv[0], strlen (argv[0])) == 0)
1583 ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;
1584 else
1585 {
1586 vty_out (vty, "mode should be md5 or text%s", VTY_NEWLINE);
1587 return CMD_WARNING;
1588 }
1589
1590 return CMD_SUCCESS;
1591}
1592
1593DEFUN (no_ip_rip_authentication_mode,
1594 no_ip_rip_authentication_mode_cmd,
1595 "no ip rip authentication mode",
1596 NO_STR
1597 IP_STR
1598 "Routing Information Protocol\n"
1599 "Authentication control\n"
1600 "Authentication mode\n")
1601{
1602 struct interface *ifp;
1603 struct rip_interface *ri;
1604
1605 ifp = (struct interface *)vty->index;
1606 ri = ifp->info;
1607
1608 /* ri->auth_type = RIP_NO_AUTH; */
1609 ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;
1610
1611 return CMD_SUCCESS;
1612}
1613
1614ALIAS (no_ip_rip_authentication_mode,
1615 no_ip_rip_authentication_mode_type_cmd,
1616 "no ip rip authentication mode (md5|text)",
1617 NO_STR
1618 IP_STR
1619 "Routing Information Protocol\n"
1620 "Authentication control\n"
1621 "Authentication mode\n"
1622 "Keyed message digest\n"
1623 "Clear text authentication\n")
1624
1625DEFUN (ip_rip_authentication_string,
1626 ip_rip_authentication_string_cmd,
1627 "ip rip authentication string LINE",
1628 IP_STR
1629 "Routing Information Protocol\n"
1630 "Authentication control\n"
1631 "Authentication string\n"
1632 "Authentication string\n")
1633{
1634 struct interface *ifp;
1635 struct rip_interface *ri;
1636
1637 ifp = (struct interface *)vty->index;
1638 ri = ifp->info;
1639
1640 if (strlen (argv[0]) > 16)
1641 {
1642 vty_out (vty, "%% RIPv2 authentication string must be shorter than 16%s",
1643 VTY_NEWLINE);
1644 return CMD_WARNING;
1645 }
1646
1647 if (ri->key_chain)
1648 {
1649 vty_out (vty, "%% key-chain configuration exists%s", VTY_NEWLINE);
1650 return CMD_WARNING;
1651 }
1652
1653 if (ri->auth_str)
1654 free (ri->auth_str);
1655
1656 ri->auth_str = strdup (argv[0]);
1657
1658 return CMD_SUCCESS;
1659}
1660
1661DEFUN (no_ip_rip_authentication_string,
1662 no_ip_rip_authentication_string_cmd,
1663 "no ip rip authentication string",
1664 NO_STR
1665 IP_STR
1666 "Routing Information Protocol\n"
1667 "Authentication control\n"
1668 "Authentication string\n")
1669{
1670 struct interface *ifp;
1671 struct rip_interface *ri;
1672
1673 ifp = (struct interface *)vty->index;
1674 ri = ifp->info;
1675
1676 if (ri->auth_str)
1677 free (ri->auth_str);
1678
1679 ri->auth_str = NULL;
1680
1681 return CMD_SUCCESS;
1682}
1683
1684ALIAS (no_ip_rip_authentication_string,
1685 no_ip_rip_authentication_string2_cmd,
1686 "no ip rip authentication string LINE",
1687 NO_STR
1688 IP_STR
1689 "Routing Information Protocol\n"
1690 "Authentication control\n"
1691 "Authentication string\n"
1692 "Authentication string\n")
1693
1694DEFUN (ip_rip_authentication_key_chain,
1695 ip_rip_authentication_key_chain_cmd,
1696 "ip rip authentication key-chain LINE",
1697 IP_STR
1698 "Routing Information Protocol\n"
1699 "Authentication control\n"
1700 "Authentication key-chain\n"
1701 "name of key-chain\n")
1702{
1703 struct interface *ifp;
1704 struct rip_interface *ri;
1705
1706 ifp = (struct interface *) vty->index;
1707 ri = ifp->info;
1708
1709 if (ri->auth_str)
1710 {
1711 vty_out (vty, "%% authentication string configuration exists%s",
1712 VTY_NEWLINE);
1713 return CMD_WARNING;
1714 }
1715
1716 if (ri->key_chain)
1717 free (ri->key_chain);
1718
1719 ri->key_chain = strdup (argv[0]);
1720
1721 return CMD_SUCCESS;
1722}
1723
1724DEFUN (no_ip_rip_authentication_key_chain,
1725 no_ip_rip_authentication_key_chain_cmd,
1726 "no ip rip authentication key-chain",
1727 NO_STR
1728 IP_STR
1729 "Routing Information Protocol\n"
1730 "Authentication control\n"
1731 "Authentication key-chain\n")
1732{
1733 struct interface *ifp;
1734 struct rip_interface *ri;
1735
1736 ifp = (struct interface *) vty->index;
1737 ri = ifp->info;
1738
1739 if (ri->key_chain)
1740 free (ri->key_chain);
1741
1742 ri->key_chain = NULL;
1743
1744 return CMD_SUCCESS;
1745}
1746
1747ALIAS (no_ip_rip_authentication_key_chain,
1748 no_ip_rip_authentication_key_chain2_cmd,
1749 "no ip rip authentication key-chain LINE",
1750 NO_STR
1751 IP_STR
1752 "Routing Information Protocol\n"
1753 "Authentication control\n"
1754 "Authentication key-chain\n"
1755 "name of key-chain\n")
1756
hasso16705132003-05-25 14:49:19 +00001757/* CHANGED: ip rip split-horizon
1758 Cisco and Zebra's command is
1759 ip split-horizon
1760 */
1761DEFUN (ip_rip_split_horizon,
1762 ip_rip_split_horizon_cmd,
1763 "ip rip split-horizon",
paul718e3742002-12-13 20:15:29 +00001764 IP_STR
hasso16705132003-05-25 14:49:19 +00001765 "Routing Information Protocol\n"
paul718e3742002-12-13 20:15:29 +00001766 "Perform split horizon\n")
1767{
1768 struct interface *ifp;
1769 struct rip_interface *ri;
1770
1771 ifp = vty->index;
1772 ri = ifp->info;
1773
hasso16705132003-05-25 14:49:19 +00001774 ri->split_horizon = RIP_SPLIT_HORIZON;
paul718e3742002-12-13 20:15:29 +00001775 return CMD_SUCCESS;
1776}
1777
hasso16705132003-05-25 14:49:19 +00001778DEFUN (ip_rip_split_horizon_poisoned_reverse,
1779 ip_rip_split_horizon_poisoned_reverse_cmd,
1780 "ip rip split-horizon poisoned-reverse",
1781 IP_STR
1782 "Routing Information Protocol\n"
1783 "Perform split horizon\n"
1784 "With poisoned-reverse\n")
1785{
1786 struct interface *ifp;
1787 struct rip_interface *ri;
1788
1789 ifp = vty->index;
1790 ri = ifp->info;
1791
1792 ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE;
1793 return CMD_SUCCESS;
1794}
1795
1796/* CHANGED: no ip rip split-horizon
1797 Cisco and Zebra's command is
1798 no ip split-horizon
1799 */
1800DEFUN (no_ip_rip_split_horizon,
1801 no_ip_rip_split_horizon_cmd,
1802 "no ip rip split-horizon",
paul718e3742002-12-13 20:15:29 +00001803 NO_STR
1804 IP_STR
hasso16705132003-05-25 14:49:19 +00001805 "Routing Information Protocol\n"
paul718e3742002-12-13 20:15:29 +00001806 "Perform split horizon\n")
1807{
1808 struct interface *ifp;
1809 struct rip_interface *ri;
1810
1811 ifp = vty->index;
1812 ri = ifp->info;
1813
hasso16705132003-05-25 14:49:19 +00001814 ri->split_horizon = RIP_NO_SPLIT_HORIZON;
paul718e3742002-12-13 20:15:29 +00001815 return CMD_SUCCESS;
1816}
1817
hasso16705132003-05-25 14:49:19 +00001818ALIAS (no_ip_rip_split_horizon,
1819 no_ip_rip_split_horizon_poisoned_reverse_cmd,
1820 "no ip rip split-horizon poisoned-reverse",
1821 NO_STR
1822 IP_STR
1823 "Routing Information Protocol\n"
1824 "Perform split horizon\n"
1825 "With poisoned-reverse\n")
1826
paul718e3742002-12-13 20:15:29 +00001827DEFUN (rip_passive_interface,
1828 rip_passive_interface_cmd,
paul56e475c2003-06-20 00:23:27 +00001829 "passive-interface (IFNAME|default)",
paul718e3742002-12-13 20:15:29 +00001830 "Suppress routing updates on an interface\n"
paul56e475c2003-06-20 00:23:27 +00001831 "Interface name\n"
1832 "default for all interfaces\n")
paul718e3742002-12-13 20:15:29 +00001833{
paul4aaff3f2003-06-07 01:04:45 +00001834 char *ifname = argv[0];
1835
1836 if (!strcmp(ifname,"default")) {
1837 passive_default = 1;
1838 rip_passive_nondefault_clean();
1839 return CMD_SUCCESS;
1840 }
1841 if (passive_default)
1842 return rip_passive_nondefault_unset (vty, ifname);
1843 else
1844 return rip_passive_nondefault_set (vty, ifname);
paul718e3742002-12-13 20:15:29 +00001845}
1846
1847DEFUN (no_rip_passive_interface,
1848 no_rip_passive_interface_cmd,
paul56e475c2003-06-20 00:23:27 +00001849 "no passive-interface (IFNAME|default)",
paul718e3742002-12-13 20:15:29 +00001850 NO_STR
1851 "Suppress routing updates on an interface\n"
paul56e475c2003-06-20 00:23:27 +00001852 "Interface name\n"
1853 "default for all interfaces\n")
paul718e3742002-12-13 20:15:29 +00001854{
paul4aaff3f2003-06-07 01:04:45 +00001855 char *ifname = argv[0];
1856
1857 if (!strcmp(ifname,"default")) {
1858 passive_default = 0;
1859 rip_passive_nondefault_clean();
1860 return CMD_SUCCESS;
1861 }
1862 if (passive_default)
1863 return rip_passive_nondefault_set (vty, ifname);
1864 else
1865 return rip_passive_nondefault_unset (vty, ifname);
paul718e3742002-12-13 20:15:29 +00001866}
1867
1868/* Write rip configuration of each interface. */
1869int
1870rip_interface_config_write (struct vty *vty)
1871{
1872 listnode node;
1873 struct interface *ifp;
1874
1875 for (node = listhead (iflist); node; nextnode (node))
1876 {
1877 struct rip_interface *ri;
1878
1879 ifp = getdata (node);
1880 ri = ifp->info;
1881
hasso16705132003-05-25 14:49:19 +00001882 /* Do not display the interface if there is no
1883 * configuration about it.
1884 **/
1885 if ((!ifp->desc) &&
1886 (ri->split_horizon == ri->split_horizon_default) &&
1887 (ri->ri_send == RI_RIP_UNSPEC) &&
1888 (ri->ri_receive == RI_RIP_UNSPEC) &&
1889 (ri->auth_type != RIP_AUTH_MD5) &&
1890 (!ri->auth_str) &&
1891 (!ri->key_chain) )
1892 continue;
1893
paul718e3742002-12-13 20:15:29 +00001894 vty_out (vty, "interface %s%s", ifp->name,
1895 VTY_NEWLINE);
1896
1897 if (ifp->desc)
1898 vty_out (vty, " description %s%s", ifp->desc,
1899 VTY_NEWLINE);
1900
1901 /* Split horizon. */
1902 if (ri->split_horizon != ri->split_horizon_default)
1903 {
hasso16705132003-05-25 14:49:19 +00001904 switch (ri->split_horizon) {
1905 case RIP_SPLIT_HORIZON:
1906 vty_out (vty, " ip rip split-horizon%s", VTY_NEWLINE);
1907 break;
1908 case RIP_SPLIT_HORIZON_POISONED_REVERSE:
1909 vty_out (vty, " ip rip split-horizon poisoned-reverse%s",
1910 VTY_NEWLINE);
1911 break;
1912 case RIP_NO_SPLIT_HORIZON:
1913 default:
1914 vty_out (vty, " no ip rip split-horizon%s", VTY_NEWLINE);
1915 break;
1916 }
paul718e3742002-12-13 20:15:29 +00001917 }
1918
1919 /* RIP version setting. */
1920 if (ri->ri_send != RI_RIP_UNSPEC)
1921 vty_out (vty, " ip rip send version %s%s",
1922 lookup (ri_version_msg, ri->ri_send),
1923 VTY_NEWLINE);
1924
1925 if (ri->ri_receive != RI_RIP_UNSPEC)
1926 vty_out (vty, " ip rip receive version %s%s",
1927 lookup (ri_version_msg, ri->ri_receive),
1928 VTY_NEWLINE);
1929
1930 /* RIP authentication. */
1931#if 0
1932 /* RIP_AUTH_SIMPLE_PASSWORD becomes default mode. */
1933 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
1934 vty_out (vty, " ip rip authentication mode text%s", VTY_NEWLINE);
1935#endif /* 0 */
1936 if (ri->auth_type == RIP_AUTH_MD5)
1937 vty_out (vty, " ip rip authentication mode md5%s", VTY_NEWLINE);
1938
1939 if (ri->auth_str)
1940 vty_out (vty, " ip rip authentication string %s%s",
1941 ri->auth_str, VTY_NEWLINE);
1942
1943 if (ri->key_chain)
1944 vty_out (vty, " ip rip authentication key-chain %s%s",
1945 ri->key_chain, VTY_NEWLINE);
1946
1947 vty_out (vty, "!%s", VTY_NEWLINE);
1948 }
1949 return 0;
1950}
1951
1952int
1953config_write_rip_network (struct vty *vty, int config_mode)
1954{
1955 int i;
1956 char *ifname;
1957 struct route_node *node;
1958
1959 /* Network type RIP enable interface statement. */
1960 for (node = route_top (rip_enable_network); node; node = route_next (node))
1961 if (node->info)
1962 vty_out (vty, "%s%s/%d%s",
1963 config_mode ? " network " : " ",
1964 inet_ntoa (node->p.u.prefix4),
1965 node->p.prefixlen,
1966 VTY_NEWLINE);
1967
1968 /* Interface name RIP enable statement. */
1969 for (i = 0; i < vector_max (rip_enable_interface); i++)
1970 if ((ifname = vector_slot (rip_enable_interface, i)) != NULL)
1971 vty_out (vty, "%s%s%s",
1972 config_mode ? " network " : " ",
1973 ifname,
1974 VTY_NEWLINE);
1975
1976 /* RIP neighbors listing. */
1977 for (node = route_top (rip->neighbor); node; node = route_next (node))
1978 if (node->info)
1979 vty_out (vty, "%s%s%s",
1980 config_mode ? " neighbor " : " ",
1981 inet_ntoa (node->p.u.prefix4),
1982 VTY_NEWLINE);
1983
1984 /* RIP passive interface listing. */
paul4aaff3f2003-06-07 01:04:45 +00001985 if (config_mode) {
1986 if (passive_default)
paul01d09082003-06-08 21:22:18 +00001987 vty_out (vty, " passive-interface default%s", VTY_NEWLINE);
paul4aaff3f2003-06-07 01:04:45 +00001988 for (i = 0; i < vector_max (Vrip_passive_nondefault); i++)
1989 if ((ifname = vector_slot (Vrip_passive_nondefault, i)) != NULL)
1990 vty_out (vty, " %spassive-interface %s%s",
1991 (passive_default ? "no " : ""), ifname, VTY_NEWLINE);
1992 }
paul718e3742002-12-13 20:15:29 +00001993
1994 return 0;
1995}
1996
1997struct cmd_node interface_node =
1998{
1999 INTERFACE_NODE,
2000 "%s(config-if)# ",
2001 1,
2002};
2003
2004/* Called when interface structure allocated. */
2005int
2006rip_interface_new_hook (struct interface *ifp)
2007{
2008 ifp->info = rip_interface_new ();
2009 return 0;
2010}
2011
2012/* Called when interface structure deleted. */
2013int
2014rip_interface_delete_hook (struct interface *ifp)
2015{
2016 XFREE (MTYPE_RIP_INTERFACE, ifp->info);
hasso16705132003-05-25 14:49:19 +00002017 ifp->info = NULL;
paul718e3742002-12-13 20:15:29 +00002018 return 0;
2019}
2020
2021/* Allocate and initialize interface vector. */
2022void
2023rip_if_init ()
2024{
2025 /* Default initial size of interface vector. */
2026 if_init();
2027 if_add_hook (IF_NEW_HOOK, rip_interface_new_hook);
2028 if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook);
2029
2030 /* RIP network init. */
2031 rip_enable_interface = vector_init (1);
2032 rip_enable_network = route_table_init ();
2033
2034 /* RIP passive interface. */
paul4aaff3f2003-06-07 01:04:45 +00002035 Vrip_passive_nondefault = vector_init (1);
paul718e3742002-12-13 20:15:29 +00002036
2037 /* Install interface node. */
2038 install_node (&interface_node, rip_interface_config_write);
2039
2040 /* Install commands. */
2041 install_element (CONFIG_NODE, &interface_cmd);
hasso034489d2003-05-24 07:59:25 +00002042 install_element (CONFIG_NODE, &no_interface_cmd);
paul718e3742002-12-13 20:15:29 +00002043 install_default (INTERFACE_NODE);
2044 install_element (INTERFACE_NODE, &interface_desc_cmd);
2045 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
2046 install_element (RIP_NODE, &rip_network_cmd);
2047 install_element (RIP_NODE, &no_rip_network_cmd);
2048 install_element (RIP_NODE, &rip_neighbor_cmd);
2049 install_element (RIP_NODE, &no_rip_neighbor_cmd);
2050
2051 install_element (RIP_NODE, &rip_passive_interface_cmd);
2052 install_element (RIP_NODE, &no_rip_passive_interface_cmd);
2053
2054 install_element (INTERFACE_NODE, &ip_rip_send_version_cmd);
2055 install_element (INTERFACE_NODE, &ip_rip_send_version_1_cmd);
2056 install_element (INTERFACE_NODE, &ip_rip_send_version_2_cmd);
2057 install_element (INTERFACE_NODE, &no_ip_rip_send_version_cmd);
2058 install_element (INTERFACE_NODE, &no_ip_rip_send_version_num_cmd);
2059
2060 install_element (INTERFACE_NODE, &ip_rip_receive_version_cmd);
2061 install_element (INTERFACE_NODE, &ip_rip_receive_version_1_cmd);
2062 install_element (INTERFACE_NODE, &ip_rip_receive_version_2_cmd);
2063 install_element (INTERFACE_NODE, &no_ip_rip_receive_version_cmd);
2064 install_element (INTERFACE_NODE, &no_ip_rip_receive_version_num_cmd);
2065
2066 install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd);
2067 install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd);
2068 install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_type_cmd);
2069
2070 install_element (INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd);
2071 install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain_cmd);
2072 install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain2_cmd);
2073
2074 install_element (INTERFACE_NODE, &ip_rip_authentication_string_cmd);
2075 install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd);
2076 install_element (INTERFACE_NODE, &no_ip_rip_authentication_string2_cmd);
2077
hasso16705132003-05-25 14:49:19 +00002078 install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd);
2079 install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd);
2080 install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd);
2081 install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd);
paul718e3742002-12-13 20:15:29 +00002082}