Annotation of embedaddon/quagga/ripd/ripd.c, revision 1.1.1.1
1.1 misho 1: /* RIP version 1 and 2.
2: * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
3: * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
4: *
5: * This file is part of GNU Zebra.
6: *
7: * GNU Zebra is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2, or (at your option) any
10: * later version.
11: *
12: * GNU Zebra is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with GNU Zebra; see the file COPYING. If not, write to the Free
19: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20: * 02111-1307, USA.
21: */
22:
23: #include <zebra.h>
24:
25: #include "if.h"
26: #include "command.h"
27: #include "prefix.h"
28: #include "table.h"
29: #include "thread.h"
30: #include "memory.h"
31: #include "log.h"
32: #include "stream.h"
33: #include "filter.h"
34: #include "sockunion.h"
35: #include "sockopt.h"
36: #include "routemap.h"
37: #include "if_rmap.h"
38: #include "plist.h"
39: #include "distribute.h"
40: #include "md5.h"
41: #include "keychain.h"
42: #include "privs.h"
43:
44: #include "ripd/ripd.h"
45: #include "ripd/rip_debug.h"
46:
47: /* UDP receive buffer size */
48: #define RIP_UDP_RCV_BUF 41600
49:
50: /* privileges global */
51: extern struct zebra_privs_t ripd_privs;
52:
53: /* RIP Structure. */
54: struct rip *rip = NULL;
55:
56: /* RIP neighbor address table. */
57: struct route_table *rip_neighbor_table;
58:
59: /* RIP route changes. */
60: long rip_global_route_changes = 0;
61:
62: /* RIP queries. */
63: long rip_global_queries = 0;
64:
65: /* Prototypes. */
66: static void rip_event (enum rip_event, int);
67: static void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
68: static int rip_triggered_update (struct thread *);
69: static int rip_update_jitter (unsigned long);
70:
71: /* RIP output routes type. */
72: enum
73: {
74: rip_all_route,
75: rip_changed_route
76: };
77:
78: /* RIP command strings. */
79: static const struct message rip_msg[] =
80: {
81: {RIP_REQUEST, "REQUEST"},
82: {RIP_RESPONSE, "RESPONSE"},
83: {RIP_TRACEON, "TRACEON"},
84: {RIP_TRACEOFF, "TRACEOFF"},
85: {RIP_POLL, "POLL"},
86: {RIP_POLL_ENTRY, "POLL ENTRY"},
87: {0, NULL},
88: };
89:
90: /* Utility function to set boradcast option to the socket. */
91: static int
92: sockopt_broadcast (int sock)
93: {
94: int ret;
95: int on = 1;
96:
97: ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
98: if (ret < 0)
99: {
100: zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
101: return -1;
102: }
103: return 0;
104: }
105:
106: static int
107: rip_route_rte (struct rip_info *rinfo)
108: {
109: return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
110: }
111:
112: static struct rip_info *
113: rip_info_new (void)
114: {
115: return XCALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
116: }
117:
118: void
119: rip_info_free (struct rip_info *rinfo)
120: {
121: XFREE (MTYPE_RIP_INFO, rinfo);
122: }
123:
124: /* RIP route garbage collect timer. */
125: static int
126: rip_garbage_collect (struct thread *t)
127: {
128: struct rip_info *rinfo;
129: struct route_node *rp;
130:
131: rinfo = THREAD_ARG (t);
132: rinfo->t_garbage_collect = NULL;
133:
134: /* Off timeout timer. */
135: RIP_TIMER_OFF (rinfo->t_timeout);
136:
137: /* Get route_node pointer. */
138: rp = rinfo->rp;
139:
140: /* Unlock route_node. */
141: rp->info = NULL;
142: route_unlock_node (rp);
143:
144: /* Free RIP routing information. */
145: rip_info_free (rinfo);
146:
147: return 0;
148: }
149:
150: /* Timeout RIP routes. */
151: static int
152: rip_timeout (struct thread *t)
153: {
154: struct rip_info *rinfo;
155: struct route_node *rn;
156:
157: rinfo = THREAD_ARG (t);
158: rinfo->t_timeout = NULL;
159:
160: rn = rinfo->rp;
161:
162: /* - The garbage-collection timer is set for 120 seconds. */
163: RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
164: rip->garbage_time);
165:
166: rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
167: rinfo->metric);
168: /* - The metric for the route is set to 16 (infinity). This causes
169: the route to be removed from service. */
170: rinfo->metric = RIP_METRIC_INFINITY;
171: rinfo->flags &= ~RIP_RTF_FIB;
172:
173: /* - The route change flag is to indicate that this entry has been
174: changed. */
175: rinfo->flags |= RIP_RTF_CHANGED;
176:
177: /* - The output process is signalled to trigger a response. */
178: rip_event (RIP_TRIGGERED_UPDATE, 0);
179:
180: return 0;
181: }
182:
183: static void
184: rip_timeout_update (struct rip_info *rinfo)
185: {
186: if (rinfo->metric != RIP_METRIC_INFINITY)
187: {
188: RIP_TIMER_OFF (rinfo->t_timeout);
189: RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
190: }
191: }
192:
193: static int
194: rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
195: {
196: struct distribute *dist;
197: struct access_list *alist;
198: struct prefix_list *plist;
199:
200: /* Input distribute-list filtering. */
201: if (ri->list[RIP_FILTER_IN])
202: {
203: if (access_list_apply (ri->list[RIP_FILTER_IN],
204: (struct prefix *) p) == FILTER_DENY)
205: {
206: if (IS_RIP_DEBUG_PACKET)
207: zlog_debug ("%s/%d filtered by distribute in",
208: inet_ntoa (p->prefix), p->prefixlen);
209: return -1;
210: }
211: }
212: if (ri->prefix[RIP_FILTER_IN])
213: {
214: if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
215: (struct prefix *) p) == PREFIX_DENY)
216: {
217: if (IS_RIP_DEBUG_PACKET)
218: zlog_debug ("%s/%d filtered by prefix-list in",
219: inet_ntoa (p->prefix), p->prefixlen);
220: return -1;
221: }
222: }
223:
224: /* All interface filter check. */
225: dist = distribute_lookup (NULL);
226: if (dist)
227: {
228: if (dist->list[DISTRIBUTE_IN])
229: {
230: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
231:
232: if (alist)
233: {
234: if (access_list_apply (alist,
235: (struct prefix *) p) == FILTER_DENY)
236: {
237: if (IS_RIP_DEBUG_PACKET)
238: zlog_debug ("%s/%d filtered by distribute in",
239: inet_ntoa (p->prefix), p->prefixlen);
240: return -1;
241: }
242: }
243: }
244: if (dist->prefix[DISTRIBUTE_IN])
245: {
246: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
247:
248: if (plist)
249: {
250: if (prefix_list_apply (plist,
251: (struct prefix *) p) == PREFIX_DENY)
252: {
253: if (IS_RIP_DEBUG_PACKET)
254: zlog_debug ("%s/%d filtered by prefix-list in",
255: inet_ntoa (p->prefix), p->prefixlen);
256: return -1;
257: }
258: }
259: }
260: }
261: return 0;
262: }
263:
264: static int
265: rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
266: {
267: struct distribute *dist;
268: struct access_list *alist;
269: struct prefix_list *plist;
270:
271: if (ri->list[RIP_FILTER_OUT])
272: {
273: if (access_list_apply (ri->list[RIP_FILTER_OUT],
274: (struct prefix *) p) == FILTER_DENY)
275: {
276: if (IS_RIP_DEBUG_PACKET)
277: zlog_debug ("%s/%d is filtered by distribute out",
278: inet_ntoa (p->prefix), p->prefixlen);
279: return -1;
280: }
281: }
282: if (ri->prefix[RIP_FILTER_OUT])
283: {
284: if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
285: (struct prefix *) p) == PREFIX_DENY)
286: {
287: if (IS_RIP_DEBUG_PACKET)
288: zlog_debug ("%s/%d is filtered by prefix-list out",
289: inet_ntoa (p->prefix), p->prefixlen);
290: return -1;
291: }
292: }
293:
294: /* All interface filter check. */
295: dist = distribute_lookup (NULL);
296: if (dist)
297: {
298: if (dist->list[DISTRIBUTE_OUT])
299: {
300: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
301:
302: if (alist)
303: {
304: if (access_list_apply (alist,
305: (struct prefix *) p) == FILTER_DENY)
306: {
307: if (IS_RIP_DEBUG_PACKET)
308: zlog_debug ("%s/%d filtered by distribute out",
309: inet_ntoa (p->prefix), p->prefixlen);
310: return -1;
311: }
312: }
313: }
314: if (dist->prefix[DISTRIBUTE_OUT])
315: {
316: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
317:
318: if (plist)
319: {
320: if (prefix_list_apply (plist,
321: (struct prefix *) p) == PREFIX_DENY)
322: {
323: if (IS_RIP_DEBUG_PACKET)
324: zlog_debug ("%s/%d filtered by prefix-list out",
325: inet_ntoa (p->prefix), p->prefixlen);
326: return -1;
327: }
328: }
329: }
330: }
331: return 0;
332: }
333:
334: /* Check nexthop address validity. */
335: static int
336: rip_nexthop_check (struct in_addr *addr)
337: {
338: struct listnode *node;
339: struct listnode *cnode;
340: struct interface *ifp;
341: struct connected *ifc;
342: struct prefix *p;
343:
344: /* If nexthop address matches local configured address then it is
345: invalid nexthop. */
346: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
347: {
348: for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
349: {
350: p = ifc->address;
351:
352: if (p->family == AF_INET
353: && IPV4_ADDR_SAME (&p->u.prefix4, addr))
354: return -1;
355: }
356: }
357: return 0;
358: }
359:
360: /* RIP add route to routing table. */
361: static void
362: rip_rte_process (struct rte *rte, struct sockaddr_in *from,
363: struct interface *ifp)
364: {
365: int ret;
366: struct prefix_ipv4 p;
367: struct route_node *rp;
368: struct rip_info *rinfo, rinfotmp;
369: struct rip_interface *ri;
370: struct in_addr *nexthop;
371: u_char oldmetric;
372: int same = 0;
373: int route_reuse = 0;
374: unsigned char old_dist, new_dist;
375:
376: /* Make prefix structure. */
377: memset (&p, 0, sizeof (struct prefix_ipv4));
378: p.family = AF_INET;
379: p.prefix = rte->prefix;
380: p.prefixlen = ip_masklen (rte->mask);
381:
382: /* Make sure mask is applied. */
383: apply_mask_ipv4 (&p);
384:
385: /* Apply input filters. */
386: ri = ifp->info;
387:
388: ret = rip_incoming_filter (&p, ri);
389: if (ret < 0)
390: return;
391:
392: /* Modify entry according to the interface routemap. */
393: if (ri->routemap[RIP_FILTER_IN])
394: {
395: int ret;
396: struct rip_info newinfo;
397:
398: memset (&newinfo, 0, sizeof (newinfo));
399: newinfo.type = ZEBRA_ROUTE_RIP;
400: newinfo.sub_type = RIP_ROUTE_RTE;
401: newinfo.nexthop = rte->nexthop;
402: newinfo.from = from->sin_addr;
403: newinfo.ifindex = ifp->ifindex;
404: newinfo.metric = rte->metric;
405: newinfo.metric_out = rte->metric; /* XXX */
406: newinfo.tag = ntohs (rte->tag); /* XXX */
407:
408: /* The object should be of the type of rip_info */
409: ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
410: (struct prefix *) &p, RMAP_RIP, &newinfo);
411:
412: if (ret == RMAP_DENYMATCH)
413: {
414: if (IS_RIP_DEBUG_PACKET)
415: zlog_debug ("RIP %s/%d is filtered by route-map in",
416: inet_ntoa (p.prefix), p.prefixlen);
417: return;
418: }
419:
420: /* Get back the object */
421: rte->nexthop = newinfo.nexthop_out;
422: rte->tag = htons (newinfo.tag_out); /* XXX */
423: rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
424: }
425:
426: /* Once the entry has been validated, update the metric by
427: adding the cost of the network on wich the message
428: arrived. If the result is greater than infinity, use infinity
429: (RFC2453 Sec. 3.9.2) */
430: /* Zebra ripd can handle offset-list in. */
431: ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
432:
433: /* If offset-list does not modify the metric use interface's
434: metric. */
435: if (!ret)
436: rte->metric += ifp->metric;
437:
438: if (rte->metric > RIP_METRIC_INFINITY)
439: rte->metric = RIP_METRIC_INFINITY;
440:
441: /* Set nexthop pointer. */
442: if (rte->nexthop.s_addr == 0)
443: nexthop = &from->sin_addr;
444: else
445: nexthop = &rte->nexthop;
446:
447: /* Check if nexthop address is myself, then do nothing. */
448: if (rip_nexthop_check (nexthop) < 0)
449: {
450: if (IS_RIP_DEBUG_PACKET)
451: zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
452: return;
453: }
454:
455: /* Get index for the prefix. */
456: rp = route_node_get (rip->table, (struct prefix *) &p);
457:
458: /* Check to see whether there is already RIP route on the table. */
459: rinfo = rp->info;
460:
461: if (rinfo)
462: {
463: /* Local static route. */
464: if (rinfo->type == ZEBRA_ROUTE_RIP
465: && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
466: (rinfo->sub_type == RIP_ROUTE_DEFAULT))
467: && rinfo->metric != RIP_METRIC_INFINITY)
468: {
469: route_unlock_node (rp);
470: return;
471: }
472:
473: /* Redistributed route check. */
474: if (rinfo->type != ZEBRA_ROUTE_RIP
475: && rinfo->metric != RIP_METRIC_INFINITY)
476: {
477: /* Fill in a minimaly temporary rip_info structure, for a future
478: rip_distance_apply() use) */
479: memset (&rinfotmp, 0, sizeof (rinfotmp));
480: IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
481: rinfotmp.rp = rinfo->rp;
482: new_dist = rip_distance_apply (&rinfotmp);
483: new_dist = new_dist ? new_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
484: old_dist = rinfo->distance;
485: /* Only connected routes may have a valid NULL distance */
486: if (rinfo->type != ZEBRA_ROUTE_CONNECT)
487: old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
488: /* If imported route does not have STRICT precedence,
489: mark it as a ghost */
490: if (new_dist > old_dist
491: || rte->metric == RIP_METRIC_INFINITY)
492: {
493: route_unlock_node (rp);
494: return;
495: }
496: else
497: {
498: RIP_TIMER_OFF (rinfo->t_timeout);
499: RIP_TIMER_OFF (rinfo->t_garbage_collect);
500:
501: rp->info = NULL;
502: if (rip_route_rte (rinfo))
503: rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
504: &rinfo->nexthop, rinfo->metric);
505: rip_info_free (rinfo);
506: rinfo = NULL;
507: route_reuse = 1;
508: }
509: }
510: }
511:
512: if (!rinfo)
513: {
514: /* Now, check to see whether there is already an explicit route
515: for the destination prefix. If there is no such route, add
516: this route to the routing table, unless the metric is
517: infinity (there is no point in adding a route which
518: unusable). */
519: if (rte->metric != RIP_METRIC_INFINITY)
520: {
521: rinfo = rip_info_new ();
522:
523: /* - Setting the destination prefix and length to those in
524: the RTE. */
525: rinfo->rp = rp;
526:
527: /* - Setting the metric to the newly calculated metric (as
528: described above). */
529: rinfo->metric = rte->metric;
530: rinfo->tag = ntohs (rte->tag);
531:
532: /* - Set the next hop address to be the address of the router
533: from which the datagram came or the next hop address
534: specified by a next hop RTE. */
535: IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
536: IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
537: rinfo->ifindex = ifp->ifindex;
538:
539: /* - Initialize the timeout for the route. If the
540: garbage-collection timer is running for this route, stop it
541: (see section 2.3 for a discussion of the timers). */
542: rip_timeout_update (rinfo);
543:
544: /* - Set the route change flag. */
545: rinfo->flags |= RIP_RTF_CHANGED;
546:
547: /* - Signal the output process to trigger an update (see section
548: 2.5). */
549: rip_event (RIP_TRIGGERED_UPDATE, 0);
550:
551: /* Finally, route goes into the kernel. */
552: rinfo->type = ZEBRA_ROUTE_RIP;
553: rinfo->sub_type = RIP_ROUTE_RTE;
554:
555: /* Set distance value. */
556: rinfo->distance = rip_distance_apply (rinfo);
557:
558: rp->info = rinfo;
559: rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
560: rinfo->distance);
561: rinfo->flags |= RIP_RTF_FIB;
562: }
563:
564: /* Unlock temporary lock, i.e. same behaviour */
565: if (route_reuse)
566: route_unlock_node (rp);
567: }
568: else
569: {
570: /* Route is there but we are not sure the route is RIP or not. */
571: rinfo = rp->info;
572:
573: /* If there is an existing route, compare the next hop address
574: to the address of the router from which the datagram came.
575: If this datagram is from the same router as the existing
576: route, reinitialize the timeout. */
577: same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
578: && (rinfo->ifindex == ifp->ifindex));
579:
580: if (same)
581: rip_timeout_update (rinfo);
582:
583:
584: /* Fill in a minimaly temporary rip_info structure, for a future
585: rip_distance_apply() use) */
586: memset (&rinfotmp, 0, sizeof (rinfotmp));
587: IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
588: rinfotmp.rp = rinfo->rp;
589:
590:
591: /* Next, compare the metrics. If the datagram is from the same
592: router as the existing route, and the new metric is different
593: than the old one; or, if the new metric is lower than the old
594: one, or if the tag has been changed; or if there is a route
595: with a lower administrave distance; or an update of the
596: distance on the actual route; do the following actions: */
597: if ((same && rinfo->metric != rte->metric)
598: || (rte->metric < rinfo->metric)
599: || ((same)
600: && (rinfo->metric == rte->metric)
601: && ntohs (rte->tag) != rinfo->tag)
602: || (rinfo->distance > rip_distance_apply (&rinfotmp))
603: || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
604: {
605: /* - Adopt the route from the datagram. That is, put the
606: new metric in, and adjust the next hop address (if
607: necessary). */
608: oldmetric = rinfo->metric;
609: rinfo->metric = rte->metric;
610: rinfo->tag = ntohs (rte->tag);
611: IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
612: rinfo->ifindex = ifp->ifindex;
613: rinfo->distance = rip_distance_apply (rinfo);
614:
615: /* Should a new route to this network be established
616: while the garbage-collection timer is running, the
617: new route will replace the one that is about to be
618: deleted. In this case the garbage-collection timer
619: must be cleared. */
620:
621: if (oldmetric == RIP_METRIC_INFINITY &&
622: rinfo->metric < RIP_METRIC_INFINITY)
623: {
624: rinfo->type = ZEBRA_ROUTE_RIP;
625: rinfo->sub_type = RIP_ROUTE_RTE;
626:
627: RIP_TIMER_OFF (rinfo->t_garbage_collect);
628:
629: if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
630: IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
631:
632: rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
633: rinfo->distance);
634: rinfo->flags |= RIP_RTF_FIB;
635: }
636:
637: /* Update nexthop and/or metric value. */
638: if (oldmetric != RIP_METRIC_INFINITY)
639: {
640: rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
641: rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
642: rinfo->distance);
643: rinfo->flags |= RIP_RTF_FIB;
644:
645: if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
646: IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
647: }
648:
649: /* - Set the route change flag and signal the output process
650: to trigger an update. */
651: rinfo->flags |= RIP_RTF_CHANGED;
652: rip_event (RIP_TRIGGERED_UPDATE, 0);
653:
654: /* - If the new metric is infinity, start the deletion
655: process (described above); */
656: if (rinfo->metric == RIP_METRIC_INFINITY)
657: {
658: /* If the new metric is infinity, the deletion process
659: begins for the route, which is no longer used for
660: routing packets. Note that the deletion process is
661: started only when the metric is first set to
662: infinity. If the metric was already infinity, then a
663: new deletion process is not started. */
664: if (oldmetric != RIP_METRIC_INFINITY)
665: {
666: /* - The garbage-collection timer is set for 120 seconds. */
667: RIP_TIMER_ON (rinfo->t_garbage_collect,
668: rip_garbage_collect, rip->garbage_time);
669: RIP_TIMER_OFF (rinfo->t_timeout);
670:
671: /* - The metric for the route is set to 16
672: (infinity). This causes the route to be removed
673: from service. */
674: rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
675: rinfo->flags &= ~RIP_RTF_FIB;
676:
677: /* - The route change flag is to indicate that this
678: entry has been changed. */
679: /* - The output process is signalled to trigger a
680: response. */
681: ; /* Above processes are already done previously. */
682: }
683: }
684: else
685: {
686: /* otherwise, re-initialize the timeout. */
687: rip_timeout_update (rinfo);
688: }
689: }
690: /* Unlock tempolary lock of the route. */
691: route_unlock_node (rp);
692: }
693: }
694:
695: /* Dump RIP packet */
696: static void
697: rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
698: {
699: caddr_t lim;
700: struct rte *rte;
701: const char *command_str;
702: char pbuf[BUFSIZ], nbuf[BUFSIZ];
703: u_char netmask = 0;
704: u_char *p;
705:
706: /* Set command string. */
707: if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
708: command_str = lookup (rip_msg, packet->command);
709: else
710: command_str = "unknown";
711:
712: /* Dump packet header. */
713: zlog_debug ("%s %s version %d packet size %d",
714: sndrcv, command_str, packet->version, size);
715:
716: /* Dump each routing table entry. */
717: rte = packet->rte;
718:
719: for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
720: {
721: if (packet->version == RIPv2)
722: {
723: netmask = ip_masklen (rte->mask);
724:
725: if (rte->family == htons (RIP_FAMILY_AUTH))
726: {
727: if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
728: {
729: p = (u_char *)&rte->prefix;
730:
731: zlog_debug (" family 0x%X type %d auth string: %s",
732: ntohs (rte->family), ntohs (rte->tag), p);
733: }
734: else if (rte->tag == htons (RIP_AUTH_MD5))
735: {
736: struct rip_md5_info *md5;
737:
738: md5 = (struct rip_md5_info *) &packet->rte;
739:
740: zlog_debug (" family 0x%X type %d (MD5 authentication)",
741: ntohs (md5->family), ntohs (md5->type));
742: zlog_debug (" RIP-2 packet len %d Key ID %d"
743: " Auth Data len %d",
744: ntohs (md5->packet_len), md5->keyid,
745: md5->auth_len);
746: zlog_debug (" Sequence Number %ld",
747: (u_long) ntohl (md5->sequence));
748: }
749: else if (rte->tag == htons (RIP_AUTH_DATA))
750: {
751: p = (u_char *)&rte->prefix;
752:
753: zlog_debug (" family 0x%X type %d (MD5 data)",
754: ntohs (rte->family), ntohs (rte->tag));
755: zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
756: "%02X%02X%02X%02X%02X%02X%02X",
757: p[0], p[1], p[2], p[3], p[4], p[5], p[6],
758: p[7], p[9], p[10], p[11], p[12], p[13],
759: p[14], p[15]);
760: }
761: else
762: {
763: zlog_debug (" family 0x%X type %d (Unknown auth type)",
764: ntohs (rte->family), ntohs (rte->tag));
765: }
766: }
767: else
768: zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
769: inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
770: netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
771: BUFSIZ), ntohs (rte->family),
772: ntohs (rte->tag), (u_long) ntohl (rte->metric));
773: }
774: else
775: {
776: zlog_debug (" %s family %d tag %d metric %ld",
777: inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
778: ntohs (rte->family), ntohs (rte->tag),
779: (u_long)ntohl (rte->metric));
780: }
781: }
782: }
783:
784: /* Check if the destination address is valid (unicast; not net 0
785: or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
786: check net 0 because we accept default route. */
787: static int
788: rip_destination_check (struct in_addr addr)
789: {
790: u_int32_t destination;
791:
792: /* Convert to host byte order. */
793: destination = ntohl (addr.s_addr);
794:
795: if (IPV4_NET127 (destination))
796: return 0;
797:
798: /* Net 0 may match to the default route. */
799: if (IPV4_NET0 (destination) && destination != 0)
800: return 0;
801:
802: /* Unicast address must belong to class A, B, C. */
803: if (IN_CLASSA (destination))
804: return 1;
805: if (IN_CLASSB (destination))
806: return 1;
807: if (IN_CLASSC (destination))
808: return 1;
809:
810: return 0;
811: }
812:
813: /* RIP version 2 authentication. */
814: static int
815: rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
816: struct interface *ifp)
817: {
818: struct rip_interface *ri;
819: char *auth_str;
820:
821: if (IS_RIP_DEBUG_EVENT)
822: zlog_debug ("RIPv2 simple password authentication from %s",
823: inet_ntoa (from->sin_addr));
824:
825: ri = ifp->info;
826:
827: if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
828: || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
829: return 0;
830:
831: /* Simple password authentication. */
832: if (ri->auth_str)
833: {
834: auth_str = (char *) &rte->prefix;
835:
836: if (strncmp (auth_str, ri->auth_str, 16) == 0)
837: return 1;
838: }
839: if (ri->key_chain)
840: {
841: struct keychain *keychain;
842: struct key *key;
843:
844: keychain = keychain_lookup (ri->key_chain);
845: if (keychain == NULL)
846: return 0;
847:
848: key = key_match_for_accept (keychain, (char *) &rte->prefix);
849: if (key)
850: return 1;
851: }
852: return 0;
853: }
854:
855: /* RIP version 2 authentication with MD5. */
856: static int
857: rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
858: int length, struct interface *ifp)
859: {
860: struct rip_interface *ri;
861: struct rip_md5_info *md5;
862: struct rip_md5_data *md5data;
863: struct keychain *keychain;
864: struct key *key;
865: MD5_CTX ctx;
866: u_char digest[RIP_AUTH_MD5_SIZE];
867: u_int16_t packet_len;
868: char auth_str[RIP_AUTH_MD5_SIZE];
869:
870: if (IS_RIP_DEBUG_EVENT)
871: zlog_debug ("RIPv2 MD5 authentication from %s",
872: inet_ntoa (from->sin_addr));
873:
874: ri = ifp->info;
875: md5 = (struct rip_md5_info *) &packet->rte;
876:
877: /* Check auth type. */
878: if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
879: return 0;
880:
881: /* If the authentication length is less than 16, then it must be wrong for
882: * any interpretation of rfc2082. Some implementations also interpret
883: * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
884: */
885: if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
886: || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
887: {
888: if (IS_RIP_DEBUG_EVENT)
889: zlog_debug ("RIPv2 MD5 authentication, strange authentication "
890: "length field %d", md5->auth_len);
891: return 0;
892: }
893:
894: /* grab and verify check packet length */
895: packet_len = ntohs (md5->packet_len);
896:
897: if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
898: {
899: if (IS_RIP_DEBUG_EVENT)
900: zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
901: "greater than received length %d!",
902: md5->packet_len, length);
903: return 0;
904: }
905:
906: /* retrieve authentication data */
907: md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
908:
909: memset (auth_str, 0, RIP_AUTH_MD5_SIZE);
910:
911: if (ri->key_chain)
912: {
913: keychain = keychain_lookup (ri->key_chain);
914: if (keychain == NULL)
915: return 0;
916:
917: key = key_lookup_for_accept (keychain, md5->keyid);
918: if (key == NULL)
919: return 0;
920:
921: strncpy (auth_str, key->string, RIP_AUTH_MD5_SIZE);
922: }
923: else if (ri->auth_str)
924: strncpy (auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
925:
926: if (auth_str[0] == 0)
927: return 0;
928:
929: /* MD5 digest authentication. */
930: memset (&ctx, 0, sizeof(ctx));
931: MD5Init(&ctx);
932: MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
933: MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
934: MD5Final(digest, &ctx);
935:
936: if (memcmp (md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
937: return packet_len;
938: else
939: return 0;
940: }
941:
942: /* Pick correct auth string for sends, prepare auth_str buffer for use.
943: * (left justified and padded).
944: *
945: * presumes one of ri or key is valid, and that the auth strings they point
946: * to are nul terminated. If neither are present, auth_str will be fully
947: * zero padded.
948: *
949: */
950: static void
951: rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
952: char *auth_str, int len)
953: {
954: assert (ri || key);
955:
956: memset (auth_str, 0, len);
957: if (key && key->string)
958: strncpy (auth_str, key->string, len);
959: else if (ri->auth_str)
960: strncpy (auth_str, ri->auth_str, len);
961:
962: return;
963: }
964:
965: /* Write RIPv2 simple password authentication information
966: *
967: * auth_str is presumed to be 2 bytes and correctly prepared
968: * (left justified and zero padded).
969: */
970: static void
971: rip_auth_simple_write (struct stream *s, char *auth_str, int len)
972: {
973: assert (s && len == RIP_AUTH_SIMPLE_SIZE);
974:
975: stream_putw (s, RIP_FAMILY_AUTH);
976: stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
977: stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
978:
979: return;
980: }
981:
982: /* write RIPv2 MD5 "authentication header"
983: * (uses the auth key data field)
984: *
985: * Digest offset field is set to 0.
986: *
987: * returns: offset of the digest offset field, which must be set when
988: * length to the auth-data MD5 digest is known.
989: */
990: static size_t
991: rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
992: struct key *key)
993: {
994: size_t doff = 0;
995:
996: assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
997:
998: /* MD5 authentication. */
999: stream_putw (s, RIP_FAMILY_AUTH);
1000: stream_putw (s, RIP_AUTH_MD5);
1001:
1002: /* MD5 AH digest offset field.
1003: *
1004: * Set to placeholder value here, to true value when RIP-2 Packet length
1005: * is known. Actual value is set in .....().
1006: */
1007: doff = stream_get_endp(s);
1008: stream_putw (s, 0);
1009:
1010: /* Key ID. */
1011: if (key)
1012: stream_putc (s, key->index % 256);
1013: else
1014: stream_putc (s, 1);
1015:
1016: /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1017: * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1018: * to be configurable.
1019: */
1020: stream_putc (s, ri->md5_auth_len);
1021:
1022: /* Sequence Number (non-decreasing). */
1023: /* RFC2080: The value used in the sequence number is
1024: arbitrary, but two suggestions are the time of the
1025: message's creation or a simple message counter. */
1026: stream_putl (s, time (NULL));
1027:
1028: /* Reserved field must be zero. */
1029: stream_putl (s, 0);
1030: stream_putl (s, 0);
1031:
1032: return doff;
1033: }
1034:
1035: /* If authentication is in used, write the appropriate header
1036: * returns stream offset to which length must later be written
1037: * or 0 if this is not required
1038: */
1039: static size_t
1040: rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1041: struct key *key, char *auth_str, int len)
1042: {
1043: assert (ri->auth_type != RIP_NO_AUTH);
1044:
1045: switch (ri->auth_type)
1046: {
1047: case RIP_AUTH_SIMPLE_PASSWORD:
1048: rip_auth_prepare_str_send (ri, key, auth_str, len);
1049: rip_auth_simple_write (s, auth_str, len);
1050: return 0;
1051: case RIP_AUTH_MD5:
1052: return rip_auth_md5_ah_write (s, ri, key);
1053: }
1054: assert (1);
1055: return 0;
1056: }
1057:
1058: /* Write RIPv2 MD5 authentication data trailer */
1059: static void
1060: rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1061: char *auth_str, int authlen)
1062: {
1063: unsigned long len;
1064: MD5_CTX ctx;
1065: unsigned char digest[RIP_AUTH_MD5_SIZE];
1066:
1067: /* Make it sure this interface is configured as MD5
1068: authentication. */
1069: assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1070: assert (doff > 0);
1071:
1072: /* Get packet length. */
1073: len = stream_get_endp(s);
1074:
1075: /* Check packet length. */
1076: if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1077: {
1078: zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1079: return;
1080: }
1081:
1082: /* Set the digest offset length in the header */
1083: stream_putw_at (s, doff, len);
1084:
1085: /* Set authentication data. */
1086: stream_putw (s, RIP_FAMILY_AUTH);
1087: stream_putw (s, RIP_AUTH_DATA);
1088:
1089: /* Generate a digest for the RIP packet. */
1090: memset(&ctx, 0, sizeof(ctx));
1091: MD5Init(&ctx);
1092: MD5Update(&ctx, STREAM_DATA (s), stream_get_endp (s));
1093: MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1094: MD5Final(digest, &ctx);
1095:
1096: /* Copy the digest to the packet. */
1097: stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1098: }
1099:
1100: /* RIP routing information. */
1101: static void
1102: rip_response_process (struct rip_packet *packet, int size,
1103: struct sockaddr_in *from, struct connected *ifc)
1104: {
1105: caddr_t lim;
1106: struct rte *rte;
1107: struct prefix_ipv4 ifaddr;
1108: struct prefix_ipv4 ifaddrclass;
1109: int subnetted;
1110:
1111: /* We don't know yet. */
1112: subnetted = -1;
1113:
1114: /* The Response must be ignored if it is not from the RIP
1115: port. (RFC2453 - Sec. 3.9.2)*/
1116: if (from->sin_port != htons(RIP_PORT_DEFAULT))
1117: {
1118: zlog_info ("response doesn't come from RIP port: %d",
1119: from->sin_port);
1120: rip_peer_bad_packet (from);
1121: return;
1122: }
1123:
1124: /* The datagram's IPv4 source address should be checked to see
1125: whether the datagram is from a valid neighbor; the source of the
1126: datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */
1127: if (if_lookup_address(from->sin_addr) == NULL)
1128: {
1129: zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1130: inet_ntoa (from->sin_addr));
1131: rip_peer_bad_packet (from);
1132: return;
1133: }
1134:
1135: /* It is also worth checking to see whether the response is from one
1136: of the router's own addresses. */
1137:
1138: ; /* Alredy done in rip_read () */
1139:
1140: /* Update RIP peer. */
1141: rip_peer_update (from, packet->version);
1142:
1143: /* Set RTE pointer. */
1144: rte = packet->rte;
1145:
1146: for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1147: {
1148: /* RIPv2 authentication check. */
1149: /* If the Address Family Identifier of the first (and only the
1150: first) entry in the message is 0xFFFF, then the remainder of
1151: the entry contains the authentication. */
1152: /* If the packet gets here it means authentication enabled */
1153: /* Check is done in rip_read(). So, just skipping it */
1154: if (packet->version == RIPv2 &&
1155: rte == packet->rte &&
1156: rte->family == htons(RIP_FAMILY_AUTH))
1157: continue;
1158:
1159: if (rte->family != htons(AF_INET))
1160: {
1161: /* Address family check. RIP only supports AF_INET. */
1162: zlog_info ("Unsupported family %d from %s.",
1163: ntohs (rte->family), inet_ntoa (from->sin_addr));
1164: continue;
1165: }
1166:
1167: /* - is the destination address valid (e.g., unicast; not net 0
1168: or 127) */
1169: if (! rip_destination_check (rte->prefix))
1170: {
1171: zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1172: rip_peer_bad_route (from);
1173: continue;
1174: }
1175:
1176: /* Convert metric value to host byte order. */
1177: rte->metric = ntohl (rte->metric);
1178:
1179: /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1180: if (! (rte->metric >= 1 && rte->metric <= 16))
1181: {
1182: zlog_info ("Route's metric is not in the 1-16 range.");
1183: rip_peer_bad_route (from);
1184: continue;
1185: }
1186:
1187: /* RIPv1 does not have nexthop value. */
1188: if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1189: {
1190: zlog_info ("RIPv1 packet with nexthop value %s",
1191: inet_ntoa (rte->nexthop));
1192: rip_peer_bad_route (from);
1193: continue;
1194: }
1195:
1196: /* That is, if the provided information is ignored, a possibly
1197: sub-optimal, but absolutely valid, route may be taken. If
1198: the received Next Hop is not directly reachable, it should be
1199: treated as 0.0.0.0. */
1200: if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1201: {
1202: u_int32_t addrval;
1203:
1204: /* Multicast address check. */
1205: addrval = ntohl (rte->nexthop.s_addr);
1206: if (IN_CLASSD (addrval))
1207: {
1208: zlog_info ("Nexthop %s is multicast address, skip this rte",
1209: inet_ntoa (rte->nexthop));
1210: continue;
1211: }
1212:
1213: if (! if_lookup_address (rte->nexthop))
1214: {
1215: struct route_node *rn;
1216: struct rip_info *rinfo;
1217:
1218: rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1219:
1220: if (rn)
1221: {
1222: rinfo = rn->info;
1223:
1224: if (rinfo->type == ZEBRA_ROUTE_RIP
1225: && rinfo->sub_type == RIP_ROUTE_RTE)
1226: {
1227: if (IS_RIP_DEBUG_EVENT)
1228: zlog_debug ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
1229: rte->nexthop = rinfo->from;
1230: }
1231: else
1232: {
1233: if (IS_RIP_DEBUG_EVENT)
1234: zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1235: rte->nexthop.s_addr = 0;
1236: }
1237:
1238: route_unlock_node (rn);
1239: }
1240: else
1241: {
1242: if (IS_RIP_DEBUG_EVENT)
1243: zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1244: rte->nexthop.s_addr = 0;
1245: }
1246:
1247: }
1248: }
1249:
1250: /* For RIPv1, there won't be a valid netmask.
1251:
1252: This is a best guess at the masks. If everyone was using old
1253: Ciscos before the 'ip subnet zero' option, it would be almost
1254: right too :-)
1255:
1256: Cisco summarize ripv1 advertisments to the classful boundary
1257: (/16 for class B's) except when the RIP packet does to inside
1258: the classful network in question. */
1259:
1260: if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1261: || (packet->version == RIPv2
1262: && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1263: {
1264: u_int32_t destination;
1265:
1266: if (subnetted == -1)
1267: {
1268: memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1269: memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1270: apply_classful_mask_ipv4 (&ifaddrclass);
1271: subnetted = 0;
1272: if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1273: subnetted = 1;
1274: }
1275:
1276: destination = ntohl (rte->prefix.s_addr);
1277:
1278: if (IN_CLASSA (destination))
1279: masklen2ip (8, &rte->mask);
1280: else if (IN_CLASSB (destination))
1281: masklen2ip (16, &rte->mask);
1282: else if (IN_CLASSC (destination))
1283: masklen2ip (24, &rte->mask);
1284:
1285: if (subnetted == 1)
1286: masklen2ip (ifaddrclass.prefixlen,
1287: (struct in_addr *) &destination);
1288: if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1289: ifaddrclass.prefix.s_addr))
1290: {
1291: masklen2ip (ifaddr.prefixlen, &rte->mask);
1292: if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1293: masklen2ip (32, &rte->mask);
1294: if (IS_RIP_DEBUG_EVENT)
1295: zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
1296: }
1297: else
1298: {
1299: if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1300: continue;
1301: }
1302:
1303: if (IS_RIP_DEBUG_EVENT)
1304: {
1305: zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1306: zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
1307: }
1308: }
1309:
1310: /* In case of RIPv2, if prefix in RTE is not netmask applied one
1311: ignore the entry. */
1312: if ((packet->version == RIPv2)
1313: && (rte->mask.s_addr != 0)
1314: && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1315: {
1316: zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1317: inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1318: rip_peer_bad_route (from);
1319: continue;
1320: }
1321:
1322: /* Default route's netmask is ignored. */
1323: if (packet->version == RIPv2
1324: && (rte->prefix.s_addr == 0)
1325: && (rte->mask.s_addr != 0))
1326: {
1327: if (IS_RIP_DEBUG_EVENT)
1328: zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
1329: rte->mask.s_addr = 0;
1330: }
1331:
1332: /* Routing table updates. */
1333: rip_rte_process (rte, from, ifc->ifp);
1334: }
1335: }
1336:
1337: /* Make socket for RIP protocol. */
1338: static int
1339: rip_create_socket (struct sockaddr_in *from)
1340: {
1341: int ret;
1342: int sock;
1343: struct sockaddr_in addr;
1344:
1345: memset (&addr, 0, sizeof (struct sockaddr_in));
1346:
1347: if (!from)
1348: {
1349: addr.sin_family = AF_INET;
1350: addr.sin_addr.s_addr = INADDR_ANY;
1351: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1352: addr.sin_len = sizeof (struct sockaddr_in);
1353: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1354: } else {
1355: memcpy(&addr, from, sizeof(addr));
1356: }
1357:
1358: /* sending port must always be the RIP port */
1359: addr.sin_port = htons (RIP_PORT_DEFAULT);
1360:
1361: /* Make datagram socket. */
1362: sock = socket (AF_INET, SOCK_DGRAM, 0);
1363: if (sock < 0)
1364: {
1365: zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1366: exit (1);
1367: }
1368:
1369: sockopt_broadcast (sock);
1370: sockopt_reuseaddr (sock);
1371: sockopt_reuseport (sock);
1372: #ifdef RIP_RECVMSG
1373: setsockopt_pktinfo (sock);
1374: #endif /* RIP_RECVMSG */
1375: #ifdef IPTOS_PREC_INTERNETCONTROL
1376: setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
1377: #endif
1378:
1379: if (ripd_privs.change (ZPRIVS_RAISE))
1380: zlog_err ("rip_create_socket: could not raise privs");
1381: setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1382: if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1383:
1384: {
1385: int save_errno = errno;
1386: if (ripd_privs.change (ZPRIVS_LOWER))
1387: zlog_err ("rip_create_socket: could not lower privs");
1388:
1389: zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1390: sock, inet_ntoa(addr.sin_addr),
1391: (int) ntohs(addr.sin_port),
1392: safe_strerror(save_errno));
1393:
1394: close (sock);
1395: return ret;
1396: }
1397:
1398: if (ripd_privs.change (ZPRIVS_LOWER))
1399: zlog_err ("rip_create_socket: could not lower privs");
1400:
1401: return sock;
1402: }
1403:
1404: /* RIP packet send to destination address, on interface denoted by
1405: * by connected argument. NULL to argument denotes destination should be
1406: * should be RIP multicast group
1407: */
1408: static int
1409: rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1410: struct connected *ifc)
1411: {
1412: int ret, send_sock;
1413: struct sockaddr_in sin;
1414:
1415: assert (ifc != NULL);
1416:
1417: if (IS_RIP_DEBUG_PACKET)
1418: {
1419: #define ADDRESS_SIZE 20
1420: char dst[ADDRESS_SIZE];
1421: dst[ADDRESS_SIZE - 1] = '\0';
1422:
1423: if (to)
1424: {
1425: strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
1426: }
1427: else
1428: {
1429: sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1430: strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
1431: }
1432: #undef ADDRESS_SIZE
1433: zlog_debug("rip_send_packet %s > %s (%s)",
1434: inet_ntoa(ifc->address->u.prefix4),
1435: dst, ifc->ifp->name);
1436: }
1437:
1438: if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
1439: {
1440: /*
1441: * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1442: * with multiple addresses on the same subnet: the first address
1443: * on the subnet is configured "primary", and all subsequent addresses
1444: * on that subnet are treated as "secondary" addresses.
1445: * In order to avoid routing-table bloat on other rip listeners,
1446: * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1447: * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1448: * flag is set, we would end up sending a packet for a "secondary"
1449: * source address on non-linux systems.
1450: */
1451: if (IS_RIP_DEBUG_PACKET)
1452: zlog_debug("duplicate dropped");
1453: return 0;
1454: }
1455:
1456: /* Make destination address. */
1457: memset (&sin, 0, sizeof (struct sockaddr_in));
1458: sin.sin_family = AF_INET;
1459: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1460: sin.sin_len = sizeof (struct sockaddr_in);
1461: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1462:
1463: /* When destination is specified, use it's port and address. */
1464: if (to)
1465: {
1466: sin.sin_port = to->sin_port;
1467: sin.sin_addr = to->sin_addr;
1468: send_sock = rip->sock;
1469: }
1470: else
1471: {
1472: struct sockaddr_in from;
1473:
1474: sin.sin_port = htons (RIP_PORT_DEFAULT);
1475: sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1476:
1477: /* multicast send should bind to local interface address */
1478: from.sin_family = AF_INET;
1479: from.sin_port = htons (RIP_PORT_DEFAULT);
1480: from.sin_addr = ifc->address->u.prefix4;
1481: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1482: from.sin_len = sizeof (struct sockaddr_in);
1483: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1484:
1485: /*
1486: * we have to open a new socket for each packet because this
1487: * is the most portable way to bind to a different source
1488: * ipv4 address for each packet.
1489: */
1490: if ( (send_sock = rip_create_socket (&from)) < 0)
1491: {
1492: zlog_warn("rip_send_packet could not create socket.");
1493: return -1;
1494: }
1495: rip_interface_multicast_set (send_sock, ifc);
1496: }
1497:
1498: ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
1499: sizeof (struct sockaddr_in));
1500:
1501: if (IS_RIP_DEBUG_EVENT)
1502: zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1503: ntohs (sin.sin_port));
1504:
1505: if (ret < 0)
1506: zlog_warn ("can't send packet : %s", safe_strerror (errno));
1507:
1508: if (!to)
1509: close(send_sock);
1510:
1511: return ret;
1512: }
1513:
1514: /* Add redistributed route to RIP table. */
1515: void
1516: rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1517: unsigned int ifindex, struct in_addr *nexthop,
1518: unsigned int metric, unsigned char distance)
1519: {
1520: int ret;
1521: struct route_node *rp;
1522: struct rip_info *rinfo;
1523:
1524: /* Redistribute route */
1525: ret = rip_destination_check (p->prefix);
1526: if (! ret)
1527: return;
1528:
1529: rp = route_node_get (rip->table, (struct prefix *) p);
1530:
1531: rinfo = rp->info;
1532:
1533: if (rinfo)
1534: {
1535: if (rinfo->type == ZEBRA_ROUTE_CONNECT
1536: && rinfo->sub_type == RIP_ROUTE_INTERFACE
1537: && rinfo->metric != RIP_METRIC_INFINITY)
1538: {
1539: route_unlock_node (rp);
1540: return;
1541: }
1542:
1543: /* Manually configured RIP route check. */
1544: if (rinfo->type == ZEBRA_ROUTE_RIP
1545: && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1546: (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
1547: {
1548: if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1549: (sub_type != RIP_ROUTE_DEFAULT)))
1550: {
1551: route_unlock_node (rp);
1552: return;
1553: }
1554: }
1555:
1556: RIP_TIMER_OFF (rinfo->t_timeout);
1557: RIP_TIMER_OFF (rinfo->t_garbage_collect);
1558:
1559: if (rip_route_rte (rinfo))
1560: rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1561: rinfo->metric);
1562: rp->info = NULL;
1563: rip_info_free (rinfo);
1564:
1565: route_unlock_node (rp);
1566: }
1567:
1568: rinfo = rip_info_new ();
1569:
1570: rinfo->type = type;
1571: rinfo->sub_type = sub_type;
1572: rinfo->ifindex = ifindex;
1573: rinfo->metric = 1;
1574: rinfo->external_metric = metric;
1575: rinfo->distance = distance;
1576: rinfo->rp = rp;
1577:
1578: if (nexthop)
1579: rinfo->nexthop = *nexthop;
1580:
1581: rinfo->flags |= RIP_RTF_FIB;
1582: rp->info = rinfo;
1583:
1584: rinfo->flags |= RIP_RTF_CHANGED;
1585:
1586: if (IS_RIP_DEBUG_EVENT) {
1587: if (!nexthop)
1588: zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
1589: inet_ntoa(p->prefix), p->prefixlen,
1590: ifindex2ifname(ifindex));
1591: else
1592: zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1593: inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1594: ifindex2ifname(ifindex));
1595: }
1596:
1597:
1598: rip_event (RIP_TRIGGERED_UPDATE, 0);
1599: }
1600:
1601: /* Delete redistributed route from RIP table. */
1602: void
1603: rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1604: unsigned int ifindex)
1605: {
1606: int ret;
1607: struct route_node *rp;
1608: struct rip_info *rinfo;
1609:
1610: ret = rip_destination_check (p->prefix);
1611: if (! ret)
1612: return;
1613:
1614: rp = route_node_lookup (rip->table, (struct prefix *) p);
1615: if (rp)
1616: {
1617: rinfo = rp->info;
1618:
1619: if (rinfo != NULL
1620: && rinfo->type == type
1621: && rinfo->sub_type == sub_type
1622: && rinfo->ifindex == ifindex)
1623: {
1624: /* Perform poisoned reverse. */
1625: rinfo->metric = RIP_METRIC_INFINITY;
1626: RIP_TIMER_ON (rinfo->t_garbage_collect,
1627: rip_garbage_collect, rip->garbage_time);
1628: RIP_TIMER_OFF (rinfo->t_timeout);
1629: rinfo->flags |= RIP_RTF_CHANGED;
1630:
1631: if (IS_RIP_DEBUG_EVENT)
1632: zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1633: inet_ntoa(p->prefix), p->prefixlen,
1634: ifindex2ifname(ifindex));
1635:
1636: rip_event (RIP_TRIGGERED_UPDATE, 0);
1637: }
1638: }
1639: }
1640:
1641: /* Response to request called from rip_read ().*/
1642: static void
1643: rip_request_process (struct rip_packet *packet, int size,
1644: struct sockaddr_in *from, struct connected *ifc)
1645: {
1646: caddr_t lim;
1647: struct rte *rte;
1648: struct prefix_ipv4 p;
1649: struct route_node *rp;
1650: struct rip_info *rinfo;
1651: struct rip_interface *ri;
1652:
1653: /* Does not reponse to the requests on the loopback interfaces */
1654: if (if_is_loopback (ifc->ifp))
1655: return;
1656:
1657: /* Check RIP process is enabled on this interface. */
1658: ri = ifc->ifp->info;
1659: if (! ri->running)
1660: return;
1661:
1662: /* When passive interface is specified, suppress responses */
1663: if (ri->passive)
1664: return;
1665:
1666: /* RIP peer update. */
1667: rip_peer_update (from, packet->version);
1668:
1669: lim = ((caddr_t) packet) + size;
1670: rte = packet->rte;
1671:
1672: /* The Request is processed entry by entry. If there are no
1673: entries, no response is given. */
1674: if (lim == (caddr_t) rte)
1675: return;
1676:
1677: /* There is one special case. If there is exactly one entry in the
1678: request, and it has an address family identifier of zero and a
1679: metric of infinity (i.e., 16), then this is a request to send the
1680: entire routing table. */
1681: if (lim == ((caddr_t) (rte + 1)) &&
1682: ntohs (rte->family) == 0 &&
1683: ntohl (rte->metric) == RIP_METRIC_INFINITY)
1684: {
1685: struct prefix_ipv4 saddr;
1686:
1687: /* saddr will be used for determining which routes to split-horizon.
1688: Since the source address we'll pick will be on the same subnet as the
1689: destination, for the purpose of split-horizoning, we'll
1690: pretend that "from" is our source address. */
1691: saddr.family = AF_INET;
1692: saddr.prefixlen = IPV4_MAX_BITLEN;
1693: saddr.prefix = from->sin_addr;
1694:
1695: /* All route with split horizon */
1696: rip_output_process (ifc, from, rip_all_route, packet->version);
1697: }
1698: else
1699: {
1700: /* Examine the list of RTEs in the Request one by one. For each
1701: entry, look up the destination in the router's routing
1702: database and, if there is a route, put that route's metric in
1703: the metric field of the RTE. If there is no explicit route
1704: to the specified destination, put infinity in the metric
1705: field. Once all the entries have been filled in, change the
1706: command from Request to Response and send the datagram back
1707: to the requestor. */
1708: p.family = AF_INET;
1709:
1710: for (; ((caddr_t) rte) < lim; rte++)
1711: {
1712: p.prefix = rte->prefix;
1713: p.prefixlen = ip_masklen (rte->mask);
1714: apply_mask_ipv4 (&p);
1715:
1716: rp = route_node_lookup (rip->table, (struct prefix *) &p);
1717: if (rp)
1718: {
1719: rinfo = rp->info;
1720: rte->metric = htonl (rinfo->metric);
1721: route_unlock_node (rp);
1722: }
1723: else
1724: rte->metric = htonl (RIP_METRIC_INFINITY);
1725: }
1726: packet->command = RIP_RESPONSE;
1727:
1728: rip_send_packet ((u_char *)packet, size, from, ifc);
1729: }
1730: rip_global_queries++;
1731: }
1732:
1733: #if RIP_RECVMSG
1734: /* Set IPv6 packet info to the socket. */
1735: static int
1736: setsockopt_pktinfo (int sock)
1737: {
1738: int ret;
1739: int val = 1;
1740:
1741: ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1742: if (ret < 0)
1743: zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
1744: return ret;
1745: }
1746:
1747: /* Read RIP packet by recvmsg function. */
1748: int
1749: rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1750: int *ifindex)
1751: {
1752: int ret;
1753: struct msghdr msg;
1754: struct iovec iov;
1755: struct cmsghdr *ptr;
1756: char adata[1024];
1757:
1758: msg.msg_name = (void *) from;
1759: msg.msg_namelen = sizeof (struct sockaddr_in);
1760: msg.msg_iov = &iov;
1761: msg.msg_iovlen = 1;
1762: msg.msg_control = (void *) adata;
1763: msg.msg_controllen = sizeof adata;
1764: iov.iov_base = buf;
1765: iov.iov_len = size;
1766:
1767: ret = recvmsg (sock, &msg, 0);
1768: if (ret < 0)
1769: return ret;
1770:
1771: for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1772: if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1773: {
1774: struct in_pktinfo *pktinfo;
1775: int i;
1776:
1777: pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1778: i = pktinfo->ipi_ifindex;
1779: }
1780: return ret;
1781: }
1782:
1783: /* RIP packet read function. */
1784: int
1785: rip_read_new (struct thread *t)
1786: {
1787: int ret;
1788: int sock;
1789: char buf[RIP_PACKET_MAXSIZ];
1790: struct sockaddr_in from;
1791: unsigned int ifindex;
1792:
1793: /* Fetch socket then register myself. */
1794: sock = THREAD_FD (t);
1795: rip_event (RIP_READ, sock);
1796:
1797: /* Read RIP packet. */
1798: ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1799: if (ret < 0)
1800: {
1801: zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
1802: return ret;
1803: }
1804:
1805: return ret;
1806: }
1807: #endif /* RIP_RECVMSG */
1808:
1809: /* First entry point of RIP packet. */
1810: static int
1811: rip_read (struct thread *t)
1812: {
1813: int sock;
1814: int ret;
1815: int rtenum;
1816: union rip_buf rip_buf;
1817: struct rip_packet *packet;
1818: struct sockaddr_in from;
1819: int len;
1820: int vrecv;
1821: socklen_t fromlen;
1822: struct interface *ifp;
1823: struct connected *ifc;
1824: struct rip_interface *ri;
1825:
1826: /* Fetch socket then register myself. */
1827: sock = THREAD_FD (t);
1828: rip->t_read = NULL;
1829:
1830: /* Add myself to tne next event */
1831: rip_event (RIP_READ, sock);
1832:
1833: /* RIPd manages only IPv4. */
1834: memset (&from, 0, sizeof (struct sockaddr_in));
1835: fromlen = sizeof (struct sockaddr_in);
1836:
1837: len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1838: (struct sockaddr *) &from, &fromlen);
1839: if (len < 0)
1840: {
1841: zlog_info ("recvfrom failed: %s", safe_strerror (errno));
1842: return len;
1843: }
1844:
1845: /* Check is this packet comming from myself? */
1846: if (if_check_address (from.sin_addr))
1847: {
1848: if (IS_RIP_DEBUG_PACKET)
1849: zlog_debug ("ignore packet comes from myself");
1850: return -1;
1851: }
1852:
1853: /* Which interface is this packet comes from. */
1854: ifp = if_lookup_address (from.sin_addr);
1855:
1856: /* RIP packet received */
1857: if (IS_RIP_DEBUG_EVENT)
1858: zlog_debug ("RECV packet from %s port %d on %s",
1859: inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1860: ifp ? ifp->name : "unknown");
1861:
1862: /* If this packet come from unknown interface, ignore it. */
1863: if (ifp == NULL)
1864: {
1865: zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1866: inet_ntoa(from.sin_addr), ntohs (from.sin_port));
1867: return -1;
1868: }
1869:
1870: ifc = connected_lookup_address (ifp, from.sin_addr);
1871:
1872: if (ifc == NULL)
1873: {
1874: zlog_info ("rip_read: cannot find connected address for packet from %s "
1875: "port %d on interface %s",
1876: inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
1877: return -1;
1878: }
1879:
1880: /* Packet length check. */
1881: if (len < RIP_PACKET_MINSIZ)
1882: {
1883: zlog_warn ("packet size %d is smaller than minimum size %d",
1884: len, RIP_PACKET_MINSIZ);
1885: rip_peer_bad_packet (&from);
1886: return len;
1887: }
1888: if (len > RIP_PACKET_MAXSIZ)
1889: {
1890: zlog_warn ("packet size %d is larger than max size %d",
1891: len, RIP_PACKET_MAXSIZ);
1892: rip_peer_bad_packet (&from);
1893: return len;
1894: }
1895:
1896: /* Packet alignment check. */
1897: if ((len - RIP_PACKET_MINSIZ) % 20)
1898: {
1899: zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1900: rip_peer_bad_packet (&from);
1901: return len;
1902: }
1903:
1904: /* Set RTE number. */
1905: rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1906:
1907: /* For easy to handle. */
1908: packet = &rip_buf.rip_packet;
1909:
1910: /* RIP version check. */
1911: if (packet->version == 0)
1912: {
1913: zlog_info ("version 0 with command %d received.", packet->command);
1914: rip_peer_bad_packet (&from);
1915: return -1;
1916: }
1917:
1918: /* Dump RIP packet. */
1919: if (IS_RIP_DEBUG_RECV)
1920: rip_packet_dump (packet, len, "RECV");
1921:
1922: /* RIP version adjust. This code should rethink now. RFC1058 says
1923: that "Version 1 implementations are to ignore this extra data and
1924: process only the fields specified in this document.". So RIPv3
1925: packet should be treated as RIPv1 ignoring must be zero field. */
1926: if (packet->version > RIPv2)
1927: packet->version = RIPv2;
1928:
1929: /* Is RIP running or is this RIP neighbor ?*/
1930: ri = ifp->info;
1931: if (! ri->running && ! rip_neighbor_lookup (&from))
1932: {
1933: if (IS_RIP_DEBUG_EVENT)
1934: zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
1935: rip_peer_bad_packet (&from);
1936: return -1;
1937: }
1938:
1939: /* RIP Version check. RFC2453, 4.6 and 5.1 */
1940: vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1941: rip->version_recv : ri->ri_receive);
1942: if ((packet->version == RIPv1) && !(vrecv & RIPv1))
1943: {
1944: if (IS_RIP_DEBUG_PACKET)
1945: zlog_debug (" packet's v%d doesn't fit to if version spec",
1946: packet->version);
1947: rip_peer_bad_packet (&from);
1948: return -1;
1949: }
1950: if ((packet->version == RIPv2) && !(vrecv & RIPv2))
1951: {
1952: if (IS_RIP_DEBUG_PACKET)
1953: zlog_debug (" packet's v%d doesn't fit to if version spec",
1954: packet->version);
1955: rip_peer_bad_packet (&from);
1956: return -1;
1957: }
1958:
1959: /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1960: messages, then RIP-1 and unauthenticated RIP-2 messages will be
1961: accepted; authenticated RIP-2 messages shall be discarded. */
1962: if ((ri->auth_type == RIP_NO_AUTH)
1963: && rtenum
1964: && (packet->version == RIPv2)
1965: && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
1966: {
1967: if (IS_RIP_DEBUG_EVENT)
1968: zlog_debug ("packet RIPv%d is dropped because authentication disabled",
1969: packet->version);
1970: rip_peer_bad_packet (&from);
1971: return -1;
1972: }
1973:
1974: /* RFC:
1975: If the router is configured to authenticate RIP-2 messages, then
1976: RIP-1 messages and RIP-2 messages which pass authentication
1977: testing shall be accepted; unauthenticated and failed
1978: authentication RIP-2 messages shall be discarded. For maximum
1979: security, RIP-1 messages should be ignored when authentication is
1980: in use (see section 4.1); otherwise, the routing information from
1981: authenticated messages will be propagated by RIP-1 routers in an
1982: unauthenticated manner.
1983: */
1984: /* We make an exception for RIPv1 REQUEST packets, to which we'll
1985: * always reply regardless of authentication settings, because:
1986: *
1987: * - if there other authorised routers on-link, the REQUESTor can
1988: * passively obtain the routing updates anyway
1989: * - if there are no other authorised routers on-link, RIP can
1990: * easily be disabled for the link to prevent giving out information
1991: * on state of this routers RIP routing table..
1992: *
1993: * I.e. if RIPv1 has any place anymore these days, it's as a very
1994: * simple way to distribute routing information (e.g. to embedded
1995: * hosts / appliances) and the ability to give out RIPv1
1996: * routing-information freely, while still requiring RIPv2
1997: * authentication for any RESPONSEs might be vaguely useful.
1998: */
1999: if (ri->auth_type != RIP_NO_AUTH
2000: && packet->version == RIPv1)
2001: {
2002: /* Discard RIPv1 messages other than REQUESTs */
2003: if (packet->command != RIP_REQUEST)
2004: {
2005: if (IS_RIP_DEBUG_PACKET)
2006: zlog_debug ("RIPv1" " dropped because authentication enabled");
2007: rip_peer_bad_packet (&from);
2008: return -1;
2009: }
2010: }
2011: else if (ri->auth_type != RIP_NO_AUTH)
2012: {
2013: const char *auth_desc;
2014:
2015: if (rtenum == 0)
2016: {
2017: /* There definitely is no authentication in the packet. */
2018: if (IS_RIP_DEBUG_PACKET)
2019: zlog_debug ("RIPv2 authentication failed: no auth RTE in packet");
2020: rip_peer_bad_packet (&from);
2021: return -1;
2022: }
2023:
2024: /* First RTE must be an Authentication Family RTE */
2025: if (packet->rte->family != htons(RIP_FAMILY_AUTH))
2026: {
2027: if (IS_RIP_DEBUG_PACKET)
2028: zlog_debug ("RIPv2" " dropped because authentication enabled");
2029: rip_peer_bad_packet (&from);
2030: return -1;
2031: }
2032:
2033: /* Check RIPv2 authentication. */
2034: switch (ntohs(packet->rte->tag))
2035: {
2036: case RIP_AUTH_SIMPLE_PASSWORD:
2037: auth_desc = "simple";
2038: ret = rip_auth_simple_password (packet->rte, &from, ifp);
2039: break;
2040:
2041: case RIP_AUTH_MD5:
2042: auth_desc = "MD5";
2043: ret = rip_auth_md5 (packet, &from, len, ifp);
2044: /* Reset RIP packet length to trim MD5 data. */
2045: len = ret;
2046: break;
2047:
2048: default:
2049: ret = 0;
2050: auth_desc = "unknown type";
2051: if (IS_RIP_DEBUG_PACKET)
2052: zlog_debug ("RIPv2 Unknown authentication type %d",
2053: ntohs (packet->rte->tag));
2054: }
2055:
2056: if (ret)
2057: {
2058: if (IS_RIP_DEBUG_PACKET)
2059: zlog_debug ("RIPv2 %s authentication success", auth_desc);
2060: }
2061: else
2062: {
2063: if (IS_RIP_DEBUG_PACKET)
2064: zlog_debug ("RIPv2 %s authentication failure", auth_desc);
2065: rip_peer_bad_packet (&from);
2066: return -1;
2067: }
2068: }
2069:
2070: /* Process each command. */
2071: switch (packet->command)
2072: {
2073: case RIP_RESPONSE:
2074: rip_response_process (packet, len, &from, ifc);
2075: break;
2076: case RIP_REQUEST:
2077: case RIP_POLL:
2078: rip_request_process (packet, len, &from, ifc);
2079: break;
2080: case RIP_TRACEON:
2081: case RIP_TRACEOFF:
2082: zlog_info ("Obsolete command %s received, please sent it to routed",
2083: lookup (rip_msg, packet->command));
2084: rip_peer_bad_packet (&from);
2085: break;
2086: case RIP_POLL_ENTRY:
2087: zlog_info ("Obsolete command %s received",
2088: lookup (rip_msg, packet->command));
2089: rip_peer_bad_packet (&from);
2090: break;
2091: default:
2092: zlog_info ("Unknown RIP command %d received", packet->command);
2093: rip_peer_bad_packet (&from);
2094: break;
2095: }
2096:
2097: return len;
2098: }
2099:
2100: /* Write routing table entry to the stream and return next index of
2101: the routing table entry in the stream. */
2102: static int
2103: rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2104: u_char version, struct rip_info *rinfo)
2105: {
2106: struct in_addr mask;
2107:
2108: /* Write routing table entry. */
2109: if (version == RIPv1)
2110: {
2111: stream_putw (s, AF_INET);
2112: stream_putw (s, 0);
2113: stream_put_ipv4 (s, p->prefix.s_addr);
2114: stream_put_ipv4 (s, 0);
2115: stream_put_ipv4 (s, 0);
2116: stream_putl (s, rinfo->metric_out);
2117: }
2118: else
2119: {
2120: masklen2ip (p->prefixlen, &mask);
2121:
2122: stream_putw (s, AF_INET);
2123: stream_putw (s, rinfo->tag_out);
2124: stream_put_ipv4 (s, p->prefix.s_addr);
2125: stream_put_ipv4 (s, mask.s_addr);
2126: stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2127: stream_putl (s, rinfo->metric_out);
2128: }
2129:
2130: return ++num;
2131: }
2132:
2133: /* Send update to the ifp or spcified neighbor. */
2134: void
2135: rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2136: int route_type, u_char version)
2137: {
2138: int ret;
2139: struct stream *s;
2140: struct route_node *rp;
2141: struct rip_info *rinfo;
2142: struct rip_interface *ri;
2143: struct prefix_ipv4 *p;
2144: struct prefix_ipv4 classfull;
2145: struct prefix_ipv4 ifaddrclass;
2146: struct key *key = NULL;
2147: /* this might need to made dynamic if RIP ever supported auth methods
2148: with larger key string sizes */
2149: char auth_str[RIP_AUTH_SIMPLE_SIZE];
2150: size_t doff = 0; /* offset of digest offset field */
2151: int num = 0;
2152: int rtemax;
2153: int subnetted = 0;
2154:
2155: /* Logging output event. */
2156: if (IS_RIP_DEBUG_EVENT)
2157: {
2158: if (to)
2159: zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2160: else
2161: zlog_debug ("update routes on interface %s ifindex %d",
2162: ifc->ifp->name, ifc->ifp->ifindex);
2163: }
2164:
2165: /* Set output stream. */
2166: s = rip->obuf;
2167:
2168: /* Reset stream and RTE counter. */
2169: stream_reset (s);
2170: rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2171:
2172: /* Get RIP interface. */
2173: ri = ifc->ifp->info;
2174:
2175: /* If output interface is in simple password authentication mode, we
2176: need space for authentication data. */
2177: if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2178: rtemax -= 1;
2179:
2180: /* If output interface is in MD5 authentication mode, we need space
2181: for authentication header and data. */
2182: if (ri->auth_type == RIP_AUTH_MD5)
2183: rtemax -= 2;
2184:
2185: /* If output interface is in simple password authentication mode
2186: and string or keychain is specified we need space for auth. data */
2187: if (ri->auth_type != RIP_NO_AUTH)
2188: {
2189: if (ri->key_chain)
2190: {
2191: struct keychain *keychain;
2192:
2193: keychain = keychain_lookup (ri->key_chain);
2194: if (keychain)
2195: key = key_lookup_for_send (keychain);
2196: }
2197: /* to be passed to auth functions later */
2198: rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
2199: }
2200:
2201: if (version == RIPv1)
2202: {
2203: memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
2204: apply_classful_mask_ipv4 (&ifaddrclass);
2205: subnetted = 0;
2206: if (ifc->address->prefixlen > ifaddrclass.prefixlen)
2207: subnetted = 1;
2208: }
2209:
2210: for (rp = route_top (rip->table); rp; rp = route_next (rp))
2211: if ((rinfo = rp->info) != NULL)
2212: {
2213: /* For RIPv1, if we are subnetted, output subnets in our network */
2214: /* that have the same mask as the output "interface". For other */
2215: /* networks, only the classfull version is output. */
2216:
2217: if (version == RIPv1)
2218: {
2219: p = (struct prefix_ipv4 *) &rp->p;
2220:
2221: if (IS_RIP_DEBUG_PACKET)
2222: zlog_debug("RIPv1 mask check, %s/%d considered for output",
2223: inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
2224:
2225: if (subnetted &&
2226: prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2227: {
2228: if ((ifc->address->prefixlen != rp->p.prefixlen) &&
2229: (rp->p.prefixlen != 32))
2230: continue;
2231: }
2232: else
2233: {
2234: memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2235: apply_classful_mask_ipv4(&classfull);
2236: if (rp->p.u.prefix4.s_addr != 0 &&
2237: classfull.prefixlen != rp->p.prefixlen)
2238: continue;
2239: }
2240: if (IS_RIP_DEBUG_PACKET)
2241: zlog_debug("RIPv1 mask check, %s/%d made it through",
2242: inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
2243: }
2244: else
2245: p = (struct prefix_ipv4 *) &rp->p;
2246:
2247: /* Apply output filters. */
2248: ret = rip_outgoing_filter (p, ri);
2249: if (ret < 0)
2250: continue;
2251:
2252: /* Changed route only output. */
2253: if (route_type == rip_changed_route &&
2254: (! (rinfo->flags & RIP_RTF_CHANGED)))
2255: continue;
2256:
2257: /* Split horizon. */
2258: /* if (split_horizon == rip_split_horizon) */
2259: if (ri->split_horizon == RIP_SPLIT_HORIZON)
2260: {
2261: /*
2262: * We perform split horizon for RIP and connected route.
2263: * For rip routes, we want to suppress the route if we would
2264: * end up sending the route back on the interface that we
2265: * learned it from, with a higher metric. For connected routes,
2266: * we suppress the route if the prefix is a subset of the
2267: * source address that we are going to use for the packet
2268: * (in order to handle the case when multiple subnets are
2269: * configured on the same interface).
2270: */
2271: if (rinfo->type == ZEBRA_ROUTE_RIP &&
2272: rinfo->ifindex == ifc->ifp->ifindex)
2273: continue;
2274: if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2275: prefix_match((struct prefix *)p, ifc->address))
2276: continue;
2277: }
2278:
2279: /* Preparation for route-map. */
2280: rinfo->metric_set = 0;
2281: rinfo->nexthop_out.s_addr = 0;
2282: rinfo->metric_out = rinfo->metric;
2283: rinfo->tag_out = rinfo->tag;
2284: rinfo->ifindex_out = ifc->ifp->ifindex;
2285:
2286: /* In order to avoid some local loops,
2287: * if the RIP route has a nexthop via this interface, keep the nexthop,
2288: * otherwise set it to 0. The nexthop should not be propagated
2289: * beyond the local broadcast/multicast area in order
2290: * to avoid an IGP multi-level recursive look-up.
2291: * see (4.4)
2292: */
2293: if (rinfo->ifindex == ifc->ifp->ifindex)
2294: rinfo->nexthop_out = rinfo->nexthop;
2295:
2296: /* Interface route-map */
2297: if (ri->routemap[RIP_FILTER_OUT])
2298: {
2299: ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2300: (struct prefix *) p, RMAP_RIP,
2301: rinfo);
2302:
2303: if (ret == RMAP_DENYMATCH)
2304: {
2305: if (IS_RIP_DEBUG_PACKET)
2306: zlog_debug ("RIP %s/%d is filtered by route-map out",
2307: inet_ntoa (p->prefix), p->prefixlen);
2308: continue;
2309: }
2310: }
2311:
2312: /* Apply redistribute route map - continue, if deny */
2313: if (rip->route_map[rinfo->type].name
2314: && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2315: {
2316: ret = route_map_apply (rip->route_map[rinfo->type].map,
2317: (struct prefix *)p, RMAP_RIP, rinfo);
2318:
2319: if (ret == RMAP_DENYMATCH)
2320: {
2321: if (IS_RIP_DEBUG_PACKET)
2322: zlog_debug ("%s/%d is filtered by route-map",
2323: inet_ntoa (p->prefix), p->prefixlen);
2324: continue;
2325: }
2326: }
2327:
2328: /* When route-map does not set metric. */
2329: if (! rinfo->metric_set)
2330: {
2331: /* If redistribute metric is set. */
2332: if (rip->route_map[rinfo->type].metric_config
2333: && rinfo->metric != RIP_METRIC_INFINITY)
2334: {
2335: rinfo->metric_out = rip->route_map[rinfo->type].metric;
2336: }
2337: else
2338: {
2339: /* If the route is not connected or localy generated
2340: one, use default-metric value*/
2341: if (rinfo->type != ZEBRA_ROUTE_RIP
2342: && rinfo->type != ZEBRA_ROUTE_CONNECT
2343: && rinfo->metric != RIP_METRIC_INFINITY)
2344: rinfo->metric_out = rip->default_metric;
2345: }
2346: }
2347:
2348: /* Apply offset-list */
2349: if (rinfo->metric != RIP_METRIC_INFINITY)
2350: rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
2351:
2352: if (rinfo->metric_out > RIP_METRIC_INFINITY)
2353: rinfo->metric_out = RIP_METRIC_INFINITY;
2354:
2355: /* Perform split-horizon with poisoned reverse
2356: * for RIP and connected routes.
2357: **/
2358: if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
2359: /*
2360: * We perform split horizon for RIP and connected route.
2361: * For rip routes, we want to suppress the route if we would
2362: * end up sending the route back on the interface that we
2363: * learned it from, with a higher metric. For connected routes,
2364: * we suppress the route if the prefix is a subset of the
2365: * source address that we are going to use for the packet
2366: * (in order to handle the case when multiple subnets are
2367: * configured on the same interface).
2368: */
2369: if (rinfo->type == ZEBRA_ROUTE_RIP &&
2370: rinfo->ifindex == ifc->ifp->ifindex)
2371: rinfo->metric_out = RIP_METRIC_INFINITY;
2372: if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2373: prefix_match((struct prefix *)p, ifc->address))
2374: rinfo->metric_out = RIP_METRIC_INFINITY;
2375: }
2376:
2377: /* Prepare preamble, auth headers, if needs be */
2378: if (num == 0)
2379: {
2380: stream_putc (s, RIP_RESPONSE);
2381: stream_putc (s, version);
2382: stream_putw (s, 0);
2383:
2384: /* auth header for !v1 && !no_auth */
2385: if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
2386: doff = rip_auth_header_write (s, ri, key, auth_str,
2387: RIP_AUTH_SIMPLE_SIZE);
2388: }
2389:
2390: /* Write RTE to the stream. */
2391: num = rip_write_rte (num, s, p, version, rinfo);
2392: if (num == rtemax)
2393: {
2394: if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2395: rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
2396:
2397: ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
2398: to, ifc);
2399:
2400: if (ret >= 0 && IS_RIP_DEBUG_SEND)
2401: rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2402: stream_get_endp(s), "SEND");
2403: num = 0;
2404: stream_reset (s);
2405: }
2406: }
2407:
2408: /* Flush unwritten RTE. */
2409: if (num != 0)
2410: {
2411: if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2412: rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
2413:
2414: ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
2415:
2416: if (ret >= 0 && IS_RIP_DEBUG_SEND)
2417: rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2418: stream_get_endp (s), "SEND");
2419: num = 0;
2420: stream_reset (s);
2421: }
2422:
2423: /* Statistics updates. */
2424: ri->sent_updates++;
2425: }
2426:
2427: /* Send RIP packet to the interface. */
2428: static void
2429: rip_update_interface (struct connected *ifc, u_char version, int route_type)
2430: {
2431: struct sockaddr_in to;
2432:
2433: /* When RIP version is 2 and multicast enable interface. */
2434: if (version == RIPv2 && if_is_multicast (ifc->ifp))
2435: {
2436: if (IS_RIP_DEBUG_EVENT)
2437: zlog_debug ("multicast announce on %s ", ifc->ifp->name);
2438:
2439: rip_output_process (ifc, NULL, route_type, version);
2440: return;
2441: }
2442:
2443: /* If we can't send multicast packet, send it with unicast. */
2444: if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
2445: {
2446: if (ifc->address->family == AF_INET)
2447: {
2448: /* Destination address and port setting. */
2449: memset (&to, 0, sizeof (struct sockaddr_in));
2450: if (ifc->destination)
2451: /* use specified broadcast or peer destination addr */
2452: to.sin_addr = ifc->destination->u.prefix4;
2453: else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
2454: /* calculate the appropriate broadcast address */
2455: to.sin_addr.s_addr =
2456: ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2457: ifc->address->prefixlen);
2458: else
2459: /* do not know where to send the packet */
2460: return;
2461: to.sin_port = htons (RIP_PORT_DEFAULT);
2462:
2463: if (IS_RIP_DEBUG_EVENT)
2464: zlog_debug("%s announce to %s on %s",
2465: CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
2466: inet_ntoa (to.sin_addr), ifc->ifp->name);
2467:
2468: rip_output_process (ifc, &to, route_type, version);
2469: }
2470: }
2471: }
2472:
2473: /* Update send to all interface and neighbor. */
2474: static void
2475: rip_update_process (int route_type)
2476: {
2477: struct listnode *node;
2478: struct listnode *ifnode, *ifnnode;
2479: struct connected *connected;
2480: struct interface *ifp;
2481: struct rip_interface *ri;
2482: struct route_node *rp;
2483: struct sockaddr_in to;
2484: struct prefix_ipv4 *p;
2485:
2486: /* Send RIP update to each interface. */
2487: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2488: {
2489: if (if_is_loopback (ifp))
2490: continue;
2491:
2492: if (! if_is_operative (ifp))
2493: continue;
2494:
2495: /* Fetch RIP interface information. */
2496: ri = ifp->info;
2497:
2498: /* When passive interface is specified, suppress announce to the
2499: interface. */
2500: if (ri->passive)
2501: continue;
2502:
2503: if (ri->running)
2504: {
2505: /*
2506: * If there is no version configuration in the interface,
2507: * use rip's version setting.
2508: */
2509: int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2510: rip->version_send : ri->ri_send);
2511:
2512: if (IS_RIP_DEBUG_EVENT)
2513: zlog_debug("SEND UPDATE to %s ifindex %d",
2514: (ifp->name ? ifp->name : "_unknown_"), ifp->ifindex);
2515:
2516: /* send update on each connected network */
2517: for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
2518: {
2519: if (connected->address->family == AF_INET)
2520: {
2521: if (vsend & RIPv1)
2522: rip_update_interface (connected, RIPv1, route_type);
2523: if ((vsend & RIPv2) && if_is_multicast(ifp))
2524: rip_update_interface (connected, RIPv2, route_type);
2525: }
2526: }
2527: }
2528: }
2529:
2530: /* RIP send updates to each neighbor. */
2531: for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2532: if (rp->info != NULL)
2533: {
2534: p = (struct prefix_ipv4 *) &rp->p;
2535:
2536: ifp = if_lookup_address (p->prefix);
2537: if (! ifp)
2538: {
2539: zlog_warn ("Neighbor %s doesnt have connected interface!",
2540: inet_ntoa (p->prefix));
2541: continue;
2542: }
2543:
2544: if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2545: {
2546: zlog_warn ("Neighbor %s doesnt have connected network",
2547: inet_ntoa (p->prefix));
2548: continue;
2549: }
2550:
2551: /* Set destination address and port */
2552: memset (&to, 0, sizeof (struct sockaddr_in));
2553: to.sin_addr = p->prefix;
2554: to.sin_port = htons (RIP_PORT_DEFAULT);
2555:
2556: /* RIP version is rip's configuration. */
2557: rip_output_process (connected, &to, route_type, rip->version_send);
2558: }
2559: }
2560:
2561: /* RIP's periodical timer. */
2562: static int
2563: rip_update (struct thread *t)
2564: {
2565: /* Clear timer pointer. */
2566: rip->t_update = NULL;
2567:
2568: if (IS_RIP_DEBUG_EVENT)
2569: zlog_debug ("update timer fire!");
2570:
2571: /* Process update output. */
2572: rip_update_process (rip_all_route);
2573:
2574: /* Triggered updates may be suppressed if a regular update is due by
2575: the time the triggered update would be sent. */
2576: if (rip->t_triggered_interval)
2577: {
2578: thread_cancel (rip->t_triggered_interval);
2579: rip->t_triggered_interval = NULL;
2580: }
2581: rip->trigger = 0;
2582:
2583: /* Register myself. */
2584: rip_event (RIP_UPDATE_EVENT, 0);
2585:
2586: return 0;
2587: }
2588:
2589: /* Walk down the RIP routing table then clear changed flag. */
2590: static void
2591: rip_clear_changed_flag (void)
2592: {
2593: struct route_node *rp;
2594: struct rip_info *rinfo;
2595:
2596: for (rp = route_top (rip->table); rp; rp = route_next (rp))
2597: if ((rinfo = rp->info) != NULL)
2598: if (rinfo->flags & RIP_RTF_CHANGED)
2599: rinfo->flags &= ~RIP_RTF_CHANGED;
2600: }
2601:
2602: /* Triggered update interval timer. */
2603: static int
2604: rip_triggered_interval (struct thread *t)
2605: {
2606: int rip_triggered_update (struct thread *);
2607:
2608: rip->t_triggered_interval = NULL;
2609:
2610: if (rip->trigger)
2611: {
2612: rip->trigger = 0;
2613: rip_triggered_update (t);
2614: }
2615: return 0;
2616: }
2617:
2618: /* Execute triggered update. */
2619: static int
2620: rip_triggered_update (struct thread *t)
2621: {
2622: int interval;
2623:
2624: /* Clear thred pointer. */
2625: rip->t_triggered_update = NULL;
2626:
2627: /* Cancel interval timer. */
2628: if (rip->t_triggered_interval)
2629: {
2630: thread_cancel (rip->t_triggered_interval);
2631: rip->t_triggered_interval = NULL;
2632: }
2633: rip->trigger = 0;
2634:
2635: /* Logging triggered update. */
2636: if (IS_RIP_DEBUG_EVENT)
2637: zlog_debug ("triggered update!");
2638:
2639: /* Split Horizon processing is done when generating triggered
2640: updates as well as normal updates (see section 2.6). */
2641: rip_update_process (rip_changed_route);
2642:
2643: /* Once all of the triggered updates have been generated, the route
2644: change flags should be cleared. */
2645: rip_clear_changed_flag ();
2646:
2647: /* After a triggered update is sent, a timer should be set for a
2648: random interval between 1 and 5 seconds. If other changes that
2649: would trigger updates occur before the timer expires, a single
2650: update is triggered when the timer expires. */
2651: interval = (random () % 5) + 1;
2652:
2653: rip->t_triggered_interval =
2654: thread_add_timer (master, rip_triggered_interval, NULL, interval);
2655:
2656: return 0;
2657: }
2658:
2659: /* Withdraw redistributed route. */
2660: void
2661: rip_redistribute_withdraw (int type)
2662: {
2663: struct route_node *rp;
2664: struct rip_info *rinfo;
2665:
2666: if (!rip)
2667: return;
2668:
2669: for (rp = route_top (rip->table); rp; rp = route_next (rp))
2670: if ((rinfo = rp->info) != NULL)
2671: {
2672: if (rinfo->type == type
2673: && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2674: {
2675: /* Perform poisoned reverse. */
2676: rinfo->metric = RIP_METRIC_INFINITY;
2677: RIP_TIMER_ON (rinfo->t_garbage_collect,
2678: rip_garbage_collect, rip->garbage_time);
2679: RIP_TIMER_OFF (rinfo->t_timeout);
2680: rinfo->flags |= RIP_RTF_CHANGED;
2681:
2682: if (IS_RIP_DEBUG_EVENT) {
2683: struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2684:
2685: zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2686: inet_ntoa(p->prefix), p->prefixlen,
2687: ifindex2ifname(rinfo->ifindex));
2688: }
2689:
2690: rip_event (RIP_TRIGGERED_UPDATE, 0);
2691: }
2692: }
2693: }
2694:
2695: /* Create new RIP instance and set it to global variable. */
2696: static int
2697: rip_create (void)
2698: {
2699: rip = XCALLOC (MTYPE_RIP, sizeof (struct rip));
2700:
2701: /* Set initial value. */
2702: rip->version_send = RI_RIP_VERSION_2;
2703: rip->version_recv = RI_RIP_VERSION_1_AND_2;
2704: rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2705: rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2706: rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2707: rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2708:
2709: /* Initialize RIP routig table. */
2710: rip->table = route_table_init ();
2711: rip->route = route_table_init ();
2712: rip->neighbor = route_table_init ();
2713:
2714: /* Make output stream. */
2715: rip->obuf = stream_new (1500);
2716:
2717: /* Make socket. */
2718: rip->sock = rip_create_socket (NULL);
2719: if (rip->sock < 0)
2720: return rip->sock;
2721:
2722: /* Create read and timer thread. */
2723: rip_event (RIP_READ, rip->sock);
2724: rip_event (RIP_UPDATE_EVENT, 1);
2725:
2726: return 0;
2727: }
2728:
2729: /* Sned RIP request to the destination. */
2730: int
2731: rip_request_send (struct sockaddr_in *to, struct interface *ifp,
2732: u_char version, struct connected *connected)
2733: {
2734: struct rte *rte;
2735: struct rip_packet rip_packet;
2736: struct listnode *node, *nnode;
2737:
2738: memset (&rip_packet, 0, sizeof (rip_packet));
2739:
2740: rip_packet.command = RIP_REQUEST;
2741: rip_packet.version = version;
2742: rte = rip_packet.rte;
2743: rte->metric = htonl (RIP_METRIC_INFINITY);
2744:
2745: if (connected)
2746: {
2747: /*
2748: * connected is only sent for ripv1 case, or when
2749: * interface does not support multicast. Caller loops
2750: * over each connected address for this case.
2751: */
2752: if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
2753: to, connected) != sizeof (rip_packet))
2754: return -1;
2755: else
2756: return sizeof (rip_packet);
2757: }
2758:
2759: /* send request on each connected network */
2760: for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
2761: {
2762: struct prefix_ipv4 *p;
2763:
2764: p = (struct prefix_ipv4 *) connected->address;
2765:
2766: if (p->family != AF_INET)
2767: continue;
2768:
2769: if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
2770: to, connected) != sizeof (rip_packet))
2771: return -1;
2772: }
2773: return sizeof (rip_packet);
2774: }
2775:
2776: static int
2777: rip_update_jitter (unsigned long time)
2778: {
2779: #define JITTER_BOUND 4
2780: /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2781: Given that, we cannot let time be less than JITTER_BOUND seconds.
2782: The RIPv2 RFC says jitter should be small compared to
2783: update_time. We consider 1/JITTER_BOUND to be small.
2784: */
2785:
2786: int jitter_input = time;
2787: int jitter;
2788:
2789: if (jitter_input < JITTER_BOUND)
2790: jitter_input = JITTER_BOUND;
2791:
2792: jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2793:
2794: return jitter/JITTER_BOUND;
2795: }
2796:
2797: void
2798: rip_event (enum rip_event event, int sock)
2799: {
2800: int jitter = 0;
2801:
2802: switch (event)
2803: {
2804: case RIP_READ:
2805: rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2806: break;
2807: case RIP_UPDATE_EVENT:
2808: if (rip->t_update)
2809: {
2810: thread_cancel (rip->t_update);
2811: rip->t_update = NULL;
2812: }
2813: jitter = rip_update_jitter (rip->update_time);
2814: rip->t_update =
2815: thread_add_timer (master, rip_update, NULL,
2816: sock ? 2 : rip->update_time + jitter);
2817: break;
2818: case RIP_TRIGGERED_UPDATE:
2819: if (rip->t_triggered_interval)
2820: rip->trigger = 1;
2821: else if (! rip->t_triggered_update)
2822: rip->t_triggered_update =
2823: thread_add_event (master, rip_triggered_update, NULL, 0);
2824: break;
2825: default:
2826: break;
2827: }
2828: }
2829:
2830: DEFUN (router_rip,
2831: router_rip_cmd,
2832: "router rip",
2833: "Enable a routing process\n"
2834: "Routing Information Protocol (RIP)\n")
2835: {
2836: int ret;
2837:
2838: /* If rip is not enabled before. */
2839: if (! rip)
2840: {
2841: ret = rip_create ();
2842: if (ret < 0)
2843: {
2844: zlog_info ("Can't create RIP");
2845: return CMD_WARNING;
2846: }
2847: }
2848: vty->node = RIP_NODE;
2849: vty->index = rip;
2850:
2851: return CMD_SUCCESS;
2852: }
2853:
2854: DEFUN (no_router_rip,
2855: no_router_rip_cmd,
2856: "no router rip",
2857: NO_STR
2858: "Enable a routing process\n"
2859: "Routing Information Protocol (RIP)\n")
2860: {
2861: if (rip)
2862: rip_clean ();
2863: return CMD_SUCCESS;
2864: }
2865:
2866: DEFUN (rip_version,
2867: rip_version_cmd,
2868: "version <1-2>",
2869: "Set routing protocol version\n"
2870: "version\n")
2871: {
2872: int version;
2873:
2874: version = atoi (argv[0]);
2875: if (version != RIPv1 && version != RIPv2)
2876: {
2877: vty_out (vty, "invalid rip version %d%s", version,
2878: VTY_NEWLINE);
2879: return CMD_WARNING;
2880: }
2881: rip->version_send = version;
2882: rip->version_recv = version;
2883:
2884: return CMD_SUCCESS;
2885: }
2886:
2887: DEFUN (no_rip_version,
2888: no_rip_version_cmd,
2889: "no version",
2890: NO_STR
2891: "Set routing protocol version\n")
2892: {
2893: /* Set RIP version to the default. */
2894: rip->version_send = RI_RIP_VERSION_2;
2895: rip->version_recv = RI_RIP_VERSION_1_AND_2;
2896:
2897: return CMD_SUCCESS;
2898: }
2899:
2900: ALIAS (no_rip_version,
2901: no_rip_version_val_cmd,
2902: "no version <1-2>",
2903: NO_STR
2904: "Set routing protocol version\n"
2905: "version\n")
2906:
2907: DEFUN (rip_route,
2908: rip_route_cmd,
2909: "route A.B.C.D/M",
2910: "RIP static route configuration\n"
2911: "IP prefix <network>/<length>\n")
2912: {
2913: int ret;
2914: struct prefix_ipv4 p;
2915: struct route_node *node;
2916:
2917: ret = str2prefix_ipv4 (argv[0], &p);
2918: if (ret < 0)
2919: {
2920: vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2921: return CMD_WARNING;
2922: }
2923: apply_mask_ipv4 (&p);
2924:
2925: /* For router rip configuration. */
2926: node = route_node_get (rip->route, (struct prefix *) &p);
2927:
2928: if (node->info)
2929: {
2930: vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2931: route_unlock_node (node);
2932: return CMD_WARNING;
2933: }
2934:
2935: node->info = (char *)"static";
2936:
2937: rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
2938:
2939: return CMD_SUCCESS;
2940: }
2941:
2942: DEFUN (no_rip_route,
2943: no_rip_route_cmd,
2944: "no route A.B.C.D/M",
2945: NO_STR
2946: "RIP static route configuration\n"
2947: "IP prefix <network>/<length>\n")
2948: {
2949: int ret;
2950: struct prefix_ipv4 p;
2951: struct route_node *node;
2952:
2953: ret = str2prefix_ipv4 (argv[0], &p);
2954: if (ret < 0)
2955: {
2956: vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2957: return CMD_WARNING;
2958: }
2959: apply_mask_ipv4 (&p);
2960:
2961: /* For router rip configuration. */
2962: node = route_node_lookup (rip->route, (struct prefix *) &p);
2963: if (! node)
2964: {
2965: vty_out (vty, "Can't find route %s.%s", argv[0],
2966: VTY_NEWLINE);
2967: return CMD_WARNING;
2968: }
2969:
2970: rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2971: route_unlock_node (node);
2972:
2973: node->info = NULL;
2974: route_unlock_node (node);
2975:
2976: return CMD_SUCCESS;
2977: }
2978:
2979: #if 0
2980: static void
2981: rip_update_default_metric (void)
2982: {
2983: struct route_node *np;
2984: struct rip_info *rinfo;
2985:
2986: for (np = route_top (rip->table); np; np = route_next (np))
2987: if ((rinfo = np->info) != NULL)
2988: if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2989: rinfo->metric = rip->default_metric;
2990: }
2991: #endif
2992:
2993: DEFUN (rip_default_metric,
2994: rip_default_metric_cmd,
2995: "default-metric <1-16>",
2996: "Set a metric of redistribute routes\n"
2997: "Default metric\n")
2998: {
2999: if (rip)
3000: {
3001: rip->default_metric = atoi (argv[0]);
3002: /* rip_update_default_metric (); */
3003: }
3004: return CMD_SUCCESS;
3005: }
3006:
3007: DEFUN (no_rip_default_metric,
3008: no_rip_default_metric_cmd,
3009: "no default-metric",
3010: NO_STR
3011: "Set a metric of redistribute routes\n"
3012: "Default metric\n")
3013: {
3014: if (rip)
3015: {
3016: rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3017: /* rip_update_default_metric (); */
3018: }
3019: return CMD_SUCCESS;
3020: }
3021:
3022: ALIAS (no_rip_default_metric,
3023: no_rip_default_metric_val_cmd,
3024: "no default-metric <1-16>",
3025: NO_STR
3026: "Set a metric of redistribute routes\n"
3027: "Default metric\n")
3028:
3029: DEFUN (rip_timers,
3030: rip_timers_cmd,
3031: "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3032: "Adjust routing timers\n"
3033: "Basic routing protocol update timers\n"
3034: "Routing table update timer value in second. Default is 30.\n"
3035: "Routing information timeout timer. Default is 180.\n"
3036: "Garbage collection timer. Default is 120.\n")
3037: {
3038: unsigned long update;
3039: unsigned long timeout;
3040: unsigned long garbage;
3041: char *endptr = NULL;
3042: unsigned long RIP_TIMER_MAX = 2147483647;
3043: unsigned long RIP_TIMER_MIN = 5;
3044:
3045: update = strtoul (argv[0], &endptr, 10);
3046: if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3047: {
3048: vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3049: return CMD_WARNING;
3050: }
3051:
3052: timeout = strtoul (argv[1], &endptr, 10);
3053: if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3054: {
3055: vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3056: return CMD_WARNING;
3057: }
3058:
3059: garbage = strtoul (argv[2], &endptr, 10);
3060: if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3061: {
3062: vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3063: return CMD_WARNING;
3064: }
3065:
3066: /* Set each timer value. */
3067: rip->update_time = update;
3068: rip->timeout_time = timeout;
3069: rip->garbage_time = garbage;
3070:
3071: /* Reset update timer thread. */
3072: rip_event (RIP_UPDATE_EVENT, 0);
3073:
3074: return CMD_SUCCESS;
3075: }
3076:
3077: DEFUN (no_rip_timers,
3078: no_rip_timers_cmd,
3079: "no timers basic",
3080: NO_STR
3081: "Adjust routing timers\n"
3082: "Basic routing protocol update timers\n")
3083: {
3084: /* Set each timer value to the default. */
3085: rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3086: rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3087: rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3088:
3089: /* Reset update timer thread. */
3090: rip_event (RIP_UPDATE_EVENT, 0);
3091:
3092: return CMD_SUCCESS;
3093: }
3094:
3095: ALIAS (no_rip_timers,
3096: no_rip_timers_val_cmd,
3097: "no timers basic <0-65535> <0-65535> <0-65535>",
3098: NO_STR
3099: "Adjust routing timers\n"
3100: "Basic routing protocol update timers\n"
3101: "Routing table update timer value in second. Default is 30.\n"
3102: "Routing information timeout timer. Default is 180.\n"
3103: "Garbage collection timer. Default is 120.\n")
3104:
3105:
3106: struct route_table *rip_distance_table;
3107:
3108: struct rip_distance
3109: {
3110: /* Distance value for the IP source prefix. */
3111: u_char distance;
3112:
3113: /* Name of the access-list to be matched. */
3114: char *access_list;
3115: };
3116:
3117: static struct rip_distance *
3118: rip_distance_new (void)
3119: {
3120: return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3121: }
3122:
3123: static void
3124: rip_distance_free (struct rip_distance *rdistance)
3125: {
3126: XFREE (MTYPE_RIP_DISTANCE, rdistance);
3127: }
3128:
3129: static int
3130: rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3131: const char *access_list_str)
3132: {
3133: int ret;
3134: struct prefix_ipv4 p;
3135: u_char distance;
3136: struct route_node *rn;
3137: struct rip_distance *rdistance;
3138:
3139: ret = str2prefix_ipv4 (ip_str, &p);
3140: if (ret == 0)
3141: {
3142: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3143: return CMD_WARNING;
3144: }
3145:
3146: distance = atoi (distance_str);
3147:
3148: /* Get RIP distance node. */
3149: rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3150: if (rn->info)
3151: {
3152: rdistance = rn->info;
3153: route_unlock_node (rn);
3154: }
3155: else
3156: {
3157: rdistance = rip_distance_new ();
3158: rn->info = rdistance;
3159: }
3160:
3161: /* Set distance value. */
3162: rdistance->distance = distance;
3163:
3164: /* Reset access-list configuration. */
3165: if (rdistance->access_list)
3166: {
3167: free (rdistance->access_list);
3168: rdistance->access_list = NULL;
3169: }
3170: if (access_list_str)
3171: rdistance->access_list = strdup (access_list_str);
3172:
3173: return CMD_SUCCESS;
3174: }
3175:
3176: static int
3177: rip_distance_unset (struct vty *vty, const char *distance_str,
3178: const char *ip_str, const char *access_list_str)
3179: {
3180: int ret;
3181: struct prefix_ipv4 p;
3182: u_char distance;
3183: struct route_node *rn;
3184: struct rip_distance *rdistance;
3185:
3186: ret = str2prefix_ipv4 (ip_str, &p);
3187: if (ret == 0)
3188: {
3189: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3190: return CMD_WARNING;
3191: }
3192:
3193: distance = atoi (distance_str);
3194:
3195: rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3196: if (! rn)
3197: {
3198: vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3199: return CMD_WARNING;
3200: }
3201:
3202: rdistance = rn->info;
3203:
3204: if (rdistance->access_list)
3205: free (rdistance->access_list);
3206: rip_distance_free (rdistance);
3207:
3208: rn->info = NULL;
3209: route_unlock_node (rn);
3210: route_unlock_node (rn);
3211:
3212: return CMD_SUCCESS;
3213: }
3214:
3215: static void
3216: rip_distance_reset (void)
3217: {
3218: struct route_node *rn;
3219: struct rip_distance *rdistance;
3220:
3221: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3222: if ((rdistance = rn->info) != NULL)
3223: {
3224: if (rdistance->access_list)
3225: free (rdistance->access_list);
3226: rip_distance_free (rdistance);
3227: rn->info = NULL;
3228: route_unlock_node (rn);
3229: }
3230: }
3231:
3232: /* Apply RIP information to distance method. */
3233: u_char
3234: rip_distance_apply (struct rip_info *rinfo)
3235: {
3236: struct route_node *rn;
3237: struct prefix_ipv4 p;
3238: struct rip_distance *rdistance;
3239: struct access_list *alist;
3240:
3241: if (! rip)
3242: return 0;
3243:
3244: memset (&p, 0, sizeof (struct prefix_ipv4));
3245: p.family = AF_INET;
3246: p.prefix = rinfo->from;
3247: p.prefixlen = IPV4_MAX_BITLEN;
3248:
3249: /* Check source address. */
3250: rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3251: if (rn)
3252: {
3253: rdistance = rn->info;
3254: route_unlock_node (rn);
3255:
3256: if (rdistance->access_list)
3257: {
3258: alist = access_list_lookup (AFI_IP, rdistance->access_list);
3259: if (alist == NULL)
3260: return 0;
3261: if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3262: return 0;
3263:
3264: return rdistance->distance;
3265: }
3266: else
3267: return rdistance->distance;
3268: }
3269:
3270: if (rip->distance)
3271: return rip->distance;
3272:
3273: return 0;
3274: }
3275:
3276: static void
3277: rip_distance_show (struct vty *vty)
3278: {
3279: struct route_node *rn;
3280: struct rip_distance *rdistance;
3281: int header = 1;
3282: char buf[BUFSIZ];
3283:
3284: vty_out (vty, " Distance: (default is %d)%s",
3285: rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3286: VTY_NEWLINE);
3287:
3288: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3289: if ((rdistance = rn->info) != NULL)
3290: {
3291: if (header)
3292: {
3293: vty_out (vty, " Address Distance List%s",
3294: VTY_NEWLINE);
3295: header = 0;
3296: }
3297: sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3298: vty_out (vty, " %-20s %4d %s%s",
3299: buf, rdistance->distance,
3300: rdistance->access_list ? rdistance->access_list : "",
3301: VTY_NEWLINE);
3302: }
3303: }
3304:
3305: DEFUN (rip_distance,
3306: rip_distance_cmd,
3307: "distance <1-255>",
3308: "Administrative distance\n"
3309: "Distance value\n")
3310: {
3311: rip->distance = atoi (argv[0]);
3312: return CMD_SUCCESS;
3313: }
3314:
3315: DEFUN (no_rip_distance,
3316: no_rip_distance_cmd,
3317: "no distance <1-255>",
3318: NO_STR
3319: "Administrative distance\n"
3320: "Distance value\n")
3321: {
3322: rip->distance = 0;
3323: return CMD_SUCCESS;
3324: }
3325:
3326: DEFUN (rip_distance_source,
3327: rip_distance_source_cmd,
3328: "distance <1-255> A.B.C.D/M",
3329: "Administrative distance\n"
3330: "Distance value\n"
3331: "IP source prefix\n")
3332: {
3333: rip_distance_set (vty, argv[0], argv[1], NULL);
3334: return CMD_SUCCESS;
3335: }
3336:
3337: DEFUN (no_rip_distance_source,
3338: no_rip_distance_source_cmd,
3339: "no distance <1-255> A.B.C.D/M",
3340: NO_STR
3341: "Administrative distance\n"
3342: "Distance value\n"
3343: "IP source prefix\n")
3344: {
3345: rip_distance_unset (vty, argv[0], argv[1], NULL);
3346: return CMD_SUCCESS;
3347: }
3348:
3349: DEFUN (rip_distance_source_access_list,
3350: rip_distance_source_access_list_cmd,
3351: "distance <1-255> A.B.C.D/M WORD",
3352: "Administrative distance\n"
3353: "Distance value\n"
3354: "IP source prefix\n"
3355: "Access list name\n")
3356: {
3357: rip_distance_set (vty, argv[0], argv[1], argv[2]);
3358: return CMD_SUCCESS;
3359: }
3360:
3361: DEFUN (no_rip_distance_source_access_list,
3362: no_rip_distance_source_access_list_cmd,
3363: "no distance <1-255> A.B.C.D/M WORD",
3364: NO_STR
3365: "Administrative distance\n"
3366: "Distance value\n"
3367: "IP source prefix\n"
3368: "Access list name\n")
3369: {
3370: rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3371: return CMD_SUCCESS;
3372: }
3373:
3374: /* Print out routes update time. */
3375: static void
3376: rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3377: {
3378: time_t clock;
3379: struct tm *tm;
3380: #define TIME_BUF 25
3381: char timebuf [TIME_BUF];
3382: struct thread *thread;
3383:
3384: if ((thread = rinfo->t_timeout) != NULL)
3385: {
3386: clock = thread_timer_remain_second (thread);
3387: tm = gmtime (&clock);
3388: strftime (timebuf, TIME_BUF, "%M:%S", tm);
3389: vty_out (vty, "%5s", timebuf);
3390: }
3391: else if ((thread = rinfo->t_garbage_collect) != NULL)
3392: {
3393: clock = thread_timer_remain_second (thread);
3394: tm = gmtime (&clock);
3395: strftime (timebuf, TIME_BUF, "%M:%S", tm);
3396: vty_out (vty, "%5s", timebuf);
3397: }
3398: }
3399:
3400: static const char *
3401: rip_route_type_print (int sub_type)
3402: {
3403: switch (sub_type)
3404: {
3405: case RIP_ROUTE_RTE:
3406: return "n";
3407: case RIP_ROUTE_STATIC:
3408: return "s";
3409: case RIP_ROUTE_DEFAULT:
3410: return "d";
3411: case RIP_ROUTE_REDISTRIBUTE:
3412: return "r";
3413: case RIP_ROUTE_INTERFACE:
3414: return "i";
3415: default:
3416: return "?";
3417: }
3418: }
3419:
3420: DEFUN (show_ip_rip,
3421: show_ip_rip_cmd,
3422: "show ip rip",
3423: SHOW_STR
3424: IP_STR
3425: "Show RIP routes\n")
3426: {
3427: struct route_node *np;
3428: struct rip_info *rinfo;
3429:
3430: if (! rip)
3431: return CMD_SUCCESS;
3432:
3433: vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3434: "Sub-codes:%s"
3435: " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
3436: " (i) - interface%s%s"
3437: " Network Next Hop Metric From Tag Time%s",
3438: VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
3439:
3440: for (np = route_top (rip->table); np; np = route_next (np))
3441: if ((rinfo = np->info) != NULL)
3442: {
3443: int len;
3444:
3445: len = vty_out (vty, "%c(%s) %s/%d",
3446: /* np->lock, For debugging. */
3447: zebra_route_char(rinfo->type),
3448: rip_route_type_print (rinfo->sub_type),
3449: inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3450:
3451: len = 24 - len;
3452:
3453: if (len > 0)
3454: vty_out (vty, "%*s", len, " ");
3455:
3456: if (rinfo->nexthop.s_addr)
3457: vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3458: rinfo->metric);
3459: else
3460: vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3461:
3462: /* Route which exist in kernel routing table. */
3463: if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3464: (rinfo->sub_type == RIP_ROUTE_RTE))
3465: {
3466: vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
3467: vty_out (vty, "%3d ", rinfo->tag);
3468: rip_vty_out_uptime (vty, rinfo);
3469: }
3470: else if (rinfo->metric == RIP_METRIC_INFINITY)
3471: {
3472: vty_out (vty, "self ");
3473: vty_out (vty, "%3d ", rinfo->tag);
3474: rip_vty_out_uptime (vty, rinfo);
3475: }
3476: else
3477: {
3478: if (rinfo->external_metric)
3479: {
3480: len = vty_out (vty, "self (%s:%d)",
3481: zebra_route_string(rinfo->type),
3482: rinfo->external_metric);
3483: len = 16 - len;
3484: if (len > 0)
3485: vty_out (vty, "%*s", len, " ");
3486: }
3487: else
3488: vty_out (vty, "self ");
3489: vty_out (vty, "%3d", rinfo->tag);
3490: }
3491:
3492: vty_out (vty, "%s", VTY_NEWLINE);
3493: }
3494: return CMD_SUCCESS;
3495: }
3496:
3497: /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3498: DEFUN (show_ip_rip_status,
3499: show_ip_rip_status_cmd,
3500: "show ip rip status",
3501: SHOW_STR
3502: IP_STR
3503: "Show RIP routes\n"
3504: "IP routing protocol process parameters and statistics\n")
3505: {
3506: struct listnode *node;
3507: struct interface *ifp;
3508: struct rip_interface *ri;
3509: extern const struct message ri_version_msg[];
3510: const char *send_version;
3511: const char *receive_version;
3512:
3513: if (! rip)
3514: return CMD_SUCCESS;
3515:
3516: vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3517: vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3518: rip->update_time);
3519: vty_out (vty, " next due in %lu seconds%s",
3520: thread_timer_remain_second(rip->t_update),
3521: VTY_NEWLINE);
3522: vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3523: vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3524: VTY_NEWLINE);
3525:
3526: /* Filtering status show. */
3527: config_show_distribute (vty);
3528:
3529: /* Default metric information. */
3530: vty_out (vty, " Default redistribution metric is %d%s",
3531: rip->default_metric, VTY_NEWLINE);
3532:
3533: /* Redistribute information. */
3534: vty_out (vty, " Redistributing:");
3535: config_write_rip_redistribute (vty, 0);
3536: vty_out (vty, "%s", VTY_NEWLINE);
3537:
3538: vty_out (vty, " Default version control: send version %s,",
3539: lookup(ri_version_msg,rip->version_send));
3540: if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3541: vty_out (vty, " receive any version %s", VTY_NEWLINE);
3542: else
3543: vty_out (vty, " receive version %s %s",
3544: lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
3545:
3546: vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3547:
3548: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
3549: {
3550: ri = ifp->info;
3551:
3552: if (!ri->running)
3553: continue;
3554:
3555: if (ri->enable_network || ri->enable_interface)
3556: {
3557: if (ri->ri_send == RI_RIP_UNSPEC)
3558: send_version = lookup (ri_version_msg, rip->version_send);
3559: else
3560: send_version = lookup (ri_version_msg, ri->ri_send);
3561:
3562: if (ri->ri_receive == RI_RIP_UNSPEC)
3563: receive_version = lookup (ri_version_msg, rip->version_recv);
3564: else
3565: receive_version = lookup (ri_version_msg, ri->ri_receive);
3566:
3567: vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3568: send_version,
3569: receive_version,
3570: ri->key_chain ? ri->key_chain : "",
3571: VTY_NEWLINE);
3572: }
3573: }
3574:
3575: vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3576: config_write_rip_network (vty, 0);
3577:
3578: {
3579: int found_passive = 0;
3580: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
3581: {
3582: ri = ifp->info;
3583:
3584: if ((ri->enable_network || ri->enable_interface) && ri->passive)
3585: {
3586: if (!found_passive)
3587: {
3588: vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3589: found_passive = 1;
3590: }
3591: vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3592: }
3593: }
3594: }
3595:
3596: vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3597: vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3598: rip_peer_display (vty);
3599:
3600: rip_distance_show (vty);
3601:
3602: return CMD_SUCCESS;
3603: }
3604:
3605: /* RIP configuration write function. */
3606: static int
3607: config_write_rip (struct vty *vty)
3608: {
3609: int write = 0;
3610: struct route_node *rn;
3611: struct rip_distance *rdistance;
3612:
3613: if (rip)
3614: {
3615: /* Router RIP statement. */
3616: vty_out (vty, "router rip%s", VTY_NEWLINE);
3617: write++;
3618:
3619: /* RIP version statement. Default is RIP version 2. */
3620: if (rip->version_send != RI_RIP_VERSION_2
3621: || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3622: vty_out (vty, " version %d%s", rip->version_send,
3623: VTY_NEWLINE);
3624:
3625: /* RIP timer configuration. */
3626: if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3627: || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3628: || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3629: vty_out (vty, " timers basic %lu %lu %lu%s",
3630: rip->update_time,
3631: rip->timeout_time,
3632: rip->garbage_time,
3633: VTY_NEWLINE);
3634:
3635: /* Default information configuration. */
3636: if (rip->default_information)
3637: {
3638: if (rip->default_information_route_map)
3639: vty_out (vty, " default-information originate route-map %s%s",
3640: rip->default_information_route_map, VTY_NEWLINE);
3641: else
3642: vty_out (vty, " default-information originate%s",
3643: VTY_NEWLINE);
3644: }
3645:
3646: /* Redistribute configuration. */
3647: config_write_rip_redistribute (vty, 1);
3648:
3649: /* RIP offset-list configuration. */
3650: config_write_rip_offset_list (vty);
3651:
3652: /* RIP enabled network and interface configuration. */
3653: config_write_rip_network (vty, 1);
3654:
3655: /* RIP default metric configuration */
3656: if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3657: vty_out (vty, " default-metric %d%s",
3658: rip->default_metric, VTY_NEWLINE);
3659:
3660: /* Distribute configuration. */
3661: write += config_write_distribute (vty);
3662:
3663: /* Interface routemap configuration */
3664: write += config_write_if_rmap (vty);
3665:
3666: /* Distance configuration. */
3667: if (rip->distance)
3668: vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3669:
3670: /* RIP source IP prefix distance configuration. */
3671: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3672: if ((rdistance = rn->info) != NULL)
3673: vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3674: inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3675: rdistance->access_list ? rdistance->access_list : "",
3676: VTY_NEWLINE);
3677:
3678: /* RIP static route configuration. */
3679: for (rn = route_top (rip->route); rn; rn = route_next (rn))
3680: if (rn->info)
3681: vty_out (vty, " route %s/%d%s",
3682: inet_ntoa (rn->p.u.prefix4),
3683: rn->p.prefixlen,
3684: VTY_NEWLINE);
3685:
3686: }
3687: return write;
3688: }
3689:
3690: /* RIP node structure. */
3691: static struct cmd_node rip_node =
3692: {
3693: RIP_NODE,
3694: "%s(config-router)# ",
3695: 1
3696: };
3697:
3698: /* Distribute-list update functions. */
3699: static void
3700: rip_distribute_update (struct distribute *dist)
3701: {
3702: struct interface *ifp;
3703: struct rip_interface *ri;
3704: struct access_list *alist;
3705: struct prefix_list *plist;
3706:
3707: if (! dist->ifname)
3708: return;
3709:
3710: ifp = if_lookup_by_name (dist->ifname);
3711: if (ifp == NULL)
3712: return;
3713:
3714: ri = ifp->info;
3715:
3716: if (dist->list[DISTRIBUTE_IN])
3717: {
3718: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3719: if (alist)
3720: ri->list[RIP_FILTER_IN] = alist;
3721: else
3722: ri->list[RIP_FILTER_IN] = NULL;
3723: }
3724: else
3725: ri->list[RIP_FILTER_IN] = NULL;
3726:
3727: if (dist->list[DISTRIBUTE_OUT])
3728: {
3729: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3730: if (alist)
3731: ri->list[RIP_FILTER_OUT] = alist;
3732: else
3733: ri->list[RIP_FILTER_OUT] = NULL;
3734: }
3735: else
3736: ri->list[RIP_FILTER_OUT] = NULL;
3737:
3738: if (dist->prefix[DISTRIBUTE_IN])
3739: {
3740: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3741: if (plist)
3742: ri->prefix[RIP_FILTER_IN] = plist;
3743: else
3744: ri->prefix[RIP_FILTER_IN] = NULL;
3745: }
3746: else
3747: ri->prefix[RIP_FILTER_IN] = NULL;
3748:
3749: if (dist->prefix[DISTRIBUTE_OUT])
3750: {
3751: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3752: if (plist)
3753: ri->prefix[RIP_FILTER_OUT] = plist;
3754: else
3755: ri->prefix[RIP_FILTER_OUT] = NULL;
3756: }
3757: else
3758: ri->prefix[RIP_FILTER_OUT] = NULL;
3759: }
3760:
3761: void
3762: rip_distribute_update_interface (struct interface *ifp)
3763: {
3764: struct distribute *dist;
3765:
3766: dist = distribute_lookup (ifp->name);
3767: if (dist)
3768: rip_distribute_update (dist);
3769: }
3770:
3771: /* Update all interface's distribute list. */
3772: /* ARGSUSED */
3773: static void
3774: rip_distribute_update_all (struct prefix_list *notused)
3775: {
3776: struct interface *ifp;
3777: struct listnode *node, *nnode;
3778:
3779: for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3780: rip_distribute_update_interface (ifp);
3781: }
3782: /* ARGSUSED */
3783: static void
3784: rip_distribute_update_all_wrapper(struct access_list *notused)
3785: {
3786: rip_distribute_update_all(NULL);
3787: }
3788:
3789: /* Delete all added rip route. */
3790: void
3791: rip_clean (void)
3792: {
3793: int i;
3794: struct route_node *rp;
3795: struct rip_info *rinfo;
3796:
3797: if (rip)
3798: {
3799: /* Clear RIP routes */
3800: for (rp = route_top (rip->table); rp; rp = route_next (rp))
3801: if ((rinfo = rp->info) != NULL)
3802: {
3803: if (rinfo->type == ZEBRA_ROUTE_RIP &&
3804: rinfo->sub_type == RIP_ROUTE_RTE)
3805: rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3806: &rinfo->nexthop, rinfo->metric);
3807:
3808: RIP_TIMER_OFF (rinfo->t_timeout);
3809: RIP_TIMER_OFF (rinfo->t_garbage_collect);
3810:
3811: rp->info = NULL;
3812: route_unlock_node (rp);
3813:
3814: rip_info_free (rinfo);
3815: }
3816:
3817: /* Cancel RIP related timers. */
3818: RIP_TIMER_OFF (rip->t_update);
3819: RIP_TIMER_OFF (rip->t_triggered_update);
3820: RIP_TIMER_OFF (rip->t_triggered_interval);
3821:
3822: /* Cancel read thread. */
3823: if (rip->t_read)
3824: {
3825: thread_cancel (rip->t_read);
3826: rip->t_read = NULL;
3827: }
3828:
3829: /* Close RIP socket. */
3830: if (rip->sock >= 0)
3831: {
3832: close (rip->sock);
3833: rip->sock = -1;
3834: }
3835:
3836: /* Static RIP route configuration. */
3837: for (rp = route_top (rip->route); rp; rp = route_next (rp))
3838: if (rp->info)
3839: {
3840: rp->info = NULL;
3841: route_unlock_node (rp);
3842: }
3843:
3844: /* RIP neighbor configuration. */
3845: for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3846: if (rp->info)
3847: {
3848: rp->info = NULL;
3849: route_unlock_node (rp);
3850: }
3851:
3852: /* Redistribute related clear. */
3853: if (rip->default_information_route_map)
3854: free (rip->default_information_route_map);
3855:
3856: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3857: if (rip->route_map[i].name)
3858: free (rip->route_map[i].name);
3859:
3860: XFREE (MTYPE_ROUTE_TABLE, rip->table);
3861: XFREE (MTYPE_ROUTE_TABLE, rip->route);
3862: XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3863:
3864: XFREE (MTYPE_RIP, rip);
3865: rip = NULL;
3866: }
3867:
3868: rip_clean_network ();
3869: rip_passive_nondefault_clean ();
3870: rip_offset_clean ();
3871: rip_interface_clean ();
3872: rip_distance_reset ();
3873: rip_redistribute_clean ();
3874: }
3875:
3876: /* Reset all values to the default settings. */
3877: void
3878: rip_reset (void)
3879: {
3880: /* Reset global counters. */
3881: rip_global_route_changes = 0;
3882: rip_global_queries = 0;
3883:
3884: /* Call ripd related reset functions. */
3885: rip_debug_reset ();
3886: rip_route_map_reset ();
3887:
3888: /* Call library reset functions. */
3889: vty_reset ();
3890: access_list_reset ();
3891: prefix_list_reset ();
3892:
3893: distribute_list_reset ();
3894:
3895: rip_interface_reset ();
3896: rip_distance_reset ();
3897:
3898: rip_zclient_reset ();
3899: }
3900:
3901: static void
3902: rip_if_rmap_update (struct if_rmap *if_rmap)
3903: {
3904: struct interface *ifp;
3905: struct rip_interface *ri;
3906: struct route_map *rmap;
3907:
3908: ifp = if_lookup_by_name (if_rmap->ifname);
3909: if (ifp == NULL)
3910: return;
3911:
3912: ri = ifp->info;
3913:
3914: if (if_rmap->routemap[IF_RMAP_IN])
3915: {
3916: rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3917: if (rmap)
3918: ri->routemap[IF_RMAP_IN] = rmap;
3919: else
3920: ri->routemap[IF_RMAP_IN] = NULL;
3921: }
3922: else
3923: ri->routemap[RIP_FILTER_IN] = NULL;
3924:
3925: if (if_rmap->routemap[IF_RMAP_OUT])
3926: {
3927: rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3928: if (rmap)
3929: ri->routemap[IF_RMAP_OUT] = rmap;
3930: else
3931: ri->routemap[IF_RMAP_OUT] = NULL;
3932: }
3933: else
3934: ri->routemap[RIP_FILTER_OUT] = NULL;
3935: }
3936:
3937: void
3938: rip_if_rmap_update_interface (struct interface *ifp)
3939: {
3940: struct if_rmap *if_rmap;
3941:
3942: if_rmap = if_rmap_lookup (ifp->name);
3943: if (if_rmap)
3944: rip_if_rmap_update (if_rmap);
3945: }
3946:
3947: static void
3948: rip_routemap_update_redistribute (void)
3949: {
3950: int i;
3951:
3952: if (rip)
3953: {
3954: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3955: {
3956: if (rip->route_map[i].name)
3957: rip->route_map[i].map =
3958: route_map_lookup_by_name (rip->route_map[i].name);
3959: }
3960: }
3961: }
3962:
3963: /* ARGSUSED */
3964: static void
3965: rip_routemap_update (const char *notused)
3966: {
3967: struct interface *ifp;
3968: struct listnode *node, *nnode;
3969:
3970: for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3971: rip_if_rmap_update_interface (ifp);
3972:
3973: rip_routemap_update_redistribute ();
3974: }
3975:
3976: /* Allocate new rip structure and set default value. */
3977: void
3978: rip_init (void)
3979: {
3980: /* Randomize for triggered update random(). */
3981: srand (time (NULL));
3982:
3983: /* Install top nodes. */
3984: install_node (&rip_node, config_write_rip);
3985:
3986: /* Install rip commands. */
3987: install_element (VIEW_NODE, &show_ip_rip_cmd);
3988: install_element (VIEW_NODE, &show_ip_rip_status_cmd);
3989: install_element (ENABLE_NODE, &show_ip_rip_cmd);
3990: install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
3991: install_element (CONFIG_NODE, &router_rip_cmd);
3992: install_element (CONFIG_NODE, &no_router_rip_cmd);
3993:
3994: install_default (RIP_NODE);
3995: install_element (RIP_NODE, &rip_version_cmd);
3996: install_element (RIP_NODE, &no_rip_version_cmd);
3997: install_element (RIP_NODE, &no_rip_version_val_cmd);
3998: install_element (RIP_NODE, &rip_default_metric_cmd);
3999: install_element (RIP_NODE, &no_rip_default_metric_cmd);
4000: install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4001: install_element (RIP_NODE, &rip_timers_cmd);
4002: install_element (RIP_NODE, &no_rip_timers_cmd);
4003: install_element (RIP_NODE, &no_rip_timers_val_cmd);
4004: install_element (RIP_NODE, &rip_route_cmd);
4005: install_element (RIP_NODE, &no_rip_route_cmd);
4006: install_element (RIP_NODE, &rip_distance_cmd);
4007: install_element (RIP_NODE, &no_rip_distance_cmd);
4008: install_element (RIP_NODE, &rip_distance_source_cmd);
4009: install_element (RIP_NODE, &no_rip_distance_source_cmd);
4010: install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4011: install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4012:
4013: /* Debug related init. */
4014: rip_debug_init ();
4015:
4016: /* SNMP init. */
4017: #ifdef HAVE_SNMP
4018: rip_snmp_init ();
4019: #endif /* HAVE_SNMP */
4020:
4021: /* Access list install. */
4022: access_list_init ();
4023: access_list_add_hook (rip_distribute_update_all_wrapper);
4024: access_list_delete_hook (rip_distribute_update_all_wrapper);
4025:
4026: /* Prefix list initialize.*/
4027: prefix_list_init ();
4028: prefix_list_add_hook (rip_distribute_update_all);
4029: prefix_list_delete_hook (rip_distribute_update_all);
4030:
4031: /* Distribute list install. */
4032: distribute_list_init (RIP_NODE);
4033: distribute_list_add_hook (rip_distribute_update);
4034: distribute_list_delete_hook (rip_distribute_update);
4035:
4036: /* Route-map */
4037: rip_route_map_init ();
4038: rip_offset_init ();
4039:
4040: route_map_add_hook (rip_routemap_update);
4041: route_map_delete_hook (rip_routemap_update);
4042:
4043: if_rmap_init (RIP_NODE);
4044: if_rmap_hook_add (rip_if_rmap_update);
4045: if_rmap_hook_delete (rip_if_rmap_update);
4046:
4047: /* Distance control. */
4048: rip_distance_table = route_table_init ();
4049: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>