Annotation of embedaddon/quagga/ripd/ripd.c, revision 1.1.1.2
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 */
1.1.1.2 ! misho 1478: memset (&from, 0, sizeof (from));
1.1 misho 1479: from.sin_family = AF_INET;
1480: from.sin_port = htons (RIP_PORT_DEFAULT);
1481: from.sin_addr = ifc->address->u.prefix4;
1482: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1483: from.sin_len = sizeof (struct sockaddr_in);
1484: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1485:
1486: /*
1487: * we have to open a new socket for each packet because this
1488: * is the most portable way to bind to a different source
1489: * ipv4 address for each packet.
1490: */
1491: if ( (send_sock = rip_create_socket (&from)) < 0)
1492: {
1493: zlog_warn("rip_send_packet could not create socket.");
1494: return -1;
1495: }
1496: rip_interface_multicast_set (send_sock, ifc);
1497: }
1498:
1499: ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
1500: sizeof (struct sockaddr_in));
1501:
1502: if (IS_RIP_DEBUG_EVENT)
1503: zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1504: ntohs (sin.sin_port));
1505:
1506: if (ret < 0)
1507: zlog_warn ("can't send packet : %s", safe_strerror (errno));
1508:
1509: if (!to)
1510: close(send_sock);
1511:
1512: return ret;
1513: }
1514:
1515: /* Add redistributed route to RIP table. */
1516: void
1517: rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1518: unsigned int ifindex, struct in_addr *nexthop,
1519: unsigned int metric, unsigned char distance)
1520: {
1521: int ret;
1522: struct route_node *rp;
1523: struct rip_info *rinfo;
1524:
1525: /* Redistribute route */
1526: ret = rip_destination_check (p->prefix);
1527: if (! ret)
1528: return;
1529:
1530: rp = route_node_get (rip->table, (struct prefix *) p);
1531:
1532: rinfo = rp->info;
1533:
1534: if (rinfo)
1535: {
1536: if (rinfo->type == ZEBRA_ROUTE_CONNECT
1537: && rinfo->sub_type == RIP_ROUTE_INTERFACE
1538: && rinfo->metric != RIP_METRIC_INFINITY)
1539: {
1540: route_unlock_node (rp);
1541: return;
1542: }
1543:
1544: /* Manually configured RIP route check. */
1545: if (rinfo->type == ZEBRA_ROUTE_RIP
1546: && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1547: (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
1548: {
1549: if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1550: (sub_type != RIP_ROUTE_DEFAULT)))
1551: {
1552: route_unlock_node (rp);
1553: return;
1554: }
1555: }
1556:
1557: RIP_TIMER_OFF (rinfo->t_timeout);
1558: RIP_TIMER_OFF (rinfo->t_garbage_collect);
1559:
1560: if (rip_route_rte (rinfo))
1561: rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1562: rinfo->metric);
1563: rp->info = NULL;
1564: rip_info_free (rinfo);
1565:
1566: route_unlock_node (rp);
1567: }
1568:
1569: rinfo = rip_info_new ();
1570:
1571: rinfo->type = type;
1572: rinfo->sub_type = sub_type;
1573: rinfo->ifindex = ifindex;
1574: rinfo->metric = 1;
1575: rinfo->external_metric = metric;
1576: rinfo->distance = distance;
1577: rinfo->rp = rp;
1578:
1579: if (nexthop)
1580: rinfo->nexthop = *nexthop;
1581:
1582: rinfo->flags |= RIP_RTF_FIB;
1583: rp->info = rinfo;
1584:
1585: rinfo->flags |= RIP_RTF_CHANGED;
1586:
1587: if (IS_RIP_DEBUG_EVENT) {
1588: if (!nexthop)
1589: zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
1590: inet_ntoa(p->prefix), p->prefixlen,
1591: ifindex2ifname(ifindex));
1592: else
1593: zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1594: inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1595: ifindex2ifname(ifindex));
1596: }
1597:
1598:
1599: rip_event (RIP_TRIGGERED_UPDATE, 0);
1600: }
1601:
1602: /* Delete redistributed route from RIP table. */
1603: void
1604: rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1605: unsigned int ifindex)
1606: {
1607: int ret;
1608: struct route_node *rp;
1609: struct rip_info *rinfo;
1610:
1611: ret = rip_destination_check (p->prefix);
1612: if (! ret)
1613: return;
1614:
1615: rp = route_node_lookup (rip->table, (struct prefix *) p);
1616: if (rp)
1617: {
1618: rinfo = rp->info;
1619:
1620: if (rinfo != NULL
1621: && rinfo->type == type
1622: && rinfo->sub_type == sub_type
1623: && rinfo->ifindex == ifindex)
1624: {
1625: /* Perform poisoned reverse. */
1626: rinfo->metric = RIP_METRIC_INFINITY;
1627: RIP_TIMER_ON (rinfo->t_garbage_collect,
1628: rip_garbage_collect, rip->garbage_time);
1629: RIP_TIMER_OFF (rinfo->t_timeout);
1630: rinfo->flags |= RIP_RTF_CHANGED;
1631:
1632: if (IS_RIP_DEBUG_EVENT)
1633: zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1634: inet_ntoa(p->prefix), p->prefixlen,
1635: ifindex2ifname(ifindex));
1636:
1637: rip_event (RIP_TRIGGERED_UPDATE, 0);
1638: }
1639: }
1640: }
1641:
1642: /* Response to request called from rip_read ().*/
1643: static void
1644: rip_request_process (struct rip_packet *packet, int size,
1645: struct sockaddr_in *from, struct connected *ifc)
1646: {
1647: caddr_t lim;
1648: struct rte *rte;
1649: struct prefix_ipv4 p;
1650: struct route_node *rp;
1651: struct rip_info *rinfo;
1652: struct rip_interface *ri;
1653:
1654: /* Does not reponse to the requests on the loopback interfaces */
1655: if (if_is_loopback (ifc->ifp))
1656: return;
1657:
1658: /* Check RIP process is enabled on this interface. */
1659: ri = ifc->ifp->info;
1660: if (! ri->running)
1661: return;
1662:
1663: /* When passive interface is specified, suppress responses */
1664: if (ri->passive)
1665: return;
1666:
1667: /* RIP peer update. */
1668: rip_peer_update (from, packet->version);
1669:
1670: lim = ((caddr_t) packet) + size;
1671: rte = packet->rte;
1672:
1673: /* The Request is processed entry by entry. If there are no
1674: entries, no response is given. */
1675: if (lim == (caddr_t) rte)
1676: return;
1677:
1678: /* There is one special case. If there is exactly one entry in the
1679: request, and it has an address family identifier of zero and a
1680: metric of infinity (i.e., 16), then this is a request to send the
1681: entire routing table. */
1682: if (lim == ((caddr_t) (rte + 1)) &&
1683: ntohs (rte->family) == 0 &&
1684: ntohl (rte->metric) == RIP_METRIC_INFINITY)
1685: {
1686: struct prefix_ipv4 saddr;
1687:
1688: /* saddr will be used for determining which routes to split-horizon.
1689: Since the source address we'll pick will be on the same subnet as the
1690: destination, for the purpose of split-horizoning, we'll
1691: pretend that "from" is our source address. */
1692: saddr.family = AF_INET;
1693: saddr.prefixlen = IPV4_MAX_BITLEN;
1694: saddr.prefix = from->sin_addr;
1695:
1696: /* All route with split horizon */
1697: rip_output_process (ifc, from, rip_all_route, packet->version);
1698: }
1699: else
1700: {
1701: /* Examine the list of RTEs in the Request one by one. For each
1702: entry, look up the destination in the router's routing
1703: database and, if there is a route, put that route's metric in
1704: the metric field of the RTE. If there is no explicit route
1705: to the specified destination, put infinity in the metric
1706: field. Once all the entries have been filled in, change the
1707: command from Request to Response and send the datagram back
1708: to the requestor. */
1709: p.family = AF_INET;
1710:
1711: for (; ((caddr_t) rte) < lim; rte++)
1712: {
1713: p.prefix = rte->prefix;
1714: p.prefixlen = ip_masklen (rte->mask);
1715: apply_mask_ipv4 (&p);
1716:
1717: rp = route_node_lookup (rip->table, (struct prefix *) &p);
1718: if (rp)
1719: {
1720: rinfo = rp->info;
1721: rte->metric = htonl (rinfo->metric);
1722: route_unlock_node (rp);
1723: }
1724: else
1725: rte->metric = htonl (RIP_METRIC_INFINITY);
1726: }
1727: packet->command = RIP_RESPONSE;
1728:
1729: rip_send_packet ((u_char *)packet, size, from, ifc);
1730: }
1731: rip_global_queries++;
1732: }
1733:
1734: #if RIP_RECVMSG
1735: /* Set IPv6 packet info to the socket. */
1736: static int
1737: setsockopt_pktinfo (int sock)
1738: {
1739: int ret;
1740: int val = 1;
1741:
1742: ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1743: if (ret < 0)
1744: zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
1745: return ret;
1746: }
1747:
1748: /* Read RIP packet by recvmsg function. */
1749: int
1750: rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1751: int *ifindex)
1752: {
1753: int ret;
1754: struct msghdr msg;
1755: struct iovec iov;
1756: struct cmsghdr *ptr;
1757: char adata[1024];
1758:
1759: msg.msg_name = (void *) from;
1760: msg.msg_namelen = sizeof (struct sockaddr_in);
1761: msg.msg_iov = &iov;
1762: msg.msg_iovlen = 1;
1763: msg.msg_control = (void *) adata;
1764: msg.msg_controllen = sizeof adata;
1765: iov.iov_base = buf;
1766: iov.iov_len = size;
1767:
1768: ret = recvmsg (sock, &msg, 0);
1769: if (ret < 0)
1770: return ret;
1771:
1772: for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1773: if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1774: {
1775: struct in_pktinfo *pktinfo;
1776: int i;
1777:
1778: pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1779: i = pktinfo->ipi_ifindex;
1780: }
1781: return ret;
1782: }
1783:
1784: /* RIP packet read function. */
1785: int
1786: rip_read_new (struct thread *t)
1787: {
1788: int ret;
1789: int sock;
1790: char buf[RIP_PACKET_MAXSIZ];
1791: struct sockaddr_in from;
1792: unsigned int ifindex;
1793:
1794: /* Fetch socket then register myself. */
1795: sock = THREAD_FD (t);
1796: rip_event (RIP_READ, sock);
1797:
1798: /* Read RIP packet. */
1799: ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1800: if (ret < 0)
1801: {
1802: zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
1803: return ret;
1804: }
1805:
1806: return ret;
1807: }
1808: #endif /* RIP_RECVMSG */
1809:
1810: /* First entry point of RIP packet. */
1811: static int
1812: rip_read (struct thread *t)
1813: {
1814: int sock;
1815: int ret;
1816: int rtenum;
1817: union rip_buf rip_buf;
1818: struct rip_packet *packet;
1819: struct sockaddr_in from;
1820: int len;
1821: int vrecv;
1822: socklen_t fromlen;
1823: struct interface *ifp;
1824: struct connected *ifc;
1825: struct rip_interface *ri;
1826:
1827: /* Fetch socket then register myself. */
1828: sock = THREAD_FD (t);
1829: rip->t_read = NULL;
1830:
1831: /* Add myself to tne next event */
1832: rip_event (RIP_READ, sock);
1833:
1834: /* RIPd manages only IPv4. */
1835: memset (&from, 0, sizeof (struct sockaddr_in));
1836: fromlen = sizeof (struct sockaddr_in);
1837:
1838: len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1839: (struct sockaddr *) &from, &fromlen);
1840: if (len < 0)
1841: {
1842: zlog_info ("recvfrom failed: %s", safe_strerror (errno));
1843: return len;
1844: }
1845:
1846: /* Check is this packet comming from myself? */
1847: if (if_check_address (from.sin_addr))
1848: {
1849: if (IS_RIP_DEBUG_PACKET)
1850: zlog_debug ("ignore packet comes from myself");
1851: return -1;
1852: }
1853:
1854: /* Which interface is this packet comes from. */
1855: ifp = if_lookup_address (from.sin_addr);
1856:
1857: /* RIP packet received */
1858: if (IS_RIP_DEBUG_EVENT)
1859: zlog_debug ("RECV packet from %s port %d on %s",
1860: inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1861: ifp ? ifp->name : "unknown");
1862:
1863: /* If this packet come from unknown interface, ignore it. */
1864: if (ifp == NULL)
1865: {
1866: zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1867: inet_ntoa(from.sin_addr), ntohs (from.sin_port));
1868: return -1;
1869: }
1870:
1871: ifc = connected_lookup_address (ifp, from.sin_addr);
1872:
1873: if (ifc == NULL)
1874: {
1875: zlog_info ("rip_read: cannot find connected address for packet from %s "
1876: "port %d on interface %s",
1877: inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
1878: return -1;
1879: }
1880:
1881: /* Packet length check. */
1882: if (len < RIP_PACKET_MINSIZ)
1883: {
1884: zlog_warn ("packet size %d is smaller than minimum size %d",
1885: len, RIP_PACKET_MINSIZ);
1886: rip_peer_bad_packet (&from);
1887: return len;
1888: }
1889: if (len > RIP_PACKET_MAXSIZ)
1890: {
1891: zlog_warn ("packet size %d is larger than max size %d",
1892: len, RIP_PACKET_MAXSIZ);
1893: rip_peer_bad_packet (&from);
1894: return len;
1895: }
1896:
1897: /* Packet alignment check. */
1898: if ((len - RIP_PACKET_MINSIZ) % 20)
1899: {
1900: zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1901: rip_peer_bad_packet (&from);
1902: return len;
1903: }
1904:
1905: /* Set RTE number. */
1906: rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1907:
1908: /* For easy to handle. */
1909: packet = &rip_buf.rip_packet;
1910:
1911: /* RIP version check. */
1912: if (packet->version == 0)
1913: {
1914: zlog_info ("version 0 with command %d received.", packet->command);
1915: rip_peer_bad_packet (&from);
1916: return -1;
1917: }
1918:
1919: /* Dump RIP packet. */
1920: if (IS_RIP_DEBUG_RECV)
1921: rip_packet_dump (packet, len, "RECV");
1922:
1923: /* RIP version adjust. This code should rethink now. RFC1058 says
1924: that "Version 1 implementations are to ignore this extra data and
1925: process only the fields specified in this document.". So RIPv3
1926: packet should be treated as RIPv1 ignoring must be zero field. */
1927: if (packet->version > RIPv2)
1928: packet->version = RIPv2;
1929:
1930: /* Is RIP running or is this RIP neighbor ?*/
1931: ri = ifp->info;
1932: if (! ri->running && ! rip_neighbor_lookup (&from))
1933: {
1934: if (IS_RIP_DEBUG_EVENT)
1935: zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
1936: rip_peer_bad_packet (&from);
1937: return -1;
1938: }
1939:
1940: /* RIP Version check. RFC2453, 4.6 and 5.1 */
1941: vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1942: rip->version_recv : ri->ri_receive);
1943: if ((packet->version == RIPv1) && !(vrecv & RIPv1))
1944: {
1945: if (IS_RIP_DEBUG_PACKET)
1946: zlog_debug (" packet's v%d doesn't fit to if version spec",
1947: packet->version);
1948: rip_peer_bad_packet (&from);
1949: return -1;
1950: }
1951: if ((packet->version == RIPv2) && !(vrecv & RIPv2))
1952: {
1953: if (IS_RIP_DEBUG_PACKET)
1954: zlog_debug (" packet's v%d doesn't fit to if version spec",
1955: packet->version);
1956: rip_peer_bad_packet (&from);
1957: return -1;
1958: }
1959:
1960: /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1961: messages, then RIP-1 and unauthenticated RIP-2 messages will be
1962: accepted; authenticated RIP-2 messages shall be discarded. */
1963: if ((ri->auth_type == RIP_NO_AUTH)
1964: && rtenum
1965: && (packet->version == RIPv2)
1966: && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
1967: {
1968: if (IS_RIP_DEBUG_EVENT)
1969: zlog_debug ("packet RIPv%d is dropped because authentication disabled",
1970: packet->version);
1971: rip_peer_bad_packet (&from);
1972: return -1;
1973: }
1974:
1975: /* RFC:
1976: If the router is configured to authenticate RIP-2 messages, then
1977: RIP-1 messages and RIP-2 messages which pass authentication
1978: testing shall be accepted; unauthenticated and failed
1979: authentication RIP-2 messages shall be discarded. For maximum
1980: security, RIP-1 messages should be ignored when authentication is
1981: in use (see section 4.1); otherwise, the routing information from
1982: authenticated messages will be propagated by RIP-1 routers in an
1983: unauthenticated manner.
1984: */
1985: /* We make an exception for RIPv1 REQUEST packets, to which we'll
1986: * always reply regardless of authentication settings, because:
1987: *
1988: * - if there other authorised routers on-link, the REQUESTor can
1989: * passively obtain the routing updates anyway
1990: * - if there are no other authorised routers on-link, RIP can
1991: * easily be disabled for the link to prevent giving out information
1992: * on state of this routers RIP routing table..
1993: *
1994: * I.e. if RIPv1 has any place anymore these days, it's as a very
1995: * simple way to distribute routing information (e.g. to embedded
1996: * hosts / appliances) and the ability to give out RIPv1
1997: * routing-information freely, while still requiring RIPv2
1998: * authentication for any RESPONSEs might be vaguely useful.
1999: */
2000: if (ri->auth_type != RIP_NO_AUTH
2001: && packet->version == RIPv1)
2002: {
2003: /* Discard RIPv1 messages other than REQUESTs */
2004: if (packet->command != RIP_REQUEST)
2005: {
2006: if (IS_RIP_DEBUG_PACKET)
2007: zlog_debug ("RIPv1" " dropped because authentication enabled");
2008: rip_peer_bad_packet (&from);
2009: return -1;
2010: }
2011: }
2012: else if (ri->auth_type != RIP_NO_AUTH)
2013: {
2014: const char *auth_desc;
2015:
2016: if (rtenum == 0)
2017: {
2018: /* There definitely is no authentication in the packet. */
2019: if (IS_RIP_DEBUG_PACKET)
2020: zlog_debug ("RIPv2 authentication failed: no auth RTE in packet");
2021: rip_peer_bad_packet (&from);
2022: return -1;
2023: }
2024:
2025: /* First RTE must be an Authentication Family RTE */
2026: if (packet->rte->family != htons(RIP_FAMILY_AUTH))
2027: {
2028: if (IS_RIP_DEBUG_PACKET)
2029: zlog_debug ("RIPv2" " dropped because authentication enabled");
2030: rip_peer_bad_packet (&from);
2031: return -1;
2032: }
2033:
2034: /* Check RIPv2 authentication. */
2035: switch (ntohs(packet->rte->tag))
2036: {
2037: case RIP_AUTH_SIMPLE_PASSWORD:
2038: auth_desc = "simple";
2039: ret = rip_auth_simple_password (packet->rte, &from, ifp);
2040: break;
2041:
2042: case RIP_AUTH_MD5:
2043: auth_desc = "MD5";
2044: ret = rip_auth_md5 (packet, &from, len, ifp);
2045: /* Reset RIP packet length to trim MD5 data. */
2046: len = ret;
2047: break;
2048:
2049: default:
2050: ret = 0;
2051: auth_desc = "unknown type";
2052: if (IS_RIP_DEBUG_PACKET)
2053: zlog_debug ("RIPv2 Unknown authentication type %d",
2054: ntohs (packet->rte->tag));
2055: }
2056:
2057: if (ret)
2058: {
2059: if (IS_RIP_DEBUG_PACKET)
2060: zlog_debug ("RIPv2 %s authentication success", auth_desc);
2061: }
2062: else
2063: {
2064: if (IS_RIP_DEBUG_PACKET)
2065: zlog_debug ("RIPv2 %s authentication failure", auth_desc);
2066: rip_peer_bad_packet (&from);
2067: return -1;
2068: }
2069: }
2070:
2071: /* Process each command. */
2072: switch (packet->command)
2073: {
2074: case RIP_RESPONSE:
2075: rip_response_process (packet, len, &from, ifc);
2076: break;
2077: case RIP_REQUEST:
2078: case RIP_POLL:
2079: rip_request_process (packet, len, &from, ifc);
2080: break;
2081: case RIP_TRACEON:
2082: case RIP_TRACEOFF:
2083: zlog_info ("Obsolete command %s received, please sent it to routed",
2084: lookup (rip_msg, packet->command));
2085: rip_peer_bad_packet (&from);
2086: break;
2087: case RIP_POLL_ENTRY:
2088: zlog_info ("Obsolete command %s received",
2089: lookup (rip_msg, packet->command));
2090: rip_peer_bad_packet (&from);
2091: break;
2092: default:
2093: zlog_info ("Unknown RIP command %d received", packet->command);
2094: rip_peer_bad_packet (&from);
2095: break;
2096: }
2097:
2098: return len;
2099: }
2100:
2101: /* Write routing table entry to the stream and return next index of
2102: the routing table entry in the stream. */
2103: static int
2104: rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2105: u_char version, struct rip_info *rinfo)
2106: {
2107: struct in_addr mask;
2108:
2109: /* Write routing table entry. */
2110: if (version == RIPv1)
2111: {
2112: stream_putw (s, AF_INET);
2113: stream_putw (s, 0);
2114: stream_put_ipv4 (s, p->prefix.s_addr);
2115: stream_put_ipv4 (s, 0);
2116: stream_put_ipv4 (s, 0);
2117: stream_putl (s, rinfo->metric_out);
2118: }
2119: else
2120: {
2121: masklen2ip (p->prefixlen, &mask);
2122:
2123: stream_putw (s, AF_INET);
2124: stream_putw (s, rinfo->tag_out);
2125: stream_put_ipv4 (s, p->prefix.s_addr);
2126: stream_put_ipv4 (s, mask.s_addr);
2127: stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2128: stream_putl (s, rinfo->metric_out);
2129: }
2130:
2131: return ++num;
2132: }
2133:
2134: /* Send update to the ifp or spcified neighbor. */
2135: void
2136: rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2137: int route_type, u_char version)
2138: {
2139: int ret;
2140: struct stream *s;
2141: struct route_node *rp;
2142: struct rip_info *rinfo;
2143: struct rip_interface *ri;
2144: struct prefix_ipv4 *p;
2145: struct prefix_ipv4 classfull;
2146: struct prefix_ipv4 ifaddrclass;
2147: struct key *key = NULL;
2148: /* this might need to made dynamic if RIP ever supported auth methods
2149: with larger key string sizes */
2150: char auth_str[RIP_AUTH_SIMPLE_SIZE];
2151: size_t doff = 0; /* offset of digest offset field */
2152: int num = 0;
2153: int rtemax;
2154: int subnetted = 0;
2155:
2156: /* Logging output event. */
2157: if (IS_RIP_DEBUG_EVENT)
2158: {
2159: if (to)
2160: zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2161: else
2162: zlog_debug ("update routes on interface %s ifindex %d",
2163: ifc->ifp->name, ifc->ifp->ifindex);
2164: }
2165:
2166: /* Set output stream. */
2167: s = rip->obuf;
2168:
2169: /* Reset stream and RTE counter. */
2170: stream_reset (s);
2171: rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2172:
2173: /* Get RIP interface. */
2174: ri = ifc->ifp->info;
2175:
2176: /* If output interface is in simple password authentication mode, we
2177: need space for authentication data. */
2178: if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2179: rtemax -= 1;
2180:
2181: /* If output interface is in MD5 authentication mode, we need space
2182: for authentication header and data. */
2183: if (ri->auth_type == RIP_AUTH_MD5)
2184: rtemax -= 2;
2185:
2186: /* If output interface is in simple password authentication mode
2187: and string or keychain is specified we need space for auth. data */
2188: if (ri->auth_type != RIP_NO_AUTH)
2189: {
2190: if (ri->key_chain)
2191: {
2192: struct keychain *keychain;
2193:
2194: keychain = keychain_lookup (ri->key_chain);
2195: if (keychain)
2196: key = key_lookup_for_send (keychain);
2197: }
2198: /* to be passed to auth functions later */
2199: rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
2200: }
2201:
2202: if (version == RIPv1)
2203: {
2204: memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
2205: apply_classful_mask_ipv4 (&ifaddrclass);
2206: subnetted = 0;
2207: if (ifc->address->prefixlen > ifaddrclass.prefixlen)
2208: subnetted = 1;
2209: }
2210:
2211: for (rp = route_top (rip->table); rp; rp = route_next (rp))
2212: if ((rinfo = rp->info) != NULL)
2213: {
2214: /* For RIPv1, if we are subnetted, output subnets in our network */
2215: /* that have the same mask as the output "interface". For other */
2216: /* networks, only the classfull version is output. */
2217:
2218: if (version == RIPv1)
2219: {
2220: p = (struct prefix_ipv4 *) &rp->p;
2221:
2222: if (IS_RIP_DEBUG_PACKET)
2223: zlog_debug("RIPv1 mask check, %s/%d considered for output",
2224: inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
2225:
2226: if (subnetted &&
2227: prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2228: {
2229: if ((ifc->address->prefixlen != rp->p.prefixlen) &&
2230: (rp->p.prefixlen != 32))
2231: continue;
2232: }
2233: else
2234: {
2235: memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2236: apply_classful_mask_ipv4(&classfull);
2237: if (rp->p.u.prefix4.s_addr != 0 &&
2238: classfull.prefixlen != rp->p.prefixlen)
2239: continue;
2240: }
2241: if (IS_RIP_DEBUG_PACKET)
2242: zlog_debug("RIPv1 mask check, %s/%d made it through",
2243: inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
2244: }
2245: else
2246: p = (struct prefix_ipv4 *) &rp->p;
2247:
2248: /* Apply output filters. */
2249: ret = rip_outgoing_filter (p, ri);
2250: if (ret < 0)
2251: continue;
2252:
2253: /* Changed route only output. */
2254: if (route_type == rip_changed_route &&
2255: (! (rinfo->flags & RIP_RTF_CHANGED)))
2256: continue;
2257:
2258: /* Split horizon. */
2259: /* if (split_horizon == rip_split_horizon) */
2260: if (ri->split_horizon == RIP_SPLIT_HORIZON)
2261: {
2262: /*
2263: * We perform split horizon for RIP and connected route.
2264: * For rip routes, we want to suppress the route if we would
2265: * end up sending the route back on the interface that we
2266: * learned it from, with a higher metric. For connected routes,
2267: * we suppress the route if the prefix is a subset of the
2268: * source address that we are going to use for the packet
2269: * (in order to handle the case when multiple subnets are
2270: * configured on the same interface).
2271: */
2272: if (rinfo->type == ZEBRA_ROUTE_RIP &&
2273: rinfo->ifindex == ifc->ifp->ifindex)
2274: continue;
2275: if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2276: prefix_match((struct prefix *)p, ifc->address))
2277: continue;
2278: }
2279:
2280: /* Preparation for route-map. */
2281: rinfo->metric_set = 0;
2282: rinfo->nexthop_out.s_addr = 0;
2283: rinfo->metric_out = rinfo->metric;
2284: rinfo->tag_out = rinfo->tag;
2285: rinfo->ifindex_out = ifc->ifp->ifindex;
2286:
2287: /* In order to avoid some local loops,
2288: * if the RIP route has a nexthop via this interface, keep the nexthop,
2289: * otherwise set it to 0. The nexthop should not be propagated
2290: * beyond the local broadcast/multicast area in order
2291: * to avoid an IGP multi-level recursive look-up.
2292: * see (4.4)
2293: */
2294: if (rinfo->ifindex == ifc->ifp->ifindex)
2295: rinfo->nexthop_out = rinfo->nexthop;
2296:
2297: /* Interface route-map */
2298: if (ri->routemap[RIP_FILTER_OUT])
2299: {
2300: ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2301: (struct prefix *) p, RMAP_RIP,
2302: rinfo);
2303:
2304: if (ret == RMAP_DENYMATCH)
2305: {
2306: if (IS_RIP_DEBUG_PACKET)
2307: zlog_debug ("RIP %s/%d is filtered by route-map out",
2308: inet_ntoa (p->prefix), p->prefixlen);
2309: continue;
2310: }
2311: }
2312:
2313: /* Apply redistribute route map - continue, if deny */
2314: if (rip->route_map[rinfo->type].name
2315: && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2316: {
2317: ret = route_map_apply (rip->route_map[rinfo->type].map,
2318: (struct prefix *)p, RMAP_RIP, rinfo);
2319:
2320: if (ret == RMAP_DENYMATCH)
2321: {
2322: if (IS_RIP_DEBUG_PACKET)
2323: zlog_debug ("%s/%d is filtered by route-map",
2324: inet_ntoa (p->prefix), p->prefixlen);
2325: continue;
2326: }
2327: }
2328:
2329: /* When route-map does not set metric. */
2330: if (! rinfo->metric_set)
2331: {
2332: /* If redistribute metric is set. */
2333: if (rip->route_map[rinfo->type].metric_config
2334: && rinfo->metric != RIP_METRIC_INFINITY)
2335: {
2336: rinfo->metric_out = rip->route_map[rinfo->type].metric;
2337: }
2338: else
2339: {
2340: /* If the route is not connected or localy generated
2341: one, use default-metric value*/
2342: if (rinfo->type != ZEBRA_ROUTE_RIP
2343: && rinfo->type != ZEBRA_ROUTE_CONNECT
2344: && rinfo->metric != RIP_METRIC_INFINITY)
2345: rinfo->metric_out = rip->default_metric;
2346: }
2347: }
2348:
2349: /* Apply offset-list */
2350: if (rinfo->metric != RIP_METRIC_INFINITY)
2351: rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
2352:
2353: if (rinfo->metric_out > RIP_METRIC_INFINITY)
2354: rinfo->metric_out = RIP_METRIC_INFINITY;
2355:
2356: /* Perform split-horizon with poisoned reverse
2357: * for RIP and connected routes.
2358: **/
2359: if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
2360: /*
2361: * We perform split horizon for RIP and connected route.
2362: * For rip routes, we want to suppress the route if we would
2363: * end up sending the route back on the interface that we
2364: * learned it from, with a higher metric. For connected routes,
2365: * we suppress the route if the prefix is a subset of the
2366: * source address that we are going to use for the packet
2367: * (in order to handle the case when multiple subnets are
2368: * configured on the same interface).
2369: */
2370: if (rinfo->type == ZEBRA_ROUTE_RIP &&
2371: rinfo->ifindex == ifc->ifp->ifindex)
2372: rinfo->metric_out = RIP_METRIC_INFINITY;
2373: if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2374: prefix_match((struct prefix *)p, ifc->address))
2375: rinfo->metric_out = RIP_METRIC_INFINITY;
2376: }
2377:
2378: /* Prepare preamble, auth headers, if needs be */
2379: if (num == 0)
2380: {
2381: stream_putc (s, RIP_RESPONSE);
2382: stream_putc (s, version);
2383: stream_putw (s, 0);
2384:
2385: /* auth header for !v1 && !no_auth */
2386: if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
2387: doff = rip_auth_header_write (s, ri, key, auth_str,
2388: RIP_AUTH_SIMPLE_SIZE);
2389: }
2390:
2391: /* Write RTE to the stream. */
2392: num = rip_write_rte (num, s, p, version, rinfo);
2393: if (num == rtemax)
2394: {
2395: if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2396: rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
2397:
2398: ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
2399: to, ifc);
2400:
2401: if (ret >= 0 && IS_RIP_DEBUG_SEND)
2402: rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2403: stream_get_endp(s), "SEND");
2404: num = 0;
2405: stream_reset (s);
2406: }
2407: }
2408:
2409: /* Flush unwritten RTE. */
2410: if (num != 0)
2411: {
2412: if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2413: rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
2414:
2415: ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
2416:
2417: if (ret >= 0 && IS_RIP_DEBUG_SEND)
2418: rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2419: stream_get_endp (s), "SEND");
2420: num = 0;
2421: stream_reset (s);
2422: }
2423:
2424: /* Statistics updates. */
2425: ri->sent_updates++;
2426: }
2427:
2428: /* Send RIP packet to the interface. */
2429: static void
2430: rip_update_interface (struct connected *ifc, u_char version, int route_type)
2431: {
2432: struct sockaddr_in to;
2433:
2434: /* When RIP version is 2 and multicast enable interface. */
2435: if (version == RIPv2 && if_is_multicast (ifc->ifp))
2436: {
2437: if (IS_RIP_DEBUG_EVENT)
2438: zlog_debug ("multicast announce on %s ", ifc->ifp->name);
2439:
2440: rip_output_process (ifc, NULL, route_type, version);
2441: return;
2442: }
2443:
2444: /* If we can't send multicast packet, send it with unicast. */
2445: if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
2446: {
2447: if (ifc->address->family == AF_INET)
2448: {
2449: /* Destination address and port setting. */
2450: memset (&to, 0, sizeof (struct sockaddr_in));
2451: if (ifc->destination)
2452: /* use specified broadcast or peer destination addr */
2453: to.sin_addr = ifc->destination->u.prefix4;
2454: else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
2455: /* calculate the appropriate broadcast address */
2456: to.sin_addr.s_addr =
2457: ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2458: ifc->address->prefixlen);
2459: else
2460: /* do not know where to send the packet */
2461: return;
2462: to.sin_port = htons (RIP_PORT_DEFAULT);
2463:
2464: if (IS_RIP_DEBUG_EVENT)
2465: zlog_debug("%s announce to %s on %s",
2466: CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
2467: inet_ntoa (to.sin_addr), ifc->ifp->name);
2468:
2469: rip_output_process (ifc, &to, route_type, version);
2470: }
2471: }
2472: }
2473:
2474: /* Update send to all interface and neighbor. */
2475: static void
2476: rip_update_process (int route_type)
2477: {
2478: struct listnode *node;
2479: struct listnode *ifnode, *ifnnode;
2480: struct connected *connected;
2481: struct interface *ifp;
2482: struct rip_interface *ri;
2483: struct route_node *rp;
2484: struct sockaddr_in to;
2485: struct prefix_ipv4 *p;
2486:
2487: /* Send RIP update to each interface. */
2488: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2489: {
2490: if (if_is_loopback (ifp))
2491: continue;
2492:
2493: if (! if_is_operative (ifp))
2494: continue;
2495:
2496: /* Fetch RIP interface information. */
2497: ri = ifp->info;
2498:
2499: /* When passive interface is specified, suppress announce to the
2500: interface. */
2501: if (ri->passive)
2502: continue;
2503:
2504: if (ri->running)
2505: {
2506: /*
2507: * If there is no version configuration in the interface,
2508: * use rip's version setting.
2509: */
2510: int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2511: rip->version_send : ri->ri_send);
2512:
2513: if (IS_RIP_DEBUG_EVENT)
2514: zlog_debug("SEND UPDATE to %s ifindex %d",
2515: (ifp->name ? ifp->name : "_unknown_"), ifp->ifindex);
2516:
2517: /* send update on each connected network */
2518: for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
2519: {
2520: if (connected->address->family == AF_INET)
2521: {
2522: if (vsend & RIPv1)
2523: rip_update_interface (connected, RIPv1, route_type);
2524: if ((vsend & RIPv2) && if_is_multicast(ifp))
2525: rip_update_interface (connected, RIPv2, route_type);
2526: }
2527: }
2528: }
2529: }
2530:
2531: /* RIP send updates to each neighbor. */
2532: for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2533: if (rp->info != NULL)
2534: {
2535: p = (struct prefix_ipv4 *) &rp->p;
2536:
2537: ifp = if_lookup_address (p->prefix);
2538: if (! ifp)
2539: {
2540: zlog_warn ("Neighbor %s doesnt have connected interface!",
2541: inet_ntoa (p->prefix));
2542: continue;
2543: }
2544:
2545: if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2546: {
2547: zlog_warn ("Neighbor %s doesnt have connected network",
2548: inet_ntoa (p->prefix));
2549: continue;
2550: }
2551:
2552: /* Set destination address and port */
2553: memset (&to, 0, sizeof (struct sockaddr_in));
2554: to.sin_addr = p->prefix;
2555: to.sin_port = htons (RIP_PORT_DEFAULT);
2556:
2557: /* RIP version is rip's configuration. */
2558: rip_output_process (connected, &to, route_type, rip->version_send);
2559: }
2560: }
2561:
2562: /* RIP's periodical timer. */
2563: static int
2564: rip_update (struct thread *t)
2565: {
2566: /* Clear timer pointer. */
2567: rip->t_update = NULL;
2568:
2569: if (IS_RIP_DEBUG_EVENT)
2570: zlog_debug ("update timer fire!");
2571:
2572: /* Process update output. */
2573: rip_update_process (rip_all_route);
2574:
2575: /* Triggered updates may be suppressed if a regular update is due by
2576: the time the triggered update would be sent. */
2577: if (rip->t_triggered_interval)
2578: {
2579: thread_cancel (rip->t_triggered_interval);
2580: rip->t_triggered_interval = NULL;
2581: }
2582: rip->trigger = 0;
2583:
2584: /* Register myself. */
2585: rip_event (RIP_UPDATE_EVENT, 0);
2586:
2587: return 0;
2588: }
2589:
2590: /* Walk down the RIP routing table then clear changed flag. */
2591: static void
2592: rip_clear_changed_flag (void)
2593: {
2594: struct route_node *rp;
2595: struct rip_info *rinfo;
2596:
2597: for (rp = route_top (rip->table); rp; rp = route_next (rp))
2598: if ((rinfo = rp->info) != NULL)
2599: if (rinfo->flags & RIP_RTF_CHANGED)
2600: rinfo->flags &= ~RIP_RTF_CHANGED;
2601: }
2602:
2603: /* Triggered update interval timer. */
2604: static int
2605: rip_triggered_interval (struct thread *t)
2606: {
2607: int rip_triggered_update (struct thread *);
2608:
2609: rip->t_triggered_interval = NULL;
2610:
2611: if (rip->trigger)
2612: {
2613: rip->trigger = 0;
2614: rip_triggered_update (t);
2615: }
2616: return 0;
2617: }
2618:
2619: /* Execute triggered update. */
2620: static int
2621: rip_triggered_update (struct thread *t)
2622: {
2623: int interval;
2624:
2625: /* Clear thred pointer. */
2626: rip->t_triggered_update = NULL;
2627:
2628: /* Cancel interval timer. */
2629: if (rip->t_triggered_interval)
2630: {
2631: thread_cancel (rip->t_triggered_interval);
2632: rip->t_triggered_interval = NULL;
2633: }
2634: rip->trigger = 0;
2635:
2636: /* Logging triggered update. */
2637: if (IS_RIP_DEBUG_EVENT)
2638: zlog_debug ("triggered update!");
2639:
2640: /* Split Horizon processing is done when generating triggered
2641: updates as well as normal updates (see section 2.6). */
2642: rip_update_process (rip_changed_route);
2643:
2644: /* Once all of the triggered updates have been generated, the route
2645: change flags should be cleared. */
2646: rip_clear_changed_flag ();
2647:
2648: /* After a triggered update is sent, a timer should be set for a
2649: random interval between 1 and 5 seconds. If other changes that
2650: would trigger updates occur before the timer expires, a single
2651: update is triggered when the timer expires. */
2652: interval = (random () % 5) + 1;
2653:
2654: rip->t_triggered_interval =
2655: thread_add_timer (master, rip_triggered_interval, NULL, interval);
2656:
2657: return 0;
2658: }
2659:
2660: /* Withdraw redistributed route. */
2661: void
2662: rip_redistribute_withdraw (int type)
2663: {
2664: struct route_node *rp;
2665: struct rip_info *rinfo;
2666:
2667: if (!rip)
2668: return;
2669:
2670: for (rp = route_top (rip->table); rp; rp = route_next (rp))
2671: if ((rinfo = rp->info) != NULL)
2672: {
2673: if (rinfo->type == type
2674: && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2675: {
2676: /* Perform poisoned reverse. */
2677: rinfo->metric = RIP_METRIC_INFINITY;
2678: RIP_TIMER_ON (rinfo->t_garbage_collect,
2679: rip_garbage_collect, rip->garbage_time);
2680: RIP_TIMER_OFF (rinfo->t_timeout);
2681: rinfo->flags |= RIP_RTF_CHANGED;
2682:
2683: if (IS_RIP_DEBUG_EVENT) {
2684: struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2685:
2686: zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2687: inet_ntoa(p->prefix), p->prefixlen,
2688: ifindex2ifname(rinfo->ifindex));
2689: }
2690:
2691: rip_event (RIP_TRIGGERED_UPDATE, 0);
2692: }
2693: }
2694: }
2695:
2696: /* Create new RIP instance and set it to global variable. */
2697: static int
2698: rip_create (void)
2699: {
2700: rip = XCALLOC (MTYPE_RIP, sizeof (struct rip));
2701:
2702: /* Set initial value. */
2703: rip->version_send = RI_RIP_VERSION_2;
2704: rip->version_recv = RI_RIP_VERSION_1_AND_2;
2705: rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2706: rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2707: rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2708: rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2709:
2710: /* Initialize RIP routig table. */
2711: rip->table = route_table_init ();
2712: rip->route = route_table_init ();
2713: rip->neighbor = route_table_init ();
2714:
2715: /* Make output stream. */
2716: rip->obuf = stream_new (1500);
2717:
2718: /* Make socket. */
2719: rip->sock = rip_create_socket (NULL);
2720: if (rip->sock < 0)
2721: return rip->sock;
2722:
2723: /* Create read and timer thread. */
2724: rip_event (RIP_READ, rip->sock);
2725: rip_event (RIP_UPDATE_EVENT, 1);
2726:
2727: return 0;
2728: }
2729:
2730: /* Sned RIP request to the destination. */
2731: int
2732: rip_request_send (struct sockaddr_in *to, struct interface *ifp,
2733: u_char version, struct connected *connected)
2734: {
2735: struct rte *rte;
2736: struct rip_packet rip_packet;
2737: struct listnode *node, *nnode;
2738:
2739: memset (&rip_packet, 0, sizeof (rip_packet));
2740:
2741: rip_packet.command = RIP_REQUEST;
2742: rip_packet.version = version;
2743: rte = rip_packet.rte;
2744: rte->metric = htonl (RIP_METRIC_INFINITY);
2745:
2746: if (connected)
2747: {
2748: /*
2749: * connected is only sent for ripv1 case, or when
2750: * interface does not support multicast. Caller loops
2751: * over each connected address for this case.
2752: */
2753: if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
2754: to, connected) != sizeof (rip_packet))
2755: return -1;
2756: else
2757: return sizeof (rip_packet);
2758: }
2759:
2760: /* send request on each connected network */
2761: for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
2762: {
2763: struct prefix_ipv4 *p;
2764:
2765: p = (struct prefix_ipv4 *) connected->address;
2766:
2767: if (p->family != AF_INET)
2768: continue;
2769:
2770: if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
2771: to, connected) != sizeof (rip_packet))
2772: return -1;
2773: }
2774: return sizeof (rip_packet);
2775: }
2776:
2777: static int
2778: rip_update_jitter (unsigned long time)
2779: {
2780: #define JITTER_BOUND 4
2781: /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2782: Given that, we cannot let time be less than JITTER_BOUND seconds.
2783: The RIPv2 RFC says jitter should be small compared to
2784: update_time. We consider 1/JITTER_BOUND to be small.
2785: */
2786:
2787: int jitter_input = time;
2788: int jitter;
2789:
2790: if (jitter_input < JITTER_BOUND)
2791: jitter_input = JITTER_BOUND;
2792:
2793: jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2794:
2795: return jitter/JITTER_BOUND;
2796: }
2797:
2798: void
2799: rip_event (enum rip_event event, int sock)
2800: {
2801: int jitter = 0;
2802:
2803: switch (event)
2804: {
2805: case RIP_READ:
2806: rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2807: break;
2808: case RIP_UPDATE_EVENT:
2809: if (rip->t_update)
2810: {
2811: thread_cancel (rip->t_update);
2812: rip->t_update = NULL;
2813: }
2814: jitter = rip_update_jitter (rip->update_time);
2815: rip->t_update =
2816: thread_add_timer (master, rip_update, NULL,
2817: sock ? 2 : rip->update_time + jitter);
2818: break;
2819: case RIP_TRIGGERED_UPDATE:
2820: if (rip->t_triggered_interval)
2821: rip->trigger = 1;
2822: else if (! rip->t_triggered_update)
2823: rip->t_triggered_update =
2824: thread_add_event (master, rip_triggered_update, NULL, 0);
2825: break;
2826: default:
2827: break;
2828: }
2829: }
2830:
2831: DEFUN (router_rip,
2832: router_rip_cmd,
2833: "router rip",
2834: "Enable a routing process\n"
2835: "Routing Information Protocol (RIP)\n")
2836: {
2837: int ret;
2838:
2839: /* If rip is not enabled before. */
2840: if (! rip)
2841: {
2842: ret = rip_create ();
2843: if (ret < 0)
2844: {
2845: zlog_info ("Can't create RIP");
2846: return CMD_WARNING;
2847: }
2848: }
2849: vty->node = RIP_NODE;
2850: vty->index = rip;
2851:
2852: return CMD_SUCCESS;
2853: }
2854:
2855: DEFUN (no_router_rip,
2856: no_router_rip_cmd,
2857: "no router rip",
2858: NO_STR
2859: "Enable a routing process\n"
2860: "Routing Information Protocol (RIP)\n")
2861: {
2862: if (rip)
2863: rip_clean ();
2864: return CMD_SUCCESS;
2865: }
2866:
2867: DEFUN (rip_version,
2868: rip_version_cmd,
2869: "version <1-2>",
2870: "Set routing protocol version\n"
2871: "version\n")
2872: {
2873: int version;
2874:
2875: version = atoi (argv[0]);
2876: if (version != RIPv1 && version != RIPv2)
2877: {
2878: vty_out (vty, "invalid rip version %d%s", version,
2879: VTY_NEWLINE);
2880: return CMD_WARNING;
2881: }
2882: rip->version_send = version;
2883: rip->version_recv = version;
2884:
2885: return CMD_SUCCESS;
2886: }
2887:
2888: DEFUN (no_rip_version,
2889: no_rip_version_cmd,
2890: "no version",
2891: NO_STR
2892: "Set routing protocol version\n")
2893: {
2894: /* Set RIP version to the default. */
2895: rip->version_send = RI_RIP_VERSION_2;
2896: rip->version_recv = RI_RIP_VERSION_1_AND_2;
2897:
2898: return CMD_SUCCESS;
2899: }
2900:
2901: ALIAS (no_rip_version,
2902: no_rip_version_val_cmd,
2903: "no version <1-2>",
2904: NO_STR
2905: "Set routing protocol version\n"
2906: "version\n")
2907:
2908: DEFUN (rip_route,
2909: rip_route_cmd,
2910: "route A.B.C.D/M",
2911: "RIP static route configuration\n"
2912: "IP prefix <network>/<length>\n")
2913: {
2914: int ret;
2915: struct prefix_ipv4 p;
2916: struct route_node *node;
2917:
2918: ret = str2prefix_ipv4 (argv[0], &p);
2919: if (ret < 0)
2920: {
2921: vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2922: return CMD_WARNING;
2923: }
2924: apply_mask_ipv4 (&p);
2925:
2926: /* For router rip configuration. */
2927: node = route_node_get (rip->route, (struct prefix *) &p);
2928:
2929: if (node->info)
2930: {
2931: vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2932: route_unlock_node (node);
2933: return CMD_WARNING;
2934: }
2935:
2936: node->info = (char *)"static";
2937:
2938: rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
2939:
2940: return CMD_SUCCESS;
2941: }
2942:
2943: DEFUN (no_rip_route,
2944: no_rip_route_cmd,
2945: "no route A.B.C.D/M",
2946: NO_STR
2947: "RIP static route configuration\n"
2948: "IP prefix <network>/<length>\n")
2949: {
2950: int ret;
2951: struct prefix_ipv4 p;
2952: struct route_node *node;
2953:
2954: ret = str2prefix_ipv4 (argv[0], &p);
2955: if (ret < 0)
2956: {
2957: vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2958: return CMD_WARNING;
2959: }
2960: apply_mask_ipv4 (&p);
2961:
2962: /* For router rip configuration. */
2963: node = route_node_lookup (rip->route, (struct prefix *) &p);
2964: if (! node)
2965: {
2966: vty_out (vty, "Can't find route %s.%s", argv[0],
2967: VTY_NEWLINE);
2968: return CMD_WARNING;
2969: }
2970:
2971: rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2972: route_unlock_node (node);
2973:
2974: node->info = NULL;
2975: route_unlock_node (node);
2976:
2977: return CMD_SUCCESS;
2978: }
2979:
2980: #if 0
2981: static void
2982: rip_update_default_metric (void)
2983: {
2984: struct route_node *np;
2985: struct rip_info *rinfo;
2986:
2987: for (np = route_top (rip->table); np; np = route_next (np))
2988: if ((rinfo = np->info) != NULL)
2989: if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2990: rinfo->metric = rip->default_metric;
2991: }
2992: #endif
2993:
2994: DEFUN (rip_default_metric,
2995: rip_default_metric_cmd,
2996: "default-metric <1-16>",
2997: "Set a metric of redistribute routes\n"
2998: "Default metric\n")
2999: {
3000: if (rip)
3001: {
3002: rip->default_metric = atoi (argv[0]);
3003: /* rip_update_default_metric (); */
3004: }
3005: return CMD_SUCCESS;
3006: }
3007:
3008: DEFUN (no_rip_default_metric,
3009: no_rip_default_metric_cmd,
3010: "no default-metric",
3011: NO_STR
3012: "Set a metric of redistribute routes\n"
3013: "Default metric\n")
3014: {
3015: if (rip)
3016: {
3017: rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3018: /* rip_update_default_metric (); */
3019: }
3020: return CMD_SUCCESS;
3021: }
3022:
3023: ALIAS (no_rip_default_metric,
3024: no_rip_default_metric_val_cmd,
3025: "no default-metric <1-16>",
3026: NO_STR
3027: "Set a metric of redistribute routes\n"
3028: "Default metric\n")
3029:
3030: DEFUN (rip_timers,
3031: rip_timers_cmd,
3032: "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3033: "Adjust routing timers\n"
3034: "Basic routing protocol update timers\n"
3035: "Routing table update timer value in second. Default is 30.\n"
3036: "Routing information timeout timer. Default is 180.\n"
3037: "Garbage collection timer. Default is 120.\n")
3038: {
3039: unsigned long update;
3040: unsigned long timeout;
3041: unsigned long garbage;
3042: char *endptr = NULL;
3043: unsigned long RIP_TIMER_MAX = 2147483647;
3044: unsigned long RIP_TIMER_MIN = 5;
3045:
3046: update = strtoul (argv[0], &endptr, 10);
3047: if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3048: {
3049: vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3050: return CMD_WARNING;
3051: }
3052:
3053: timeout = strtoul (argv[1], &endptr, 10);
3054: if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3055: {
3056: vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3057: return CMD_WARNING;
3058: }
3059:
3060: garbage = strtoul (argv[2], &endptr, 10);
3061: if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3062: {
3063: vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3064: return CMD_WARNING;
3065: }
3066:
3067: /* Set each timer value. */
3068: rip->update_time = update;
3069: rip->timeout_time = timeout;
3070: rip->garbage_time = garbage;
3071:
3072: /* Reset update timer thread. */
3073: rip_event (RIP_UPDATE_EVENT, 0);
3074:
3075: return CMD_SUCCESS;
3076: }
3077:
3078: DEFUN (no_rip_timers,
3079: no_rip_timers_cmd,
3080: "no timers basic",
3081: NO_STR
3082: "Adjust routing timers\n"
3083: "Basic routing protocol update timers\n")
3084: {
3085: /* Set each timer value to the default. */
3086: rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3087: rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3088: rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3089:
3090: /* Reset update timer thread. */
3091: rip_event (RIP_UPDATE_EVENT, 0);
3092:
3093: return CMD_SUCCESS;
3094: }
3095:
3096: ALIAS (no_rip_timers,
3097: no_rip_timers_val_cmd,
3098: "no timers basic <0-65535> <0-65535> <0-65535>",
3099: NO_STR
3100: "Adjust routing timers\n"
3101: "Basic routing protocol update timers\n"
3102: "Routing table update timer value in second. Default is 30.\n"
3103: "Routing information timeout timer. Default is 180.\n"
3104: "Garbage collection timer. Default is 120.\n")
3105:
3106:
3107: struct route_table *rip_distance_table;
3108:
3109: struct rip_distance
3110: {
3111: /* Distance value for the IP source prefix. */
3112: u_char distance;
3113:
3114: /* Name of the access-list to be matched. */
3115: char *access_list;
3116: };
3117:
3118: static struct rip_distance *
3119: rip_distance_new (void)
3120: {
3121: return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3122: }
3123:
3124: static void
3125: rip_distance_free (struct rip_distance *rdistance)
3126: {
3127: XFREE (MTYPE_RIP_DISTANCE, rdistance);
3128: }
3129:
3130: static int
3131: rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3132: const char *access_list_str)
3133: {
3134: int ret;
3135: struct prefix_ipv4 p;
3136: u_char distance;
3137: struct route_node *rn;
3138: struct rip_distance *rdistance;
3139:
3140: ret = str2prefix_ipv4 (ip_str, &p);
3141: if (ret == 0)
3142: {
3143: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3144: return CMD_WARNING;
3145: }
3146:
3147: distance = atoi (distance_str);
3148:
3149: /* Get RIP distance node. */
3150: rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3151: if (rn->info)
3152: {
3153: rdistance = rn->info;
3154: route_unlock_node (rn);
3155: }
3156: else
3157: {
3158: rdistance = rip_distance_new ();
3159: rn->info = rdistance;
3160: }
3161:
3162: /* Set distance value. */
3163: rdistance->distance = distance;
3164:
3165: /* Reset access-list configuration. */
3166: if (rdistance->access_list)
3167: {
3168: free (rdistance->access_list);
3169: rdistance->access_list = NULL;
3170: }
3171: if (access_list_str)
3172: rdistance->access_list = strdup (access_list_str);
3173:
3174: return CMD_SUCCESS;
3175: }
3176:
3177: static int
3178: rip_distance_unset (struct vty *vty, const char *distance_str,
3179: const char *ip_str, const char *access_list_str)
3180: {
3181: int ret;
3182: struct prefix_ipv4 p;
3183: u_char distance;
3184: struct route_node *rn;
3185: struct rip_distance *rdistance;
3186:
3187: ret = str2prefix_ipv4 (ip_str, &p);
3188: if (ret == 0)
3189: {
3190: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3191: return CMD_WARNING;
3192: }
3193:
3194: distance = atoi (distance_str);
3195:
3196: rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3197: if (! rn)
3198: {
3199: vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3200: return CMD_WARNING;
3201: }
3202:
3203: rdistance = rn->info;
3204:
3205: if (rdistance->access_list)
3206: free (rdistance->access_list);
3207: rip_distance_free (rdistance);
3208:
3209: rn->info = NULL;
3210: route_unlock_node (rn);
3211: route_unlock_node (rn);
3212:
3213: return CMD_SUCCESS;
3214: }
3215:
3216: static void
3217: rip_distance_reset (void)
3218: {
3219: struct route_node *rn;
3220: struct rip_distance *rdistance;
3221:
3222: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3223: if ((rdistance = rn->info) != NULL)
3224: {
3225: if (rdistance->access_list)
3226: free (rdistance->access_list);
3227: rip_distance_free (rdistance);
3228: rn->info = NULL;
3229: route_unlock_node (rn);
3230: }
3231: }
3232:
3233: /* Apply RIP information to distance method. */
3234: u_char
3235: rip_distance_apply (struct rip_info *rinfo)
3236: {
3237: struct route_node *rn;
3238: struct prefix_ipv4 p;
3239: struct rip_distance *rdistance;
3240: struct access_list *alist;
3241:
3242: if (! rip)
3243: return 0;
3244:
3245: memset (&p, 0, sizeof (struct prefix_ipv4));
3246: p.family = AF_INET;
3247: p.prefix = rinfo->from;
3248: p.prefixlen = IPV4_MAX_BITLEN;
3249:
3250: /* Check source address. */
3251: rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3252: if (rn)
3253: {
3254: rdistance = rn->info;
3255: route_unlock_node (rn);
3256:
3257: if (rdistance->access_list)
3258: {
3259: alist = access_list_lookup (AFI_IP, rdistance->access_list);
3260: if (alist == NULL)
3261: return 0;
3262: if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3263: return 0;
3264:
3265: return rdistance->distance;
3266: }
3267: else
3268: return rdistance->distance;
3269: }
3270:
3271: if (rip->distance)
3272: return rip->distance;
3273:
3274: return 0;
3275: }
3276:
3277: static void
3278: rip_distance_show (struct vty *vty)
3279: {
3280: struct route_node *rn;
3281: struct rip_distance *rdistance;
3282: int header = 1;
3283: char buf[BUFSIZ];
3284:
3285: vty_out (vty, " Distance: (default is %d)%s",
3286: rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3287: VTY_NEWLINE);
3288:
3289: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3290: if ((rdistance = rn->info) != NULL)
3291: {
3292: if (header)
3293: {
3294: vty_out (vty, " Address Distance List%s",
3295: VTY_NEWLINE);
3296: header = 0;
3297: }
3298: sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3299: vty_out (vty, " %-20s %4d %s%s",
3300: buf, rdistance->distance,
3301: rdistance->access_list ? rdistance->access_list : "",
3302: VTY_NEWLINE);
3303: }
3304: }
3305:
3306: DEFUN (rip_distance,
3307: rip_distance_cmd,
3308: "distance <1-255>",
3309: "Administrative distance\n"
3310: "Distance value\n")
3311: {
3312: rip->distance = atoi (argv[0]);
3313: return CMD_SUCCESS;
3314: }
3315:
3316: DEFUN (no_rip_distance,
3317: no_rip_distance_cmd,
3318: "no distance <1-255>",
3319: NO_STR
3320: "Administrative distance\n"
3321: "Distance value\n")
3322: {
3323: rip->distance = 0;
3324: return CMD_SUCCESS;
3325: }
3326:
3327: DEFUN (rip_distance_source,
3328: rip_distance_source_cmd,
3329: "distance <1-255> A.B.C.D/M",
3330: "Administrative distance\n"
3331: "Distance value\n"
3332: "IP source prefix\n")
3333: {
3334: rip_distance_set (vty, argv[0], argv[1], NULL);
3335: return CMD_SUCCESS;
3336: }
3337:
3338: DEFUN (no_rip_distance_source,
3339: no_rip_distance_source_cmd,
3340: "no distance <1-255> A.B.C.D/M",
3341: NO_STR
3342: "Administrative distance\n"
3343: "Distance value\n"
3344: "IP source prefix\n")
3345: {
3346: rip_distance_unset (vty, argv[0], argv[1], NULL);
3347: return CMD_SUCCESS;
3348: }
3349:
3350: DEFUN (rip_distance_source_access_list,
3351: rip_distance_source_access_list_cmd,
3352: "distance <1-255> A.B.C.D/M WORD",
3353: "Administrative distance\n"
3354: "Distance value\n"
3355: "IP source prefix\n"
3356: "Access list name\n")
3357: {
3358: rip_distance_set (vty, argv[0], argv[1], argv[2]);
3359: return CMD_SUCCESS;
3360: }
3361:
3362: DEFUN (no_rip_distance_source_access_list,
3363: no_rip_distance_source_access_list_cmd,
3364: "no distance <1-255> A.B.C.D/M WORD",
3365: NO_STR
3366: "Administrative distance\n"
3367: "Distance value\n"
3368: "IP source prefix\n"
3369: "Access list name\n")
3370: {
3371: rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3372: return CMD_SUCCESS;
3373: }
3374:
3375: /* Print out routes update time. */
3376: static void
3377: rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3378: {
3379: time_t clock;
3380: struct tm *tm;
3381: #define TIME_BUF 25
3382: char timebuf [TIME_BUF];
3383: struct thread *thread;
3384:
3385: if ((thread = rinfo->t_timeout) != NULL)
3386: {
3387: clock = thread_timer_remain_second (thread);
3388: tm = gmtime (&clock);
3389: strftime (timebuf, TIME_BUF, "%M:%S", tm);
3390: vty_out (vty, "%5s", timebuf);
3391: }
3392: else if ((thread = rinfo->t_garbage_collect) != NULL)
3393: {
3394: clock = thread_timer_remain_second (thread);
3395: tm = gmtime (&clock);
3396: strftime (timebuf, TIME_BUF, "%M:%S", tm);
3397: vty_out (vty, "%5s", timebuf);
3398: }
3399: }
3400:
3401: static const char *
3402: rip_route_type_print (int sub_type)
3403: {
3404: switch (sub_type)
3405: {
3406: case RIP_ROUTE_RTE:
3407: return "n";
3408: case RIP_ROUTE_STATIC:
3409: return "s";
3410: case RIP_ROUTE_DEFAULT:
3411: return "d";
3412: case RIP_ROUTE_REDISTRIBUTE:
3413: return "r";
3414: case RIP_ROUTE_INTERFACE:
3415: return "i";
3416: default:
3417: return "?";
3418: }
3419: }
3420:
3421: DEFUN (show_ip_rip,
3422: show_ip_rip_cmd,
3423: "show ip rip",
3424: SHOW_STR
3425: IP_STR
3426: "Show RIP routes\n")
3427: {
3428: struct route_node *np;
3429: struct rip_info *rinfo;
3430:
3431: if (! rip)
3432: return CMD_SUCCESS;
3433:
3434: vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3435: "Sub-codes:%s"
3436: " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
3437: " (i) - interface%s%s"
3438: " Network Next Hop Metric From Tag Time%s",
3439: VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
3440:
3441: for (np = route_top (rip->table); np; np = route_next (np))
3442: if ((rinfo = np->info) != NULL)
3443: {
3444: int len;
3445:
3446: len = vty_out (vty, "%c(%s) %s/%d",
3447: /* np->lock, For debugging. */
3448: zebra_route_char(rinfo->type),
3449: rip_route_type_print (rinfo->sub_type),
3450: inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3451:
3452: len = 24 - len;
3453:
3454: if (len > 0)
3455: vty_out (vty, "%*s", len, " ");
3456:
3457: if (rinfo->nexthop.s_addr)
3458: vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3459: rinfo->metric);
3460: else
3461: vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3462:
3463: /* Route which exist in kernel routing table. */
3464: if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3465: (rinfo->sub_type == RIP_ROUTE_RTE))
3466: {
3467: vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
3468: vty_out (vty, "%3d ", rinfo->tag);
3469: rip_vty_out_uptime (vty, rinfo);
3470: }
3471: else if (rinfo->metric == RIP_METRIC_INFINITY)
3472: {
3473: vty_out (vty, "self ");
3474: vty_out (vty, "%3d ", rinfo->tag);
3475: rip_vty_out_uptime (vty, rinfo);
3476: }
3477: else
3478: {
3479: if (rinfo->external_metric)
3480: {
3481: len = vty_out (vty, "self (%s:%d)",
3482: zebra_route_string(rinfo->type),
3483: rinfo->external_metric);
3484: len = 16 - len;
3485: if (len > 0)
3486: vty_out (vty, "%*s", len, " ");
3487: }
3488: else
3489: vty_out (vty, "self ");
3490: vty_out (vty, "%3d", rinfo->tag);
3491: }
3492:
3493: vty_out (vty, "%s", VTY_NEWLINE);
3494: }
3495: return CMD_SUCCESS;
3496: }
3497:
3498: /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3499: DEFUN (show_ip_rip_status,
3500: show_ip_rip_status_cmd,
3501: "show ip rip status",
3502: SHOW_STR
3503: IP_STR
3504: "Show RIP routes\n"
3505: "IP routing protocol process parameters and statistics\n")
3506: {
3507: struct listnode *node;
3508: struct interface *ifp;
3509: struct rip_interface *ri;
3510: extern const struct message ri_version_msg[];
3511: const char *send_version;
3512: const char *receive_version;
3513:
3514: if (! rip)
3515: return CMD_SUCCESS;
3516:
3517: vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3518: vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3519: rip->update_time);
3520: vty_out (vty, " next due in %lu seconds%s",
3521: thread_timer_remain_second(rip->t_update),
3522: VTY_NEWLINE);
3523: vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3524: vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3525: VTY_NEWLINE);
3526:
3527: /* Filtering status show. */
3528: config_show_distribute (vty);
3529:
3530: /* Default metric information. */
3531: vty_out (vty, " Default redistribution metric is %d%s",
3532: rip->default_metric, VTY_NEWLINE);
3533:
3534: /* Redistribute information. */
3535: vty_out (vty, " Redistributing:");
3536: config_write_rip_redistribute (vty, 0);
3537: vty_out (vty, "%s", VTY_NEWLINE);
3538:
3539: vty_out (vty, " Default version control: send version %s,",
3540: lookup(ri_version_msg,rip->version_send));
3541: if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3542: vty_out (vty, " receive any version %s", VTY_NEWLINE);
3543: else
3544: vty_out (vty, " receive version %s %s",
3545: lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
3546:
3547: vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3548:
3549: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
3550: {
3551: ri = ifp->info;
3552:
3553: if (!ri->running)
3554: continue;
3555:
3556: if (ri->enable_network || ri->enable_interface)
3557: {
3558: if (ri->ri_send == RI_RIP_UNSPEC)
3559: send_version = lookup (ri_version_msg, rip->version_send);
3560: else
3561: send_version = lookup (ri_version_msg, ri->ri_send);
3562:
3563: if (ri->ri_receive == RI_RIP_UNSPEC)
3564: receive_version = lookup (ri_version_msg, rip->version_recv);
3565: else
3566: receive_version = lookup (ri_version_msg, ri->ri_receive);
3567:
3568: vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3569: send_version,
3570: receive_version,
3571: ri->key_chain ? ri->key_chain : "",
3572: VTY_NEWLINE);
3573: }
3574: }
3575:
3576: vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3577: config_write_rip_network (vty, 0);
3578:
3579: {
3580: int found_passive = 0;
3581: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
3582: {
3583: ri = ifp->info;
3584:
3585: if ((ri->enable_network || ri->enable_interface) && ri->passive)
3586: {
3587: if (!found_passive)
3588: {
3589: vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3590: found_passive = 1;
3591: }
3592: vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3593: }
3594: }
3595: }
3596:
3597: vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3598: vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3599: rip_peer_display (vty);
3600:
3601: rip_distance_show (vty);
3602:
3603: return CMD_SUCCESS;
3604: }
3605:
3606: /* RIP configuration write function. */
3607: static int
3608: config_write_rip (struct vty *vty)
3609: {
3610: int write = 0;
3611: struct route_node *rn;
3612: struct rip_distance *rdistance;
3613:
3614: if (rip)
3615: {
3616: /* Router RIP statement. */
3617: vty_out (vty, "router rip%s", VTY_NEWLINE);
3618: write++;
3619:
3620: /* RIP version statement. Default is RIP version 2. */
3621: if (rip->version_send != RI_RIP_VERSION_2
3622: || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3623: vty_out (vty, " version %d%s", rip->version_send,
3624: VTY_NEWLINE);
3625:
3626: /* RIP timer configuration. */
3627: if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3628: || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3629: || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3630: vty_out (vty, " timers basic %lu %lu %lu%s",
3631: rip->update_time,
3632: rip->timeout_time,
3633: rip->garbage_time,
3634: VTY_NEWLINE);
3635:
3636: /* Default information configuration. */
3637: if (rip->default_information)
3638: {
3639: if (rip->default_information_route_map)
3640: vty_out (vty, " default-information originate route-map %s%s",
3641: rip->default_information_route_map, VTY_NEWLINE);
3642: else
3643: vty_out (vty, " default-information originate%s",
3644: VTY_NEWLINE);
3645: }
3646:
3647: /* Redistribute configuration. */
3648: config_write_rip_redistribute (vty, 1);
3649:
3650: /* RIP offset-list configuration. */
3651: config_write_rip_offset_list (vty);
3652:
3653: /* RIP enabled network and interface configuration. */
3654: config_write_rip_network (vty, 1);
3655:
3656: /* RIP default metric configuration */
3657: if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3658: vty_out (vty, " default-metric %d%s",
3659: rip->default_metric, VTY_NEWLINE);
3660:
3661: /* Distribute configuration. */
3662: write += config_write_distribute (vty);
3663:
3664: /* Interface routemap configuration */
3665: write += config_write_if_rmap (vty);
3666:
3667: /* Distance configuration. */
3668: if (rip->distance)
3669: vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3670:
3671: /* RIP source IP prefix distance configuration. */
3672: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3673: if ((rdistance = rn->info) != NULL)
3674: vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3675: inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3676: rdistance->access_list ? rdistance->access_list : "",
3677: VTY_NEWLINE);
3678:
3679: /* RIP static route configuration. */
3680: for (rn = route_top (rip->route); rn; rn = route_next (rn))
3681: if (rn->info)
3682: vty_out (vty, " route %s/%d%s",
3683: inet_ntoa (rn->p.u.prefix4),
3684: rn->p.prefixlen,
3685: VTY_NEWLINE);
3686:
3687: }
3688: return write;
3689: }
3690:
3691: /* RIP node structure. */
3692: static struct cmd_node rip_node =
3693: {
3694: RIP_NODE,
3695: "%s(config-router)# ",
3696: 1
3697: };
3698:
3699: /* Distribute-list update functions. */
3700: static void
3701: rip_distribute_update (struct distribute *dist)
3702: {
3703: struct interface *ifp;
3704: struct rip_interface *ri;
3705: struct access_list *alist;
3706: struct prefix_list *plist;
3707:
3708: if (! dist->ifname)
3709: return;
3710:
3711: ifp = if_lookup_by_name (dist->ifname);
3712: if (ifp == NULL)
3713: return;
3714:
3715: ri = ifp->info;
3716:
3717: if (dist->list[DISTRIBUTE_IN])
3718: {
3719: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3720: if (alist)
3721: ri->list[RIP_FILTER_IN] = alist;
3722: else
3723: ri->list[RIP_FILTER_IN] = NULL;
3724: }
3725: else
3726: ri->list[RIP_FILTER_IN] = NULL;
3727:
3728: if (dist->list[DISTRIBUTE_OUT])
3729: {
3730: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3731: if (alist)
3732: ri->list[RIP_FILTER_OUT] = alist;
3733: else
3734: ri->list[RIP_FILTER_OUT] = NULL;
3735: }
3736: else
3737: ri->list[RIP_FILTER_OUT] = NULL;
3738:
3739: if (dist->prefix[DISTRIBUTE_IN])
3740: {
3741: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3742: if (plist)
3743: ri->prefix[RIP_FILTER_IN] = plist;
3744: else
3745: ri->prefix[RIP_FILTER_IN] = NULL;
3746: }
3747: else
3748: ri->prefix[RIP_FILTER_IN] = NULL;
3749:
3750: if (dist->prefix[DISTRIBUTE_OUT])
3751: {
3752: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3753: if (plist)
3754: ri->prefix[RIP_FILTER_OUT] = plist;
3755: else
3756: ri->prefix[RIP_FILTER_OUT] = NULL;
3757: }
3758: else
3759: ri->prefix[RIP_FILTER_OUT] = NULL;
3760: }
3761:
3762: void
3763: rip_distribute_update_interface (struct interface *ifp)
3764: {
3765: struct distribute *dist;
3766:
3767: dist = distribute_lookup (ifp->name);
3768: if (dist)
3769: rip_distribute_update (dist);
3770: }
3771:
3772: /* Update all interface's distribute list. */
3773: /* ARGSUSED */
3774: static void
3775: rip_distribute_update_all (struct prefix_list *notused)
3776: {
3777: struct interface *ifp;
3778: struct listnode *node, *nnode;
3779:
3780: for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3781: rip_distribute_update_interface (ifp);
3782: }
3783: /* ARGSUSED */
3784: static void
3785: rip_distribute_update_all_wrapper(struct access_list *notused)
3786: {
3787: rip_distribute_update_all(NULL);
3788: }
3789:
3790: /* Delete all added rip route. */
3791: void
3792: rip_clean (void)
3793: {
3794: int i;
3795: struct route_node *rp;
3796: struct rip_info *rinfo;
3797:
3798: if (rip)
3799: {
3800: /* Clear RIP routes */
3801: for (rp = route_top (rip->table); rp; rp = route_next (rp))
3802: if ((rinfo = rp->info) != NULL)
3803: {
3804: if (rinfo->type == ZEBRA_ROUTE_RIP &&
3805: rinfo->sub_type == RIP_ROUTE_RTE)
3806: rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3807: &rinfo->nexthop, rinfo->metric);
3808:
3809: RIP_TIMER_OFF (rinfo->t_timeout);
3810: RIP_TIMER_OFF (rinfo->t_garbage_collect);
3811:
3812: rp->info = NULL;
3813: route_unlock_node (rp);
3814:
3815: rip_info_free (rinfo);
3816: }
3817:
3818: /* Cancel RIP related timers. */
3819: RIP_TIMER_OFF (rip->t_update);
3820: RIP_TIMER_OFF (rip->t_triggered_update);
3821: RIP_TIMER_OFF (rip->t_triggered_interval);
3822:
3823: /* Cancel read thread. */
3824: if (rip->t_read)
3825: {
3826: thread_cancel (rip->t_read);
3827: rip->t_read = NULL;
3828: }
3829:
3830: /* Close RIP socket. */
3831: if (rip->sock >= 0)
3832: {
3833: close (rip->sock);
3834: rip->sock = -1;
3835: }
3836:
3837: /* Static RIP route configuration. */
3838: for (rp = route_top (rip->route); rp; rp = route_next (rp))
3839: if (rp->info)
3840: {
3841: rp->info = NULL;
3842: route_unlock_node (rp);
3843: }
3844:
3845: /* RIP neighbor configuration. */
3846: for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3847: if (rp->info)
3848: {
3849: rp->info = NULL;
3850: route_unlock_node (rp);
3851: }
3852:
3853: /* Redistribute related clear. */
3854: if (rip->default_information_route_map)
3855: free (rip->default_information_route_map);
3856:
3857: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3858: if (rip->route_map[i].name)
3859: free (rip->route_map[i].name);
3860:
3861: XFREE (MTYPE_ROUTE_TABLE, rip->table);
3862: XFREE (MTYPE_ROUTE_TABLE, rip->route);
3863: XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3864:
3865: XFREE (MTYPE_RIP, rip);
3866: rip = NULL;
3867: }
3868:
3869: rip_clean_network ();
3870: rip_passive_nondefault_clean ();
3871: rip_offset_clean ();
3872: rip_interface_clean ();
3873: rip_distance_reset ();
3874: rip_redistribute_clean ();
3875: }
3876:
3877: /* Reset all values to the default settings. */
3878: void
3879: rip_reset (void)
3880: {
3881: /* Reset global counters. */
3882: rip_global_route_changes = 0;
3883: rip_global_queries = 0;
3884:
3885: /* Call ripd related reset functions. */
3886: rip_debug_reset ();
3887: rip_route_map_reset ();
3888:
3889: /* Call library reset functions. */
3890: vty_reset ();
3891: access_list_reset ();
3892: prefix_list_reset ();
3893:
3894: distribute_list_reset ();
3895:
3896: rip_interface_reset ();
3897: rip_distance_reset ();
3898:
3899: rip_zclient_reset ();
3900: }
3901:
3902: static void
3903: rip_if_rmap_update (struct if_rmap *if_rmap)
3904: {
3905: struct interface *ifp;
3906: struct rip_interface *ri;
3907: struct route_map *rmap;
3908:
3909: ifp = if_lookup_by_name (if_rmap->ifname);
3910: if (ifp == NULL)
3911: return;
3912:
3913: ri = ifp->info;
3914:
3915: if (if_rmap->routemap[IF_RMAP_IN])
3916: {
3917: rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3918: if (rmap)
3919: ri->routemap[IF_RMAP_IN] = rmap;
3920: else
3921: ri->routemap[IF_RMAP_IN] = NULL;
3922: }
3923: else
3924: ri->routemap[RIP_FILTER_IN] = NULL;
3925:
3926: if (if_rmap->routemap[IF_RMAP_OUT])
3927: {
3928: rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3929: if (rmap)
3930: ri->routemap[IF_RMAP_OUT] = rmap;
3931: else
3932: ri->routemap[IF_RMAP_OUT] = NULL;
3933: }
3934: else
3935: ri->routemap[RIP_FILTER_OUT] = NULL;
3936: }
3937:
3938: void
3939: rip_if_rmap_update_interface (struct interface *ifp)
3940: {
3941: struct if_rmap *if_rmap;
3942:
3943: if_rmap = if_rmap_lookup (ifp->name);
3944: if (if_rmap)
3945: rip_if_rmap_update (if_rmap);
3946: }
3947:
3948: static void
3949: rip_routemap_update_redistribute (void)
3950: {
3951: int i;
3952:
3953: if (rip)
3954: {
3955: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3956: {
3957: if (rip->route_map[i].name)
3958: rip->route_map[i].map =
3959: route_map_lookup_by_name (rip->route_map[i].name);
3960: }
3961: }
3962: }
3963:
3964: /* ARGSUSED */
3965: static void
3966: rip_routemap_update (const char *notused)
3967: {
3968: struct interface *ifp;
3969: struct listnode *node, *nnode;
3970:
3971: for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3972: rip_if_rmap_update_interface (ifp);
3973:
3974: rip_routemap_update_redistribute ();
3975: }
3976:
3977: /* Allocate new rip structure and set default value. */
3978: void
3979: rip_init (void)
3980: {
3981: /* Randomize for triggered update random(). */
3982: srand (time (NULL));
3983:
3984: /* Install top nodes. */
3985: install_node (&rip_node, config_write_rip);
3986:
3987: /* Install rip commands. */
3988: install_element (VIEW_NODE, &show_ip_rip_cmd);
3989: install_element (VIEW_NODE, &show_ip_rip_status_cmd);
3990: install_element (ENABLE_NODE, &show_ip_rip_cmd);
3991: install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
3992: install_element (CONFIG_NODE, &router_rip_cmd);
3993: install_element (CONFIG_NODE, &no_router_rip_cmd);
3994:
3995: install_default (RIP_NODE);
3996: install_element (RIP_NODE, &rip_version_cmd);
3997: install_element (RIP_NODE, &no_rip_version_cmd);
3998: install_element (RIP_NODE, &no_rip_version_val_cmd);
3999: install_element (RIP_NODE, &rip_default_metric_cmd);
4000: install_element (RIP_NODE, &no_rip_default_metric_cmd);
4001: install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4002: install_element (RIP_NODE, &rip_timers_cmd);
4003: install_element (RIP_NODE, &no_rip_timers_cmd);
4004: install_element (RIP_NODE, &no_rip_timers_val_cmd);
4005: install_element (RIP_NODE, &rip_route_cmd);
4006: install_element (RIP_NODE, &no_rip_route_cmd);
4007: install_element (RIP_NODE, &rip_distance_cmd);
4008: install_element (RIP_NODE, &no_rip_distance_cmd);
4009: install_element (RIP_NODE, &rip_distance_source_cmd);
4010: install_element (RIP_NODE, &no_rip_distance_source_cmd);
4011: install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4012: install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4013:
4014: /* Debug related init. */
4015: rip_debug_init ();
4016:
4017: /* SNMP init. */
4018: #ifdef HAVE_SNMP
4019: rip_snmp_init ();
4020: #endif /* HAVE_SNMP */
4021:
4022: /* Access list install. */
4023: access_list_init ();
4024: access_list_add_hook (rip_distribute_update_all_wrapper);
4025: access_list_delete_hook (rip_distribute_update_all_wrapper);
4026:
4027: /* Prefix list initialize.*/
4028: prefix_list_init ();
4029: prefix_list_add_hook (rip_distribute_update_all);
4030: prefix_list_delete_hook (rip_distribute_update_all);
4031:
4032: /* Distribute list install. */
4033: distribute_list_init (RIP_NODE);
4034: distribute_list_add_hook (rip_distribute_update);
4035: distribute_list_delete_hook (rip_distribute_update);
4036:
4037: /* Route-map */
4038: rip_route_map_init ();
4039: rip_offset_init ();
4040:
4041: route_map_add_hook (rip_routemap_update);
4042: route_map_delete_hook (rip_routemap_update);
4043:
4044: if_rmap_init (RIP_NODE);
4045: if_rmap_hook_add (rip_if_rmap_update);
4046: if_rmap_hook_delete (rip_if_rmap_update);
4047:
4048: /* Distance control. */
4049: rip_distance_table = route_table_init ();
4050: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>