1 /* 2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/mbuf.h> 40 #include <sys/protosw.h> 41 #include <sys/socket.h> 42 #include <sys/socketvar.h> 43 #include <sys/ioctl.h> 44 #include <sys/errno.h> 45 #include <sys/time.h> 46 #include <sys/proc.h> 47 48 #include <net/if.h> 49 #include <net/route.h> 50 51 #include <netinet/in.h> 52 #include <netinet/in_systm.h> 53 #include <netinet/ip.h> 54 #include <netinet/in_pcb.h> 55 #include <netinet/in_var.h> 56 #include <netinet/ip_var.h> 57 58 struct in_addr zeroin_addr; 59 60 int 61 in_pcballoc(so, head) 62 struct socket *so; 63 struct inpcb *head; 64 { 65 register struct inpcb *inp; 66 67 MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_WAITOK); 68 if (inp == NULL) 69 return (ENOBUFS); 70 bzero((caddr_t)inp, sizeof(*inp)); 71 inp->inp_head = head; 72 inp->inp_socket = so; 73 insque(inp, head); 74 so->so_pcb = (caddr_t)inp; 75 return (0); 76 } 77 78 int 79 in_pcbbind(inp, nam) 80 register struct inpcb *inp; 81 struct mbuf *nam; 82 { 83 register struct socket *so = inp->inp_socket; 84 register struct inpcb *head = inp->inp_head; 85 register struct sockaddr_in *sin; 86 struct proc *p = curproc; /* XXX */ 87 u_short lport = 0; 88 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); 89 int error; 90 91 if (in_ifaddr == 0) 92 return (EADDRNOTAVAIL); 93 if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY) 94 return (EINVAL); 95 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && 96 ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || 97 (so->so_options & SO_ACCEPTCONN) == 0)) 98 wild = INPLOOKUP_WILDCARD; 99 if (nam) { 100 sin = mtod(nam, struct sockaddr_in *); 101 if (nam->m_len != sizeof (*sin)) 102 return (EINVAL); 103 #ifdef notdef 104 /* 105 * We should check the family, but old programs 106 * incorrectly fail to initialize it. 107 */ 108 if (sin->sin_family != AF_INET) 109 return (EAFNOSUPPORT); 110 #endif 111 lport = sin->sin_port; 112 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 113 /* 114 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 115 * allow complete duplication of binding if 116 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 117 * and a multicast address is bound on both 118 * new and duplicated sockets. 119 */ 120 if (so->so_options & SO_REUSEADDR) 121 reuseport = SO_REUSEADDR|SO_REUSEPORT; 122 } else if (sin->sin_addr.s_addr != INADDR_ANY) { 123 sin->sin_port = 0; /* yech... */ 124 if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) 125 return (EADDRNOTAVAIL); 126 } 127 if (lport) { 128 struct inpcb *t; 129 130 /* GROSS */ 131 if (ntohs(lport) < IPPORT_RESERVED && 132 (error = suser(p->p_ucred, &p->p_acflag))) 133 return (error); 134 t = in_pcblookup(head, zeroin_addr, 0, 135 sin->sin_addr, lport, wild); 136 if (t && (reuseport & t->inp_socket->so_options) == 0) 137 return (EADDRINUSE); 138 } 139 inp->inp_laddr = sin->sin_addr; 140 } 141 if (lport == 0) 142 do { 143 if (head->inp_lport++ < IPPORT_RESERVED || 144 head->inp_lport > IPPORT_USERRESERVED) 145 head->inp_lport = IPPORT_RESERVED; 146 lport = htons(head->inp_lport); 147 } while (in_pcblookup(head, 148 zeroin_addr, 0, inp->inp_laddr, lport, wild)); 149 inp->inp_lport = lport; 150 return (0); 151 } 152 153 /* 154 * Connect from a socket to a specified address. 155 * Both address and port must be specified in argument sin. 156 * If don't have a local address for this socket yet, 157 * then pick one. 158 */ 159 int 160 in_pcbconnect(inp, nam) 161 register struct inpcb *inp; 162 struct mbuf *nam; 163 { 164 struct in_ifaddr *ia; 165 struct sockaddr_in *ifaddr = 0; 166 register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 167 168 if (nam->m_len != sizeof (*sin)) 169 return (EINVAL); 170 if (sin->sin_family != AF_INET) 171 return (EAFNOSUPPORT); 172 if (sin->sin_port == 0) 173 return (EADDRNOTAVAIL); 174 if (in_ifaddr) { 175 /* 176 * If the destination address is INADDR_ANY, 177 * use the primary local address. 178 * If the supplied address is INADDR_BROADCAST, 179 * and the primary interface supports broadcast, 180 * choose the broadcast address for that interface. 181 */ 182 #define satosin(sa) ((struct sockaddr_in *)(sa)) 183 #define sintosa(sin) ((struct sockaddr *)(sin)) 184 #define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) 185 if (sin->sin_addr.s_addr == INADDR_ANY) 186 sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr; 187 else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST && 188 (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST)) 189 sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr; 190 } 191 if (inp->inp_laddr.s_addr == INADDR_ANY) { 192 register struct route *ro; 193 194 ia = (struct in_ifaddr *)0; 195 /* 196 * If route is known or can be allocated now, 197 * our src addr is taken from the i/f, else punt. 198 */ 199 ro = &inp->inp_route; 200 if (ro->ro_rt && 201 (satosin(&ro->ro_dst)->sin_addr.s_addr != 202 sin->sin_addr.s_addr || 203 inp->inp_socket->so_options & SO_DONTROUTE)) { 204 RTFREE(ro->ro_rt); 205 ro->ro_rt = (struct rtentry *)0; 206 } 207 if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ 208 (ro->ro_rt == (struct rtentry *)0 || 209 ro->ro_rt->rt_ifp == (struct ifnet *)0)) { 210 /* No route yet, so try to acquire one */ 211 ro->ro_dst.sa_family = AF_INET; 212 ro->ro_dst.sa_len = sizeof(struct sockaddr_in); 213 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = 214 sin->sin_addr; 215 rtalloc(ro); 216 } 217 /* 218 * If we found a route, use the address 219 * corresponding to the outgoing interface 220 * unless it is the loopback (in case a route 221 * to our address on another net goes to loopback). 222 */ 223 if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) 224 ia = ifatoia(ro->ro_rt->rt_ifa); 225 if (ia == 0) { 226 u_short fport = sin->sin_port; 227 228 sin->sin_port = 0; 229 ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); 230 if (ia == 0) 231 ia = ifatoia(ifa_ifwithnet(sintosa(sin))); 232 sin->sin_port = fport; 233 if (ia == 0) 234 ia = in_ifaddr; 235 if (ia == 0) 236 return (EADDRNOTAVAIL); 237 } 238 /* 239 * If the destination address is multicast and an outgoing 240 * interface has been set as a multicast option, use the 241 * address of that interface as our source address. 242 */ 243 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && 244 inp->inp_moptions != NULL) { 245 struct ip_moptions *imo; 246 struct ifnet *ifp; 247 248 imo = inp->inp_moptions; 249 if (imo->imo_multicast_ifp != NULL) { 250 ifp = imo->imo_multicast_ifp; 251 for (ia = in_ifaddr; ia; ia = ia->ia_next) 252 if (ia->ia_ifp == ifp) 253 break; 254 if (ia == 0) 255 return (EADDRNOTAVAIL); 256 } 257 } 258 ifaddr = (struct sockaddr_in *)&ia->ia_addr; 259 } 260 if (in_pcblookup(inp->inp_head, 261 sin->sin_addr, 262 sin->sin_port, 263 inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr, 264 inp->inp_lport, 265 0)) 266 return (EADDRINUSE); 267 if (inp->inp_laddr.s_addr == INADDR_ANY) { 268 if (inp->inp_lport == 0) 269 (void)in_pcbbind(inp, (struct mbuf *)0); 270 inp->inp_laddr = ifaddr->sin_addr; 271 } 272 inp->inp_faddr = sin->sin_addr; 273 inp->inp_fport = sin->sin_port; 274 return (0); 275 } 276 277 void 278 in_pcbdisconnect(inp) 279 struct inpcb *inp; 280 { 281 282 inp->inp_faddr.s_addr = INADDR_ANY; 283 inp->inp_fport = 0; 284 if (inp->inp_socket->so_state & SS_NOFDREF) 285 in_pcbdetach(inp); 286 } 287 288 void 289 in_pcbdetach(inp) 290 struct inpcb *inp; 291 { 292 struct socket *so = inp->inp_socket; 293 294 so->so_pcb = 0; 295 sofree(so); 296 if (inp->inp_options) 297 (void)m_free(inp->inp_options); 298 if (inp->inp_route.ro_rt) 299 rtfree(inp->inp_route.ro_rt); 300 ip_freemoptions(inp->inp_moptions); 301 remque(inp); 302 FREE(inp, M_PCB); 303 } 304 305 void 306 in_setsockaddr(inp, nam) 307 register struct inpcb *inp; 308 struct mbuf *nam; 309 { 310 register struct sockaddr_in *sin; 311 312 nam->m_len = sizeof (*sin); 313 sin = mtod(nam, struct sockaddr_in *); 314 bzero((caddr_t)sin, sizeof (*sin)); 315 sin->sin_family = AF_INET; 316 sin->sin_len = sizeof(*sin); 317 sin->sin_port = inp->inp_lport; 318 sin->sin_addr = inp->inp_laddr; 319 } 320 321 void 322 in_setpeeraddr(inp, nam) 323 struct inpcb *inp; 324 struct mbuf *nam; 325 { 326 register struct sockaddr_in *sin; 327 328 nam->m_len = sizeof (*sin); 329 sin = mtod(nam, struct sockaddr_in *); 330 bzero((caddr_t)sin, sizeof (*sin)); 331 sin->sin_family = AF_INET; 332 sin->sin_len = sizeof(*sin); 333 sin->sin_port = inp->inp_fport; 334 sin->sin_addr = inp->inp_faddr; 335 } 336 337 /* 338 * Pass some notification to all connections of a protocol 339 * associated with address dst. The local address and/or port numbers 340 * may be specified to limit the search. The "usual action" will be 341 * taken, depending on the ctlinput cmd. The caller must filter any 342 * cmds that are uninteresting (e.g., no error in the map). 343 * Call the protocol specific routine (if any) to report 344 * any errors for each matching socket. 345 * 346 * Must be called at splnet. 347 */ 348 void 349 in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify) 350 struct inpcb *head; 351 struct sockaddr *dst; 352 u_int fport_arg, lport_arg; 353 struct in_addr laddr; 354 int cmd; 355 void (*notify) __P((struct inpcb *, int)); 356 { 357 extern u_char inetctlerrmap[]; 358 register struct inpcb *inp, *oinp; 359 struct in_addr faddr; 360 u_short fport = fport_arg, lport = lport_arg; 361 int errno; 362 363 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET) 364 return; 365 faddr = ((struct sockaddr_in *)dst)->sin_addr; 366 if (faddr.s_addr == INADDR_ANY) 367 return; 368 369 /* 370 * Redirects go to all references to the destination, 371 * and use in_rtchange to invalidate the route cache. 372 * Dead host indications: notify all references to the destination. 373 * Otherwise, if we have knowledge of the local port and address, 374 * deliver only to that socket. 375 */ 376 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { 377 fport = 0; 378 lport = 0; 379 laddr.s_addr = 0; 380 if (cmd != PRC_HOSTDEAD) 381 notify = in_rtchange; 382 } 383 errno = inetctlerrmap[cmd]; 384 for (inp = head->inp_next; inp != head;) { 385 if (inp->inp_faddr.s_addr != faddr.s_addr || 386 inp->inp_socket == 0 || 387 (lport && inp->inp_lport != lport) || 388 (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) || 389 (fport && inp->inp_fport != fport)) { 390 inp = inp->inp_next; 391 continue; 392 } 393 oinp = inp; 394 inp = inp->inp_next; 395 if (notify) 396 (*notify)(oinp, errno); 397 } 398 } 399 400 /* 401 * Check for alternatives when higher level complains 402 * about service problems. For now, invalidate cached 403 * routing information. If the route was created dynamically 404 * (by a redirect), time to try a default gateway again. 405 */ 406 void 407 in_losing(inp) 408 struct inpcb *inp; 409 { 410 register struct rtentry *rt; 411 struct rt_addrinfo info; 412 413 if ((rt = inp->inp_route.ro_rt)) { 414 inp->inp_route.ro_rt = 0; 415 bzero((caddr_t)&info, sizeof(info)); 416 info.rti_info[RTAX_DST] = 417 (struct sockaddr *)&inp->inp_route.ro_dst; 418 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 419 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 420 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 421 if (rt->rt_flags & RTF_DYNAMIC) 422 (void) rtrequest(RTM_DELETE, rt_key(rt), 423 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 424 (struct rtentry **)0); 425 else 426 /* 427 * A new route can be allocated 428 * the next time output is attempted. 429 */ 430 rtfree(rt); 431 } 432 } 433 434 /* 435 * After a routing change, flush old routing 436 * and allocate a (hopefully) better one. 437 */ 438 void 439 in_rtchange(inp, errno) 440 register struct inpcb *inp; 441 int errno; 442 { 443 if (inp->inp_route.ro_rt) { 444 rtfree(inp->inp_route.ro_rt); 445 inp->inp_route.ro_rt = 0; 446 /* 447 * A new route can be allocated the next time 448 * output is attempted. 449 */ 450 } 451 } 452 453 struct inpcb * 454 in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags) 455 struct inpcb *head; 456 struct in_addr faddr, laddr; 457 u_int fport_arg, lport_arg; 458 int flags; 459 { 460 register struct inpcb *inp, *match = 0; 461 int matchwild = 3, wildcard; 462 u_short fport = fport_arg, lport = lport_arg; 463 464 for (inp = head->inp_next; inp != head; inp = inp->inp_next) { 465 if (inp->inp_lport != lport) 466 continue; 467 wildcard = 0; 468 if (inp->inp_laddr.s_addr != INADDR_ANY) { 469 if (laddr.s_addr == INADDR_ANY) 470 wildcard++; 471 else if (inp->inp_laddr.s_addr != laddr.s_addr) 472 continue; 473 } else { 474 if (laddr.s_addr != INADDR_ANY) 475 wildcard++; 476 } 477 if (inp->inp_faddr.s_addr != INADDR_ANY) { 478 if (faddr.s_addr == INADDR_ANY) 479 wildcard++; 480 else if (inp->inp_faddr.s_addr != faddr.s_addr || 481 inp->inp_fport != fport) 482 continue; 483 } else { 484 if (faddr.s_addr != INADDR_ANY) 485 wildcard++; 486 } 487 if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0) 488 continue; 489 if (wildcard < matchwild) { 490 match = inp; 491 matchwild = wildcard; 492 if (matchwild == 0) 493 break; 494 } 495 } 496 return (match); 497 } 498