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 */
46void
47supplyall(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
75static void
76solicit(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
86void
87solicitall(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*/
115void
116sendpacket(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 */
132void
133supply(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