xref: /netbsd-src/sys/netinet/in_pcb.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
1 /*	$NetBSD: in_pcb.c,v 1.13 1995/04/13 06:28:21 cgd Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1991, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)in_pcb.c	8.2 (Berkeley) 1/4/94
36  */
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/ioctl.h>
46 #include <sys/errno.h>
47 #include <sys/time.h>
48 #include <sys/proc.h>
49 
50 #include <net/if.h>
51 #include <net/route.h>
52 
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netinet/in_pcb.h>
57 #include <netinet/in_var.h>
58 #include <netinet/ip_var.h>
59 
60 struct	in_addr zeroin_addr;
61 
62 int
63 in_pcballoc(so, head)
64 	struct socket *so;
65 	struct inpcb *head;
66 {
67 	register struct inpcb *inp;
68 
69 	MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_WAITOK);
70 	if (inp == NULL)
71 		return (ENOBUFS);
72 	bzero((caddr_t)inp, sizeof(*inp));
73 	inp->inp_head = head;
74 	inp->inp_socket = so;
75 	insque(inp, head);
76 	so->so_pcb = (caddr_t)inp;
77 	return (0);
78 }
79 
80 int
81 in_pcbbind(inp, nam)
82 	register struct inpcb *inp;
83 	struct mbuf *nam;
84 {
85 	register struct socket *so = inp->inp_socket;
86 	register struct inpcb *head = inp->inp_head;
87 	register struct sockaddr_in *sin;
88 	struct proc *p = curproc;		/* XXX */
89 	u_int16_t lport = 0;
90 	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
91 	int error;
92 
93 	if (in_ifaddr == 0)
94 		return (EADDRNOTAVAIL);
95 	if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
96 		return (EINVAL);
97 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
98 	    ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
99 	     (so->so_options & SO_ACCEPTCONN) == 0))
100 		wild = INPLOOKUP_WILDCARD;
101 	if (nam) {
102 		sin = mtod(nam, struct sockaddr_in *);
103 		if (nam->m_len != sizeof (*sin))
104 			return (EINVAL);
105 #ifdef notdef
106 		/*
107 		 * We should check the family, but old programs
108 		 * incorrectly fail to initialize it.
109 		 */
110 		if (sin->sin_family != AF_INET)
111 			return (EAFNOSUPPORT);
112 #endif
113 		lport = sin->sin_port;
114 		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
115 			/*
116 			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
117 			 * allow complete duplication of binding if
118 			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
119 			 * and a multicast address is bound on both
120 			 * new and duplicated sockets.
121 			 */
122 			if (so->so_options & SO_REUSEADDR)
123 				reuseport = SO_REUSEADDR|SO_REUSEPORT;
124 		} else if (sin->sin_addr.s_addr != INADDR_ANY) {
125 			sin->sin_port = 0;		/* yech... */
126 			if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
127 				return (EADDRNOTAVAIL);
128 		}
129 		if (lport) {
130 			struct inpcb *t;
131 
132 			/* GROSS */
133 			if (ntohs(lport) < IPPORT_RESERVED &&
134 			    (error = suser(p->p_ucred, &p->p_acflag)))
135 				return (EACCES);
136 			t = in_pcblookup(head, zeroin_addr, 0,
137 			    sin->sin_addr, lport, wild);
138 			if (t && (reuseport & t->inp_socket->so_options) == 0)
139 				return (EADDRINUSE);
140 		}
141 		inp->inp_laddr = sin->sin_addr;
142 	}
143 	if (lport == 0)
144 		do {
145 			if (head->inp_lport++ < IPPORT_RESERVED ||
146 			    head->inp_lport > IPPORT_USERRESERVED)
147 				head->inp_lport = IPPORT_RESERVED;
148 			lport = htons(head->inp_lport);
149 		} while (in_pcblookup(head,
150 			    zeroin_addr, 0, inp->inp_laddr, lport, wild));
151 	inp->inp_lport = lport;
152 	return (0);
153 }
154 
155 /*
156  * Connect from a socket to a specified address.
157  * Both address and port must be specified in argument sin.
158  * If don't have a local address for this socket yet,
159  * then pick one.
160  */
161 int
162 in_pcbconnect(inp, nam)
163 	register struct inpcb *inp;
164 	struct mbuf *nam;
165 {
166 	struct in_ifaddr *ia;
167 	struct sockaddr_in *ifaddr;
168 	register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
169 
170 	if (nam->m_len != sizeof (*sin))
171 		return (EINVAL);
172 	if (sin->sin_family != AF_INET)
173 		return (EAFNOSUPPORT);
174 	if (sin->sin_port == 0)
175 		return (EADDRNOTAVAIL);
176 	if (in_ifaddr) {
177 		/*
178 		 * If the destination address is INADDR_ANY,
179 		 * use the primary local address.
180 		 * If the supplied address is INADDR_BROADCAST,
181 		 * and the primary interface supports broadcast,
182 		 * choose the broadcast address for that interface.
183 		 */
184 #define	satosin(sa)	((struct sockaddr_in *)(sa))
185 #define sintosa(sin)	((struct sockaddr *)(sin))
186 #define ifatoia(ifa)	((struct in_ifaddr *)(ifa))
187 		if (sin->sin_addr.s_addr == INADDR_ANY)
188 		    sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
189 		else if (sin->sin_addr.s_addr == (u_int32_t)INADDR_BROADCAST &&
190 		  (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
191 		    sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
192 	}
193 	if (inp->inp_laddr.s_addr == INADDR_ANY) {
194 		register struct route *ro;
195 
196 		ia = (struct in_ifaddr *)0;
197 		/*
198 		 * If route is known or can be allocated now,
199 		 * our src addr is taken from the i/f, else punt.
200 		 */
201 		ro = &inp->inp_route;
202 		if (ro->ro_rt &&
203 		    (satosin(&ro->ro_dst)->sin_addr.s_addr !=
204 			sin->sin_addr.s_addr ||
205 		    inp->inp_socket->so_options & SO_DONTROUTE)) {
206 			RTFREE(ro->ro_rt);
207 			ro->ro_rt = (struct rtentry *)0;
208 		}
209 		if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
210 		    (ro->ro_rt == (struct rtentry *)0 ||
211 		    ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
212 			/* No route yet, so try to acquire one */
213 			ro->ro_dst.sa_family = AF_INET;
214 			ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
215 			((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
216 				sin->sin_addr;
217 			rtalloc(ro);
218 		}
219 		/*
220 		 * If we found a route, use the address
221 		 * corresponding to the outgoing interface
222 		 * unless it is the loopback (in case a route
223 		 * to our address on another net goes to loopback).
224 		 */
225 		if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
226 			ia = ifatoia(ro->ro_rt->rt_ifa);
227 		if (ia == 0) {
228 			u_int16_t fport = sin->sin_port;
229 
230 			sin->sin_port = 0;
231 			ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
232 			if (ia == 0)
233 				ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
234 			sin->sin_port = fport;
235 			if (ia == 0)
236 				ia = in_ifaddr;
237 			if (ia == 0)
238 				return (EADDRNOTAVAIL);
239 		}
240 		/*
241 		 * If the destination address is multicast and an outgoing
242 		 * interface has been set as a multicast option, use the
243 		 * address of that interface as our source address.
244 		 */
245 		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
246 		    inp->inp_moptions != NULL) {
247 			struct ip_moptions *imo;
248 			struct ifnet *ifp;
249 
250 			imo = inp->inp_moptions;
251 			if (imo->imo_multicast_ifp != NULL) {
252 				ifp = imo->imo_multicast_ifp;
253 				for (ia = in_ifaddr; ia; ia = ia->ia_next)
254 					if (ia->ia_ifp == ifp)
255 						break;
256 				if (ia == 0)
257 					return (EADDRNOTAVAIL);
258 			}
259 		}
260 		ifaddr = (struct sockaddr_in *)&ia->ia_addr;
261 	}
262 	if (in_pcblookup(inp->inp_head,
263 	    sin->sin_addr,
264 	    sin->sin_port,
265 	    inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
266 	    inp->inp_lport,
267 	    0))
268 		return (EADDRINUSE);
269 	if (inp->inp_laddr.s_addr == INADDR_ANY) {
270 		if (inp->inp_lport == 0)
271 			(void)in_pcbbind(inp, (struct mbuf *)0);
272 		inp->inp_laddr = ifaddr->sin_addr;
273 	}
274 	inp->inp_faddr = sin->sin_addr;
275 	inp->inp_fport = sin->sin_port;
276 	return (0);
277 }
278 
279 int
280 in_pcbdisconnect(inp)
281 	struct inpcb *inp;
282 {
283 
284 	inp->inp_faddr.s_addr = INADDR_ANY;
285 	inp->inp_fport = 0;
286 	if (inp->inp_socket->so_state & SS_NOFDREF)
287 		in_pcbdetach(inp);
288 }
289 
290 int
291 in_pcbdetach(inp)
292 	struct inpcb *inp;
293 {
294 	struct socket *so = inp->inp_socket;
295 
296 	so->so_pcb = 0;
297 	sofree(so);
298 	if (inp->inp_options)
299 		(void)m_free(inp->inp_options);
300 	if (inp->inp_route.ro_rt)
301 		rtfree(inp->inp_route.ro_rt);
302 	ip_freemoptions(inp->inp_moptions);
303 	remque(inp);
304 	FREE(inp, M_PCB);
305 }
306 
307 int
308 in_setsockaddr(inp, nam)
309 	register struct inpcb *inp;
310 	struct mbuf *nam;
311 {
312 	register struct sockaddr_in *sin;
313 
314 	nam->m_len = sizeof (*sin);
315 	sin = mtod(nam, struct sockaddr_in *);
316 	bzero((caddr_t)sin, sizeof (*sin));
317 	sin->sin_family = AF_INET;
318 	sin->sin_len = sizeof(*sin);
319 	sin->sin_port = inp->inp_lport;
320 	sin->sin_addr = inp->inp_laddr;
321 }
322 
323 int
324 in_setpeeraddr(inp, nam)
325 	struct inpcb *inp;
326 	struct mbuf *nam;
327 {
328 	register struct sockaddr_in *sin;
329 
330 	nam->m_len = sizeof (*sin);
331 	sin = mtod(nam, struct sockaddr_in *);
332 	bzero((caddr_t)sin, sizeof (*sin));
333 	sin->sin_family = AF_INET;
334 	sin->sin_len = sizeof(*sin);
335 	sin->sin_port = inp->inp_fport;
336 	sin->sin_addr = inp->inp_faddr;
337 }
338 
339 /*
340  * Pass some notification to all connections of a protocol
341  * associated with address dst.  The local address and/or port numbers
342  * may be specified to limit the search.  The "usual action" will be
343  * taken, depending on the ctlinput cmd.  The caller must filter any
344  * cmds that are uninteresting (e.g., no error in the map).
345  * Call the protocol specific routine (if any) to report
346  * any errors for each matching socket.
347  *
348  * Must be called at splnet.
349  */
350 int
351 in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
352 	struct inpcb *head;
353 	struct sockaddr *dst;
354 	u_int fport_arg, lport_arg;
355 	struct in_addr laddr;
356 	int cmd;
357 	void (*notify) __P((struct inpcb *, int));
358 {
359 	extern u_char inetctlerrmap[];
360 	register struct inpcb *inp, *oinp;
361 	struct in_addr faddr;
362 	u_int16_t fport = fport_arg, lport = lport_arg;
363 	int errno;
364 
365 	if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
366 		return;
367 	faddr = ((struct sockaddr_in *)dst)->sin_addr;
368 	if (faddr.s_addr == INADDR_ANY)
369 		return;
370 
371 	/*
372 	 * Redirects go to all references to the destination,
373 	 * and use in_rtchange to invalidate the route cache.
374 	 * Dead host indications: notify all references to the destination.
375 	 * Otherwise, if we have knowledge of the local port and address,
376 	 * deliver only to that socket.
377 	 */
378 	if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
379 		fport = 0;
380 		lport = 0;
381 		laddr.s_addr = 0;
382 		if (cmd != PRC_HOSTDEAD)
383 			notify = in_rtchange;
384 	}
385 	errno = inetctlerrmap[cmd];
386 	for (inp = head->inp_next; inp != head;) {
387 		if (inp->inp_faddr.s_addr != faddr.s_addr ||
388 		    inp->inp_socket == 0 ||
389 		    (lport && inp->inp_lport != lport) ||
390 		    (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
391 		    (fport && inp->inp_fport != fport)) {
392 			inp = inp->inp_next;
393 			continue;
394 		}
395 		oinp = inp;
396 		inp = inp->inp_next;
397 		if (notify)
398 			(*notify)(oinp, errno);
399 	}
400 }
401 
402 /*
403  * Check for alternatives when higher level complains
404  * about service problems.  For now, invalidate cached
405  * routing information.  If the route was created dynamically
406  * (by a redirect), time to try a default gateway again.
407  */
408 int
409 in_losing(inp)
410 	struct inpcb *inp;
411 {
412 	register struct rtentry *rt;
413 	struct rt_addrinfo info;
414 
415 	if ((rt = inp->inp_route.ro_rt)) {
416 		inp->inp_route.ro_rt = 0;
417 		bzero((caddr_t)&info, sizeof(info));
418 		info.rti_info[RTAX_DST] =
419 			(struct sockaddr *)&inp->inp_route.ro_dst;
420 		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
421 		info.rti_info[RTAX_NETMASK] = rt_mask(rt);
422 		rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
423 		if (rt->rt_flags & RTF_DYNAMIC)
424 			(void) rtrequest(RTM_DELETE, rt_key(rt),
425 				rt->rt_gateway, rt_mask(rt), rt->rt_flags,
426 				(struct rtentry **)0);
427 		else
428 		/*
429 		 * A new route can be allocated
430 		 * the next time output is attempted.
431 		 */
432 			rtfree(rt);
433 	}
434 }
435 
436 /*
437  * After a routing change, flush old routing
438  * and allocate a (hopefully) better one.
439  */
440 void
441 in_rtchange(inp, errno)
442 	register struct inpcb *inp;
443 	int errno;
444 {
445 	if (inp->inp_route.ro_rt) {
446 		rtfree(inp->inp_route.ro_rt);
447 		inp->inp_route.ro_rt = 0;
448 		/*
449 		 * A new route can be allocated the next time
450 		 * output is attempted.
451 		 */
452 	}
453 }
454 
455 struct inpcb *
456 in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
457 	struct inpcb *head;
458 	struct in_addr faddr, laddr;
459 	u_int fport_arg, lport_arg;
460 	int flags;
461 {
462 	register struct inpcb *inp, *match = 0;
463 	int matchwild = 3, wildcard;
464 	u_int16_t fport = fport_arg, lport = lport_arg;
465 
466 	for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
467 		if (inp->inp_lport != lport)
468 			continue;
469 		wildcard = 0;
470 		if (inp->inp_laddr.s_addr != INADDR_ANY) {
471 			if (laddr.s_addr == INADDR_ANY)
472 				wildcard++;
473 			else if (inp->inp_laddr.s_addr != laddr.s_addr)
474 				continue;
475 		} else {
476 			if (laddr.s_addr != INADDR_ANY)
477 				wildcard++;
478 		}
479 		if (inp->inp_faddr.s_addr != INADDR_ANY) {
480 			if (faddr.s_addr == INADDR_ANY)
481 				wildcard++;
482 			else if (inp->inp_faddr.s_addr != faddr.s_addr ||
483 			    inp->inp_fport != fport)
484 				continue;
485 		} else {
486 			if (faddr.s_addr != INADDR_ANY)
487 				wildcard++;
488 		}
489 		if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
490 			continue;
491 		if (wildcard < matchwild) {
492 			match = inp;
493 			matchwild = wildcard;
494 			if (matchwild == 0)
495 				break;
496 		}
497 	}
498 	return (match);
499 }
500