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