in_pcb.c revision 1.15 1 /* $NetBSD: in_pcb.c,v 1.15 1995/06/04 05:06:58 mycroft 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(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(sintosa(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 if (sin->sin_addr.s_addr == INADDR_ANY)
185 sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
186 else if (sin->sin_addr.s_addr == INADDR_BROADCAST &&
187 (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
188 sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
189 }
190 if (inp->inp_laddr.s_addr == INADDR_ANY) {
191 register struct route *ro;
192
193 ia = (struct in_ifaddr *)0;
194 /*
195 * If route is known or can be allocated now,
196 * our src addr is taken from the i/f, else punt.
197 */
198 ro = &inp->inp_route;
199 if (ro->ro_rt &&
200 (satosin(&ro->ro_dst)->sin_addr.s_addr !=
201 sin->sin_addr.s_addr ||
202 inp->inp_socket->so_options & SO_DONTROUTE)) {
203 RTFREE(ro->ro_rt);
204 ro->ro_rt = (struct rtentry *)0;
205 }
206 if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
207 (ro->ro_rt == (struct rtentry *)0 ||
208 ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
209 /* No route yet, so try to acquire one */
210 ro->ro_dst.sa_family = AF_INET;
211 ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
212 satosin(&ro->ro_dst)->sin_addr = sin->sin_addr;
213 rtalloc(ro);
214 }
215 /*
216 * If we found a route, use the address
217 * corresponding to the outgoing interface
218 * unless it is the loopback (in case a route
219 * to our address on another net goes to loopback).
220 */
221 if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
222 ia = ifatoia(ro->ro_rt->rt_ifa);
223 if (ia == 0) {
224 u_int16_t fport = sin->sin_port;
225
226 sin->sin_port = 0;
227 ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
228 if (ia == 0)
229 ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
230 sin->sin_port = fport;
231 if (ia == 0)
232 ia = in_ifaddr;
233 if (ia == 0)
234 return (EADDRNOTAVAIL);
235 }
236 /*
237 * If the destination address is multicast and an outgoing
238 * interface has been set as a multicast option, use the
239 * address of that interface as our source address.
240 */
241 if (IN_MULTICAST(sin->sin_addr.s_addr) &&
242 inp->inp_moptions != NULL) {
243 struct ip_moptions *imo;
244 struct ifnet *ifp;
245
246 imo = inp->inp_moptions;
247 if (imo->imo_multicast_ifp != NULL) {
248 ifp = imo->imo_multicast_ifp;
249 for (ia = in_ifaddr; ia; ia = ia->ia_next)
250 if (ia->ia_ifp == ifp)
251 break;
252 if (ia == 0)
253 return (EADDRNOTAVAIL);
254 }
255 }
256 ifaddr = satosin(&ia->ia_addr);
257 }
258 if (in_pcblookup(inp->inp_head,
259 sin->sin_addr,
260 sin->sin_port,
261 inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
262 inp->inp_lport,
263 0))
264 return (EADDRINUSE);
265 if (inp->inp_laddr.s_addr == INADDR_ANY) {
266 if (inp->inp_lport == 0)
267 (void)in_pcbbind(inp, (struct mbuf *)0);
268 inp->inp_laddr = ifaddr->sin_addr;
269 }
270 inp->inp_faddr = sin->sin_addr;
271 inp->inp_fport = sin->sin_port;
272 return (0);
273 }
274
275 int
276 in_pcbdisconnect(inp)
277 struct inpcb *inp;
278 {
279
280 inp->inp_faddr.s_addr = INADDR_ANY;
281 inp->inp_fport = 0;
282 if (inp->inp_socket->so_state & SS_NOFDREF)
283 in_pcbdetach(inp);
284 }
285
286 int
287 in_pcbdetach(inp)
288 struct inpcb *inp;
289 {
290 struct socket *so = inp->inp_socket;
291
292 so->so_pcb = 0;
293 sofree(so);
294 if (inp->inp_options)
295 (void)m_free(inp->inp_options);
296 if (inp->inp_route.ro_rt)
297 rtfree(inp->inp_route.ro_rt);
298 ip_freemoptions(inp->inp_moptions);
299 remque(inp);
300 FREE(inp, M_PCB);
301 }
302
303 int
304 in_setsockaddr(inp, nam)
305 register struct inpcb *inp;
306 struct mbuf *nam;
307 {
308 register struct sockaddr_in *sin;
309
310 nam->m_len = sizeof (*sin);
311 sin = mtod(nam, struct sockaddr_in *);
312 bzero((caddr_t)sin, sizeof (*sin));
313 sin->sin_family = AF_INET;
314 sin->sin_len = sizeof(*sin);
315 sin->sin_port = inp->inp_lport;
316 sin->sin_addr = inp->inp_laddr;
317 }
318
319 int
320 in_setpeeraddr(inp, nam)
321 struct inpcb *inp;
322 struct mbuf *nam;
323 {
324 register struct sockaddr_in *sin;
325
326 nam->m_len = sizeof (*sin);
327 sin = mtod(nam, struct sockaddr_in *);
328 bzero((caddr_t)sin, sizeof (*sin));
329 sin->sin_family = AF_INET;
330 sin->sin_len = sizeof(*sin);
331 sin->sin_port = inp->inp_fport;
332 sin->sin_addr = inp->inp_faddr;
333 }
334
335 /*
336 * Pass some notification to all connections of a protocol
337 * associated with address dst. The local address and/or port numbers
338 * may be specified to limit the search. The "usual action" will be
339 * taken, depending on the ctlinput cmd. The caller must filter any
340 * cmds that are uninteresting (e.g., no error in the map).
341 * Call the protocol specific routine (if any) to report
342 * any errors for each matching socket.
343 *
344 * Must be called at splnet.
345 */
346 int
347 in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
348 struct inpcb *head;
349 struct sockaddr *dst;
350 u_int fport_arg, lport_arg;
351 struct in_addr laddr;
352 int cmd;
353 void (*notify) __P((struct inpcb *, int));
354 {
355 extern u_char inetctlerrmap[];
356 register struct inpcb *inp, *oinp;
357 struct in_addr faddr;
358 u_int16_t fport = fport_arg, lport = lport_arg;
359 int errno;
360
361 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
362 return;
363 faddr = satosin(dst)->sin_addr;
364 if (faddr.s_addr == INADDR_ANY)
365 return;
366
367 /*
368 * Redirects go to all references to the destination,
369 * and use in_rtchange to invalidate the route cache.
370 * Dead host indications: notify all references to the destination.
371 * Otherwise, if we have knowledge of the local port and address,
372 * deliver only to that socket.
373 */
374 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
375 fport = 0;
376 lport = 0;
377 laddr.s_addr = 0;
378 if (cmd != PRC_HOSTDEAD)
379 notify = in_rtchange;
380 }
381 errno = inetctlerrmap[cmd];
382 for (inp = head->inp_next; inp != head;) {
383 if (inp->inp_faddr.s_addr != faddr.s_addr ||
384 inp->inp_socket == 0 ||
385 (lport && inp->inp_lport != lport) ||
386 (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
387 (fport && inp->inp_fport != fport)) {
388 inp = inp->inp_next;
389 continue;
390 }
391 oinp = inp;
392 inp = inp->inp_next;
393 if (notify)
394 (*notify)(oinp, errno);
395 }
396 }
397
398 /*
399 * Check for alternatives when higher level complains
400 * about service problems. For now, invalidate cached
401 * routing information. If the route was created dynamically
402 * (by a redirect), time to try a default gateway again.
403 */
404 int
405 in_losing(inp)
406 struct inpcb *inp;
407 {
408 register struct rtentry *rt;
409 struct rt_addrinfo info;
410
411 if ((rt = inp->inp_route.ro_rt)) {
412 inp->inp_route.ro_rt = 0;
413 bzero((caddr_t)&info, sizeof(info));
414 info.rti_info[RTAX_DST] = sintosa(&inp->inp_route.ro_dst);
415 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
416 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
417 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
418 if (rt->rt_flags & RTF_DYNAMIC)
419 (void) rtrequest(RTM_DELETE, rt_key(rt),
420 rt->rt_gateway, rt_mask(rt), rt->rt_flags,
421 (struct rtentry **)0);
422 else
423 /*
424 * A new route can be allocated
425 * the next time output is attempted.
426 */
427 rtfree(rt);
428 }
429 }
430
431 /*
432 * After a routing change, flush old routing
433 * and allocate a (hopefully) better one.
434 */
435 void
436 in_rtchange(inp, errno)
437 register struct inpcb *inp;
438 int errno;
439 {
440 if (inp->inp_route.ro_rt) {
441 rtfree(inp->inp_route.ro_rt);
442 inp->inp_route.ro_rt = 0;
443 /*
444 * A new route can be allocated the next time
445 * output is attempted.
446 */
447 }
448 }
449
450 struct inpcb *
451 in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
452 struct inpcb *head;
453 struct in_addr faddr, laddr;
454 u_int fport_arg, lport_arg;
455 int flags;
456 {
457 register struct inpcb *inp, *match = 0;
458 int matchwild = 3, wildcard;
459 u_int16_t fport = fport_arg, lport = lport_arg;
460
461 for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
462 if (inp->inp_lport != lport)
463 continue;
464 wildcard = 0;
465 if (inp->inp_laddr.s_addr != INADDR_ANY) {
466 if (laddr.s_addr == INADDR_ANY)
467 wildcard++;
468 else if (inp->inp_laddr.s_addr != laddr.s_addr)
469 continue;
470 } else {
471 if (laddr.s_addr != INADDR_ANY)
472 wildcard++;
473 }
474 if (inp->inp_faddr.s_addr != INADDR_ANY) {
475 if (faddr.s_addr == INADDR_ANY)
476 wildcard++;
477 else if (inp->inp_faddr.s_addr != faddr.s_addr ||
478 inp->inp_fport != fport)
479 continue;
480 } else {
481 if (faddr.s_addr != INADDR_ANY)
482 wildcard++;
483 }
484 if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
485 continue;
486 if (wildcard < matchwild) {
487 match = inp;
488 matchwild = wildcard;
489 if (matchwild == 0)
490 break;
491 }
492 }
493 return (match);
494 }
495