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