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