xref: /freebsd/sys/net/route.c (revision 0c43d89a0d8e976ca494d4837f4c1f3734d2c300)
1 /*
2  * Copyright (c) 1980, 1986, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)route.c	8.2 (Berkeley) 11/15/93
34  * $Id$
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/proc.h>
40 #include <sys/mbuf.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/domain.h>
44 #include <sys/protosw.h>
45 #include <sys/ioctl.h>
46 
47 #include <net/if.h>
48 #include <net/route.h>
49 #include <net/raw_cb.h>
50 
51 #include <netinet/in.h>
52 #include <netinet/in_var.h>
53 
54 #ifdef NS
55 #include <netns/ns.h>
56 #endif
57 
58 #define	SA(p) ((struct sockaddr *)(p))
59 
60 int	rttrash;		/* routes not in table but not freed */
61 struct	sockaddr wildcard;	/* zero valued cookie for wildcard searches */
62 
63 void
64 rtable_init(table)
65 	void **table;
66 {
67 	struct domain *dom;
68 	for (dom = domains; dom; dom = dom->dom_next)
69 		if (dom->dom_rtattach)
70 			dom->dom_rtattach(&table[dom->dom_family],
71 			    dom->dom_rtoffset);
72 }
73 
74 void
75 route_init()
76 {
77 	rn_init();	/* initialize all zeroes, all ones, mask table */
78 	rtable_init((void **)rt_tables);
79 }
80 
81 /*
82  * Packet routing routines.
83  */
84 void
85 rtalloc(ro)
86 	register struct route *ro;
87 {
88 	if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
89 		return;				 /* XXX */
90 	ro->ro_rt = rtalloc1(&ro->ro_dst, 1);
91 }
92 
93 struct rtentry *
94 rtalloc1(dst, report)
95 	register struct sockaddr *dst;
96 	int report;
97 {
98 	register struct radix_node_head *rnh = rt_tables[dst->sa_family];
99 	register struct rtentry *rt;
100 	register struct radix_node *rn;
101 	struct rtentry *newrt = 0;
102 	struct rt_addrinfo info;
103 	int  s = splnet(), err = 0, msgtype = RTM_MISS;
104 
105 	if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
106 	    ((rn->rn_flags & RNF_ROOT) == 0)) {
107 		newrt = rt = (struct rtentry *)rn;
108 		if (report && (rt->rt_flags & RTF_CLONING)) {
109 			err = rtrequest(RTM_RESOLVE, dst, SA(0),
110 					      SA(0), 0, &newrt);
111 			if (err) {
112 				newrt = rt;
113 				rt->rt_refcnt++;
114 				goto miss;
115 			}
116 			if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
117 				msgtype = RTM_RESOLVE;
118 				goto miss;
119 			}
120 		} else
121 			rt->rt_refcnt++;
122 	} else {
123 		rtstat.rts_unreach++;
124 	miss:	if (report) {
125 			bzero((caddr_t)&info, sizeof(info));
126 			info.rti_info[RTAX_DST] = dst;
127 			rt_missmsg(msgtype, &info, 0, err);
128 		}
129 	}
130 	splx(s);
131 	return (newrt);
132 }
133 
134 void
135 rtfree(rt)
136 	register struct rtentry *rt;
137 {
138 	register struct ifaddr *ifa;
139 
140 	if (rt == 0)
141 		panic("rtfree");
142 	rt->rt_refcnt--;
143 	if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
144 		if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
145 			panic ("rtfree 2");
146 		rttrash--;
147 		if (rt->rt_refcnt < 0) {
148 			printf("rtfree: %x not freed (neg refs)\n", rt);
149 			return;
150 		}
151 		ifa = rt->rt_ifa;
152 		IFAFREE(ifa);
153 		Free(rt_key(rt));
154 		Free(rt);
155 	}
156 }
157 
158 void
159 ifafree(ifa)
160 	register struct ifaddr *ifa;
161 {
162 	if (ifa == NULL)
163 		panic("ifafree");
164 	if (ifa->ifa_refcnt == 0)
165 		free(ifa, M_IFADDR);
166 	else
167 		ifa->ifa_refcnt--;
168 }
169 
170 /*
171  * Force a routing table entry to the specified
172  * destination to go through the given gateway.
173  * Normally called as a result of a routing redirect
174  * message from the network layer.
175  *
176  * N.B.: must be called at splnet
177  *
178  */
179 void
180 rtredirect(dst, gateway, netmask, flags, src, rtp)
181 	struct sockaddr *dst, *gateway, *netmask, *src;
182 	int flags;
183 	struct rtentry **rtp;
184 {
185 	register struct rtentry *rt;
186 	int error = 0;
187 	short *stat = 0;
188 	struct rt_addrinfo info;
189 	struct ifaddr *ifa;
190 
191 	/* verify the gateway is directly reachable */
192 	if ((ifa = ifa_ifwithnet(gateway)) == 0) {
193 		error = ENETUNREACH;
194 		goto out;
195 	}
196 	rt = rtalloc1(dst, 0);
197 	/*
198 	 * If the redirect isn't from our current router for this dst,
199 	 * it's either old or wrong.  If it redirects us to ourselves,
200 	 * we have a routing loop, perhaps as a result of an interface
201 	 * going down recently.
202 	 */
203 #define	equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
204 	if (!(flags & RTF_DONE) && rt &&
205 	     (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
206 		error = EINVAL;
207 	else if (ifa_ifwithaddr(gateway))
208 		error = EHOSTUNREACH;
209 	if (error)
210 		goto done;
211 	/*
212 	 * Create a new entry if we just got back a wildcard entry
213 	 * or the the lookup failed.  This is necessary for hosts
214 	 * which use routing redirects generated by smart gateways
215 	 * to dynamically build the routing tables.
216 	 */
217 	if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
218 		goto create;
219 	/*
220 	 * Don't listen to the redirect if it's
221 	 * for a route to an interface.
222 	 */
223 	if (rt->rt_flags & RTF_GATEWAY) {
224 		if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
225 			/*
226 			 * Changing from route to net => route to host.
227 			 * Create new route, rather than smashing route to net.
228 			 */
229 		create:
230 			flags |=  RTF_GATEWAY | RTF_DYNAMIC;
231 			error = rtrequest((int)RTM_ADD, dst, gateway,
232 				    netmask, flags,
233 				    (struct rtentry **)0);
234 			stat = &rtstat.rts_dynamic;
235 		} else {
236 			/*
237 			 * Smash the current notion of the gateway to
238 			 * this destination.  Should check about netmask!!!
239 			 */
240 			rt->rt_flags |= RTF_MODIFIED;
241 			flags |= RTF_MODIFIED;
242 			stat = &rtstat.rts_newgateway;
243 			rt_setgate(rt, rt_key(rt), gateway);
244 		}
245 	} else
246 		error = EHOSTUNREACH;
247 done:
248 	if (rt) {
249 		if (rtp && !error)
250 			*rtp = rt;
251 		else
252 			rtfree(rt);
253 	}
254 out:
255 	if (error)
256 		rtstat.rts_badredirect++;
257 	else if (stat != NULL)
258 		(*stat)++;
259 	bzero((caddr_t)&info, sizeof(info));
260 	info.rti_info[RTAX_DST] = dst;
261 	info.rti_info[RTAX_GATEWAY] = gateway;
262 	info.rti_info[RTAX_NETMASK] = netmask;
263 	info.rti_info[RTAX_AUTHOR] = src;
264 	rt_missmsg(RTM_REDIRECT, &info, flags, error);
265 }
266 
267 /*
268 * Routing table ioctl interface.
269 */
270 int
271 rtioctl(req, data, p)
272 	int req;
273 	caddr_t data;
274 	struct proc *p;
275 {
276 	return (EOPNOTSUPP);
277 }
278 
279 struct ifaddr *
280 ifa_ifwithroute(flags, dst, gateway)
281 	int flags;
282 	struct sockaddr	*dst, *gateway;
283 {
284 	register struct ifaddr *ifa;
285 	if ((flags & RTF_GATEWAY) == 0) {
286 		/*
287 		 * If we are adding a route to an interface,
288 		 * and the interface is a pt to pt link
289 		 * we should search for the destination
290 		 * as our clue to the interface.  Otherwise
291 		 * we can use the local address.
292 		 */
293 		ifa = 0;
294 		if (flags & RTF_HOST)
295 			ifa = ifa_ifwithdstaddr(dst);
296 		if (ifa == 0)
297 			ifa = ifa_ifwithaddr(gateway);
298 	} else {
299 		/*
300 		 * If we are adding a route to a remote net
301 		 * or host, the gateway may still be on the
302 		 * other end of a pt to pt link.
303 		 */
304 		ifa = ifa_ifwithdstaddr(gateway);
305 	}
306 	if (ifa == 0)
307 		ifa = ifa_ifwithnet(gateway);
308 	if (ifa == 0) {
309 		struct rtentry *rt = rtalloc1(dst, 0);
310 		if (rt == 0)
311 			return (0);
312 		rt->rt_refcnt--;
313 		if ((ifa = rt->rt_ifa) == 0)
314 			return (0);
315 	}
316 	if (ifa->ifa_addr->sa_family != dst->sa_family) {
317 		struct ifaddr *oifa = ifa;
318 		ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
319 		if (ifa == 0)
320 			ifa = oifa;
321 	}
322 	return (ifa);
323 }
324 
325 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
326 
327 int
328 rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
329 	int req, flags;
330 	struct sockaddr *dst, *gateway, *netmask;
331 	struct rtentry **ret_nrt;
332 {
333 	int s = splnet(); int error = 0;
334 	register struct rtentry *rt;
335 	register struct radix_node *rn;
336 	register struct radix_node_head *rnh;
337 	struct ifaddr *ifa;
338 	struct sockaddr *ndst;
339 #define senderr(x) { error = x ; goto bad; }
340 
341 	if ((rnh = rt_tables[dst->sa_family]) == 0)
342 		senderr(ESRCH);
343 	if (flags & RTF_HOST)
344 		netmask = 0;
345 	switch (req) {
346 	case RTM_DELETE:
347 		if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0)
348 			senderr(ESRCH);
349 		if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
350 			panic ("rtrequest delete");
351 		rt = (struct rtentry *)rn;
352 		rt->rt_flags &= ~RTF_UP;
353 		if (rt->rt_gwroute) {
354 			rt = rt->rt_gwroute; RTFREE(rt);
355 			(rt = (struct rtentry *)rn)->rt_gwroute = 0;
356 		}
357 		if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
358 			ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
359 		rttrash++;
360 		if (ret_nrt)
361 			*ret_nrt = rt;
362 		else if (rt->rt_refcnt <= 0) {
363 			rt->rt_refcnt++;
364 			rtfree(rt);
365 		}
366 		break;
367 
368 	case RTM_RESOLVE:
369 		if (ret_nrt == 0 || (rt = *ret_nrt) == 0)
370 			senderr(EINVAL);
371 		ifa = rt->rt_ifa;
372 		flags = rt->rt_flags & ~RTF_CLONING;
373 		gateway = rt->rt_gateway;
374 		if ((netmask = rt->rt_genmask) == 0)
375 			flags |= RTF_HOST;
376 		goto makeroute;
377 
378 	case RTM_ADD:
379 		if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
380 			senderr(ENETUNREACH);
381 	makeroute:
382 		R_Malloc(rt, struct rtentry *, sizeof(*rt));
383 		if (rt == 0)
384 			senderr(ENOBUFS);
385 		Bzero(rt, sizeof(*rt));
386 		rt->rt_flags = RTF_UP | flags;
387 		if (rt_setgate(rt, dst, gateway)) {
388 			Free(rt);
389 			senderr(ENOBUFS);
390 		}
391 		ndst = rt_key(rt);
392 		if (netmask) {
393 			rt_maskedcopy(dst, ndst, netmask);
394 		} else
395 			Bcopy(dst, ndst, dst->sa_len);
396 		rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask,
397 					rnh, rt->rt_nodes);
398 		if (rn == 0) {
399 			if (rt->rt_gwroute)
400 				rtfree(rt->rt_gwroute);
401 			Free(rt_key(rt));
402 			Free(rt);
403 			senderr(EEXIST);
404 		}
405 		ifa->ifa_refcnt++;
406 		rt->rt_ifa = ifa;
407 		rt->rt_ifp = ifa->ifa_ifp;
408 		if (req == RTM_RESOLVE)
409 			rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
410 		if (ifa->ifa_rtrequest)
411 			ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
412 		if (ret_nrt) {
413 			*ret_nrt = rt;
414 			rt->rt_refcnt++;
415 		}
416 		break;
417 	}
418 bad:
419 	splx(s);
420 	return (error);
421 }
422 
423 int
424 rt_setgate(rt0, dst, gate)
425 	struct rtentry *rt0;
426 	struct sockaddr *dst, *gate;
427 {
428 	caddr_t new, old;
429 	int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
430 	register struct rtentry *rt = rt0;
431 
432 	if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) {
433 		old = (caddr_t)rt_key(rt);
434 		R_Malloc(new, caddr_t, dlen + glen);
435 		if (new == 0)
436 			return 1;
437 		rt->rt_nodes->rn_key = new;
438 	} else {
439 		new = rt->rt_nodes->rn_key;
440 		old = 0;
441 	}
442 	Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
443 	if (old) {
444 		Bcopy(dst, new, dlen);
445 		Free(old);
446 	}
447 	if (rt->rt_gwroute) {
448 		rt = rt->rt_gwroute; RTFREE(rt);
449 		rt = rt0; rt->rt_gwroute = 0;
450 	}
451 	if (rt->rt_flags & RTF_GATEWAY) {
452 		rt->rt_gwroute = rtalloc1(gate, 1);
453 	}
454 	return 0;
455 }
456 
457 void
458 rt_maskedcopy(src, dst, netmask)
459 	struct sockaddr *src, *dst, *netmask;
460 {
461 	register u_char *cp1 = (u_char *)src;
462 	register u_char *cp2 = (u_char *)dst;
463 	register u_char *cp3 = (u_char *)netmask;
464 	u_char *cplim = cp2 + *cp3;
465 	u_char *cplim2 = cp2 + *cp1;
466 
467 	*cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */
468 	cp3 += 2;
469 	if (cplim > cplim2)
470 		cplim = cplim2;
471 	while (cp2 < cplim)
472 		*cp2++ = *cp1++ & *cp3++;
473 	if (cp2 < cplim2)
474 		bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2));
475 }
476 
477 /*
478  * Set up a routing table entry, normally
479  * for an interface.
480  */
481 int
482 rtinit(ifa, cmd, flags)
483 	register struct ifaddr *ifa;
484 	int cmd, flags;
485 {
486 	register struct rtentry *rt;
487 	register struct sockaddr *dst;
488 	register struct sockaddr *deldst;
489 	struct mbuf *m = 0;
490 	struct rtentry *nrt = 0;
491 	int error;
492 
493 	dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
494 	if (cmd == RTM_DELETE) {
495 		if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
496 			m = m_get(M_WAIT, MT_SONAME);
497 			deldst = mtod(m, struct sockaddr *);
498 			rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
499 			dst = deldst;
500 		}
501 		if (rt = rtalloc1(dst, 0)) {
502 			rt->rt_refcnt--;
503 			if (rt->rt_ifa != ifa) {
504 				if (m)
505 					(void) m_free(m);
506 				return (flags & RTF_HOST ? EHOSTUNREACH
507 							: ENETUNREACH);
508 			}
509 		}
510 	}
511 	error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask,
512 			flags | ifa->ifa_flags, &nrt);
513 	if (m)
514 		(void) m_free(m);
515 	if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
516 		rt_newaddrmsg(cmd, ifa, error, nrt);
517 		if (rt->rt_refcnt <= 0) {
518 			rt->rt_refcnt++;
519 			rtfree(rt);
520 		}
521 	}
522 	if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
523 		rt->rt_refcnt--;
524 		if (rt->rt_ifa != ifa) {
525 			printf("rtinit: wrong ifa (%x) was (%x)\n", ifa,
526 				rt->rt_ifa);
527 			if (rt->rt_ifa->ifa_rtrequest)
528 			    rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
529 			IFAFREE(rt->rt_ifa);
530 			rt->rt_ifa = ifa;
531 			rt->rt_ifp = ifa->ifa_ifp;
532 			ifa->ifa_refcnt++;
533 			if (ifa->ifa_rtrequest)
534 			    ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
535 		}
536 		rt_newaddrmsg(cmd, ifa, error, nrt);
537 	}
538 	return (error);
539 }
540