1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1999 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
33 */
34
35 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
36
37 /*
38 * Routing Table Management Daemon
39 */
40 #include "defs.h"
41
42 /*
43 * Apply the function "supply" to all active
44 * interfaces with a link-local address.
45 */
46 void
supplyall(struct sockaddr_in6 * sin6,int rtstate,struct interface * skipif,boolean_t splith)47 supplyall(struct sockaddr_in6 *sin6, int rtstate, struct interface *skipif,
48 boolean_t splith)
49 {
50 struct interface *ifp;
51
52 for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
53 if ((ifp->int_flags & RIP6_IFF_UP) == 0)
54 continue;
55 if (ifp->int_flags & RIP6_IFF_NORTEXCH) {
56 if (tracing & OUTPUT_BIT) {
57 (void) fprintf(ftrace,
58 "Suppress sending RIPng response packet "
59 "on %s (no route exchange on interface)\n",
60 ifp->int_name);
61 (void) fflush(ftrace);
62 }
63 continue;
64 }
65 if (ifp->int_sock == -1)
66 continue;
67 if (ifp == skipif)
68 continue;
69 if (!IN6_IS_ADDR_LINKLOCAL(&ifp->int_addr))
70 continue;
71 supply(sin6, ifp, rtstate, splith);
72 }
73 }
74
75 static void
solicit(struct sockaddr_in6 * sin6,struct interface * ifp)76 solicit(struct sockaddr_in6 *sin6, struct interface *ifp)
77 {
78 msg->rip6_cmd = RIPCMD6_REQUEST;
79 msg->rip6_vers = RIPVERSION6;
80 msg->rip6_nets[0].rip6_prefix = in6addr_any;
81 msg->rip6_nets[0].rip6_prefix_length = 0;
82 msg->rip6_nets[0].rip6_metric = HOPCNT_INFINITY;
83 sendpacket(sin6, ifp, sizeof (struct rip6), 0);
84 }
85
86 void
solicitall(struct sockaddr_in6 * sin6)87 solicitall(struct sockaddr_in6 *sin6)
88 {
89 struct interface *ifp;
90
91 for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
92 if ((ifp->int_flags & RIP6_IFF_UP) == 0)
93 continue;
94 if (ifp->int_flags & RIP6_IFF_NORTEXCH) {
95 if (tracing & OUTPUT_BIT) {
96 (void) fprintf(ftrace,
97 "Suppress sending RIPng request packet "
98 "on %s (no route exchange on interface)\n",
99 ifp->int_name);
100 (void) fflush(ftrace);
101 }
102 continue;
103 }
104 if (ifp->int_sock == -1)
105 continue;
106 solicit(sin6, ifp);
107 }
108 }
109
110
111 /*
112 * Output a preformed packet.
113 */
114 /*ARGSUSED*/
115 void
sendpacket(struct sockaddr_in6 * sin6,struct interface * ifp,int size,int flags)116 sendpacket(struct sockaddr_in6 *sin6, struct interface *ifp, int size,
117 int flags)
118 {
119 if (sendto(ifp->int_sock, packet, size, flags,
120 (struct sockaddr *)sin6, sizeof (*sin6)) < 0) {
121 syslog(LOG_ERR, "sendpacket: sendto: %m");
122 return;
123 }
124 TRACE_OUTPUT(ifp, sin6, sizeof (struct rip6));
125 ifp->int_opackets++;
126 }
127
128 /*
129 * Supply dst with the contents of the routing tables.
130 * If this won't fit in one packet, chop it up into several.
131 */
132 void
supply(struct sockaddr_in6 * sin6,struct interface * ifp,int rtstate,boolean_t splith)133 supply(struct sockaddr_in6 *sin6, struct interface *ifp, int rtstate,
134 boolean_t splith)
135 {
136 struct rt_entry *rt;
137 struct netinfo6 *n = msg->rip6_nets;
138 struct rthash *rh;
139 int size, i, maxsize;
140 uint8_t rtmetric;
141
142 msg->rip6_cmd = RIPCMD6_RESPONSE;
143 msg->rip6_vers = RIPVERSION6;
144
145 /*
146 * Initialize maxsize to the size of the largest RIPng packet supported
147 * on the outgoing interface.
148 */
149 maxsize = ifp->int_mtu - sizeof (ip6_t) - sizeof (struct udphdr);
150
151 for (i = IPV6_ABITS; i >= 0; i--) {
152 if (net_hashes[i] == NULL)
153 continue;
154
155 for (rh = net_hashes[i]; rh < &net_hashes[i][ROUTEHASHSIZ];
156 rh++) {
157 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh;
158 rt = rt->rt_forw) {
159
160 if (IN6_IS_ADDR_LINKLOCAL(&rt->rt_dst))
161 continue;
162 if (IN6_IS_ADDR_UNSPECIFIED(&rt->rt_dst))
163 continue;
164
165 /* do not send if private */
166 if (rt->rt_state & RTS_PRIVATE)
167 continue;
168
169 /*
170 * Don't resend the information
171 * on the network from which it was received.
172 */
173 if (splith && rt->rt_ifp != NULL &&
174 strcmp(ifp->int_ifbase,
175 rt->rt_ifp->int_ifbase) == 0) {
176 if (dopoison)
177 rtmetric = HOPCNT_INFINITY;
178 else
179 continue;
180 } else {
181 rtmetric = rt->rt_metric;
182 }
183
184 /*
185 * For dynamic updates, limit update to routes
186 * with the specified state.
187 */
188 if (rtstate != 0 &&
189 (rt->rt_state & rtstate) == 0)
190 continue;
191
192 /*
193 * Check if there is space for another RTE. If
194 * not, send the packet built up and reset n for
195 * the remaining RTEs.
196 */
197 size = (char *)n - packet;
198 if (size > maxsize - sizeof (struct netinfo6)) {
199 sendpacket(sin6, ifp, size, 0);
200 TRACE_OUTPUT(ifp, sin6, size);
201 n = msg->rip6_nets;
202 }
203 n->rip6_prefix = rt->rt_dst;
204 n->rip6_route_tag = rt->rt_tag;
205 n->rip6_prefix_length = rt->rt_prefix_length;
206 n->rip6_metric = min(rtmetric, HOPCNT_INFINITY);
207 n++;
208 } /* end of hash chain */
209 } /* end of particular prefix length */
210 } /* end of all prefix lengths */
211 if (n != msg->rip6_nets) {
212 size = (char *)n - packet;
213 sendpacket(sin6, ifp, size, 0);
214 TRACE_OUTPUT(ifp, sin6, size);
215 }
216 }
217