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