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