1*25202Skarels #ifdef RCSIDENT 2*25202Skarels static char rcsident[] = "$Header: in_pcb.c,v 1.12 84/11/29 17:02:13 walsh Exp $"; 3*25202Skarels #endif RCSIDENT 4*25202Skarels 5*25202Skarels #include "../h/param.h" 6*25202Skarels #include "../h/systm.h" 7*25202Skarels #include "../h/dir.h" 8*25202Skarels #include "../h/user.h" 9*25202Skarels #include "../h/mbuf.h" 10*25202Skarels #include "../h/socket.h" 11*25202Skarels #include "../h/socketvar.h" 12*25202Skarels #include "../h/protosw.h" 13*25202Skarels #include "../h/domain.h" 14*25202Skarels 15*25202Skarels #include "../net/if.h" 16*25202Skarels #include "../net/route.h" 17*25202Skarels 18*25202Skarels #include "../bbnnet/in.h" 19*25202Skarels #include "../bbnnet/net.h" 20*25202Skarels #include "../bbnnet/in_pcb.h" 21*25202Skarels #include "../bbnnet/in_var.h" 22*25202Skarels 23*25202Skarels extern struct rtentry *ip_route(); 24*25202Skarels extern struct domain inetdomain; 25*25202Skarels 26*25202Skarels in_pcballoc(so, head) 27*25202Skarels struct socket *so; 28*25202Skarels struct inpcb *head; 29*25202Skarels { 30*25202Skarels register struct mbuf *m; 31*25202Skarels register struct inpcb *inp; 32*25202Skarels 33*25202Skarels m = m_getclr(M_DONTWAIT, MT_PCB); 34*25202Skarels if (m == NULL) 35*25202Skarels return (ENOBUFS); 36*25202Skarels 37*25202Skarels inp = mtod(m, struct inpcb *); 38*25202Skarels inp->inp_socket = so; 39*25202Skarels 40*25202Skarels insque(inp,head); 41*25202Skarels 42*25202Skarels so->so_pcb = (caddr_t)inp; 43*25202Skarels 44*25202Skarels return (0); 45*25202Skarels } 46*25202Skarels 47*25202Skarels /* 48*25202Skarels * changed from 4.2 to accept a structure which has protocol 49*25202Skarels * specific data like how to break down port allocation. 50*25202Skarels */ 51*25202Skarels 52*25202Skarels in_pcbbind(inp, nam, advice) 53*25202Skarels register struct inpcb *inp; 54*25202Skarels struct mbuf *nam; 55*25202Skarels struct pr_advice *advice; 56*25202Skarels { 57*25202Skarels register struct socket *so = inp->inp_socket; 58*25202Skarels register struct sockaddr_in *sin; 59*25202Skarels register u_short lport = 0; 60*25202Skarels 61*25202Skarels if (in_ifaddr == NULL) 62*25202Skarels return (EADDRNOTAVAIL); 63*25202Skarels /* 64*25202Skarels * socket must not already be bound 65*25202Skarels */ 66*25202Skarels 67*25202Skarels if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY) 68*25202Skarels return (EINVAL); 69*25202Skarels 70*25202Skarels if (nam == 0) 71*25202Skarels goto noname; 72*25202Skarels sin = mtod(nam, struct sockaddr_in *); 73*25202Skarels if (nam->m_len != sizeof (*sin)) 74*25202Skarels return (EINVAL); 75*25202Skarels /* 76*25202Skarels * Since Berkeley left this out, some of their programs (ftpd) 77*25202Skarels * aren't ready for it 78*25202Skarels * 79*25202Skarels if (sin->sin_family != AF_INET) 80*25202Skarels return (EAFNOSUPPORT); 81*25202Skarels */ 82*25202Skarels 83*25202Skarels if (sin->sin_addr.s_addr != INADDR_ANY) 84*25202Skarels { 85*25202Skarels /* some code says ..withnet() */ 86*25202Skarels if (in_iawithaddr(sin->sin_addr, FALSE) == NULL) 87*25202Skarels return (EADDRNOTAVAIL); 88*25202Skarels 89*25202Skarels } 90*25202Skarels 91*25202Skarels /* user gives port to us in net order */ 92*25202Skarels if (lport = sin->sin_port) 93*25202Skarels { 94*25202Skarels u_short aport; 95*25202Skarels 96*25202Skarels /* if portsize > 2 a major rewrite needed to 97*25202Skarels * accomodate longs..... 98*25202Skarels */ 99*25202Skarels 100*25202Skarels if (advice->portsize > 1) 101*25202Skarels aport = ntohs(lport); 102*25202Skarels else 103*25202Skarels aport = lport; /* a char is a char */ 104*25202Skarels 105*25202Skarels /* 106*25202Skarels * really only a worry for byte size ports 107*25202Skarels */ 108*25202Skarels 109*25202Skarels if (aport > advice->maxport) 110*25202Skarels return(EADDRNOTAVAIL); 111*25202Skarels 112*25202Skarels if (aport <= advice->rootport && u.u_uid != 0) 113*25202Skarels return (EACCES); 114*25202Skarels 115*25202Skarels /* 116*25202Skarels * Check to see if the local address/port is in use. 117*25202Skarels * but, process may use this pair to communicate with 118*25202Skarels * several destinations (each with its own tcp) if he 119*25202Skarels * sets SO_REUSEADDR 120*25202Skarels */ 121*25202Skarels if (advice->bind_used && 122*25202Skarels (*(advice->bind_used))(inp, /* current binding */ 123*25202Skarels lport, /* desired port */ 124*25202Skarels sin->sin_addr.s_addr, /* desired address */ 125*25202Skarels so->so_options & SO_REUSEADDR)) 126*25202Skarels { 127*25202Skarels return (EADDRINUSE); 128*25202Skarels } 129*25202Skarels } 130*25202Skarels inp->inp_laddr = sin->sin_addr; 131*25202Skarels 132*25202Skarels noname : 133*25202Skarels /* any ports for random allocation by non-root users? */ 134*25202Skarels if ((advice->maxport <= advice->resvport) && (u.u_uid)) 135*25202Skarels return(EADDRNOTAVAIL); 136*25202Skarels 137*25202Skarels if (lport == 0) 138*25202Skarels { 139*25202Skarels /* 140*25202Skarels * Allow for reserved ports for non-super users 141*25202Skarels * so that don't interfere with some project's software. 142*25202Skarels */ 143*25202Skarels u_short possible = advice->nowport; 144*25202Skarels 145*25202Skarels do 146*25202Skarels { 147*25202Skarels if (advice->portsize > 1) 148*25202Skarels lport = htons(possible); 149*25202Skarels else 150*25202Skarels lport = possible; 151*25202Skarels 152*25202Skarels /* 153*25202Skarels * catch roll over..... 154*25202Skarels */ 155*25202Skarels 156*25202Skarels if (possible >= advice->maxport) 157*25202Skarels possible = advice->resvport + 1; 158*25202Skarels else 159*25202Skarels possible++; 160*25202Skarels 161*25202Skarels /* 162*25202Skarels * no free ports??? RDP/HMP problem 163*25202Skarels */ 164*25202Skarels 165*25202Skarels if (possible == advice->nowport) 166*25202Skarels return(EADDRNOTAVAIL); 167*25202Skarels 168*25202Skarels } 169*25202Skarels while (advice->bind_used && 170*25202Skarels (*(advice->bind_used))(inp, lport, inp->inp_laddr.s_addr, 0)); 171*25202Skarels 172*25202Skarels advice->nowport = possible; 173*25202Skarels } 174*25202Skarels inp->inp_lport = lport; 175*25202Skarels return (0); 176*25202Skarels } 177*25202Skarels 178*25202Skarels /* 179*25202Skarels * Connect from a socket to a specified address. 180*25202Skarels * Both address and port must be specified in argument sin. 181*25202Skarels * If don't have a local address for this socket yet, 182*25202Skarels * then pick one. 183*25202Skarels */ 184*25202Skarels in_pcbconnect(inp, nam, conn_used) 185*25202Skarels struct inpcb *inp; 186*25202Skarels struct mbuf *nam; 187*25202Skarels char *(*conn_used)(); 188*25202Skarels { 189*25202Skarels register struct ifnet *ifp = NULL; 190*25202Skarels register struct in_ifaddr *ia = NULL; 191*25202Skarels register struct sockaddr_in *ifaddr; 192*25202Skarels register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 193*25202Skarels register struct rtentry *rt; 194*25202Skarels struct sockaddr_in *inpsin; 195*25202Skarels 196*25202Skarels if (nam->m_len != sizeof (*sin)) 197*25202Skarels return (EINVAL); 198*25202Skarels if (sin->sin_family != AF_INET) 199*25202Skarels return (EAFNOSUPPORT); 200*25202Skarels if (sin->sin_addr.s_addr == INADDR_ANY || sin->sin_port == 0) 201*25202Skarels return (EADDRNOTAVAIL); 202*25202Skarels 203*25202Skarels /* 204*25202Skarels * Find route for connection. For a tcp connecting to a server, 205*25202Skarels * this route will be used for the duration of the connection 206*25202Skarels * (unless redirected...). For a UDP doing a connect, this route 207*25202Skarels * will also be used for the duration. For a UDP unconnected send, 208*25202Skarels * this route will be used for the current packet. 209*25202Skarels * 210*25202Skarels * rtalloc cannot handle routing with both sides already bound 211*25202Skarels */ 212*25202Skarels rt = (struct rtentry *) NULL; 213*25202Skarels 214*25202Skarels /* 215*25202Skarels * NOTE: programmers often forget to zero sin_zero[0-1]. 216*25202Skarels * rtalloc does not want to know the port number for routes to hosts. 217*25202Skarels */ 218*25202Skarels inpsin = (struct sockaddr_in *) &inp->inp_route.ro_dst; 219*25202Skarels bcopy((caddr_t)sin, (caddr_t)inpsin, sizeof (*sin)); 220*25202Skarels inpsin->sin_port = 0; 221*25202Skarels 222*25202Skarels if (inp->inp_laddr.s_addr == INADDR_ANY) 223*25202Skarels { 224*25202Skarels rtalloc(&inp->inp_route); 225*25202Skarels if (rt = inp->inp_route.ro_rt) 226*25202Skarels ifp = rt->rt_ifp; 227*25202Skarels } 228*25202Skarels else 229*25202Skarels { 230*25202Skarels if (rt = ip_route(&inp->inp_laddr, &sin->sin_addr)) 231*25202Skarels { 232*25202Skarels inp->inp_route.ro_rt = rt; 233*25202Skarels ifp = rt->rt_ifp; 234*25202Skarels } 235*25202Skarels } 236*25202Skarels 237*25202Skarels if (ifp == NULL) 238*25202Skarels return (ENETUNREACH); 239*25202Skarels 240*25202Skarels /* 241*25202Skarels * find Internet address structure for this interface. 242*25202Skarels */ 243*25202Skarels ia = in_iafromif(ifp); 244*25202Skarels 245*25202Skarels if (ia == NULL) 246*25202Skarels /* ??? */ 247*25202Skarels return (ENETUNREACH); 248*25202Skarels 249*25202Skarels ifaddr = (struct sockaddr_in *) &ia->ia_addr; 250*25202Skarels 251*25202Skarels #ifdef bsd42 252*25202Skarels /* 253*25202Skarels * 8.7.0.2 (on IMP net) can send to 128.11.0.0 (on Ethernet), but 254*25202Skarels * not to 8.0.0.0 255*25202Skarels */ 256*25202Skarels if (in_broadcast(sin->sin_addr) && 257*25202Skarels iptonet(sin->sin_addr) == iptonet(ifaddr->sin_addr) && 258*25202Skarels !(ifp->if_flags & IFF_BROADCAST) ) 259*25202Skarels { 260*25202Skarels if (rt) 261*25202Skarels { 262*25202Skarels rtfree(rt); 263*25202Skarels inp->inp_route.ro_rt = NULL; 264*25202Skarels } 265*25202Skarels return (EADDRNOTAVAIL); 266*25202Skarels } 267*25202Skarels #endif 268*25202Skarels 269*25202Skarels if ((*conn_used)(inp, 270*25202Skarels inp->inp_lport, 271*25202Skarels (inp->inp_laddr.s_addr ? inp->inp_laddr.s_addr : ifaddr->sin_addr.s_addr), 272*25202Skarels sin->sin_port, 273*25202Skarels sin->sin_addr.s_addr) != (char *)NULL) 274*25202Skarels { 275*25202Skarels 276*25202Skarels if (rt) 277*25202Skarels { 278*25202Skarels rtfree(rt); 279*25202Skarels inp->inp_route.ro_rt = NULL; 280*25202Skarels } 281*25202Skarels return (EADDRINUSE); 282*25202Skarels } 283*25202Skarels 284*25202Skarels if (inp->inp_laddr.s_addr == INADDR_ANY) 285*25202Skarels inp->inp_laddr = ifaddr->sin_addr; 286*25202Skarels inp->inp_faddr = sin->sin_addr; 287*25202Skarels inp->inp_fport = sin->sin_port; 288*25202Skarels return (0); 289*25202Skarels } 290*25202Skarels 291*25202Skarels in_pcbdisconnect(inp, pcb_free_func) 292*25202Skarels struct inpcb *inp; 293*25202Skarels int (*pcb_free_func)(); 294*25202Skarels { 295*25202Skarels inp->inp_faddr.s_addr = INADDR_ANY; 296*25202Skarels inp->inp_fport = 0; 297*25202Skarels /* 298*25202Skarels * may attach a route to an inpcb several times. For example, 299*25202Skarels * when UDP does unconnected, but bound, sends. 300*25202Skarels */ 301*25202Skarels if (inp->inp_route.ro_rt) 302*25202Skarels { 303*25202Skarels rtfree(inp->inp_route.ro_rt); 304*25202Skarels inp->inp_route.ro_rt = NULL; 305*25202Skarels } 306*25202Skarels 307*25202Skarels if (inp->inp_socket->so_state & SS_NOFDREF) 308*25202Skarels in_pcbdetach(inp, pcb_free_func); 309*25202Skarels } 310*25202Skarels 311*25202Skarels /* 312*25202Skarels * Don't need to splnet while altering lists, since called from places 313*25202Skarels * where that has already been done. 314*25202Skarels */ 315*25202Skarels in_pcbdetach(inp, pcb_free_func) 316*25202Skarels register struct inpcb *inp; 317*25202Skarels int (*pcb_free_func)(); 318*25202Skarels { 319*25202Skarels register struct socket *so; 320*25202Skarels 321*25202Skarels if (so = inp->inp_socket) 322*25202Skarels { 323*25202Skarels so->so_pcb = (caddr_t) NULL; 324*25202Skarels /* inp->inp_socket = (struct socket *) NULL; */ 325*25202Skarels soisdisconnected(so); 326*25202Skarels sofree(so); 327*25202Skarels } 328*25202Skarels else 329*25202Skarels panic("in_pcbdetach"); 330*25202Skarels 331*25202Skarels if (inp->inp_route.ro_rt) 332*25202Skarels rtfree(inp->inp_route.ro_rt); 333*25202Skarels 334*25202Skarels if (inp->inp_ppcb) 335*25202Skarels (*pcb_free_func)(inp); /* free per-protocol block */ 336*25202Skarels 337*25202Skarels remque(inp); 338*25202Skarels 339*25202Skarels (void) m_free(dtom(inp)); 340*25202Skarels } 341*25202Skarels 342*25202Skarels in_setsockaddr(inp, nam) 343*25202Skarels register struct inpcb *inp; 344*25202Skarels struct mbuf *nam; 345*25202Skarels { 346*25202Skarels register struct sockaddr_in *sin; 347*25202Skarels 348*25202Skarels nam->m_len = sizeof (*sin); 349*25202Skarels sin = mtod(nam, struct sockaddr_in *); 350*25202Skarels bzero((caddr_t)sin, sizeof (*sin)); 351*25202Skarels sin->sin_family = AF_INET; 352*25202Skarels sin->sin_port = inp->inp_lport; 353*25202Skarels sin->sin_addr = inp->inp_laddr; 354*25202Skarels } 355*25202Skarels 356*25202Skarels in_setpeeraddr(inp, nam) 357*25202Skarels register struct inpcb *inp; 358*25202Skarels struct mbuf *nam; 359*25202Skarels { 360*25202Skarels register struct sockaddr_in *sin; 361*25202Skarels 362*25202Skarels nam->m_len = sizeof (*sin); 363*25202Skarels sin = mtod(nam, struct sockaddr_in *); 364*25202Skarels bzero((caddr_t)sin, sizeof (*sin)); 365*25202Skarels sin->sin_family = AF_INET; 366*25202Skarels sin->sin_port = inp->inp_fport; 367*25202Skarels sin->sin_addr = inp->inp_faddr; 368*25202Skarels } 369*25202Skarels 370*25202Skarels /* 371*25202Skarels * somewhat different from the one in 4.2 and (I think) substantially 372*25202Skarels * easier to read, though a bit slower. 373*25202Skarels * 374*25202Skarels * fport == 0 if don't want/need match on remote port # (HMP and UDP) 375*25202Skarels */ 376*25202Skarels struct inpcb * 377*25202Skarels in_pcblookup(head,faddr,fport,laddr,lport,wild) 378*25202Skarels struct inpcb *head; 379*25202Skarels u_long faddr, laddr; 380*25202Skarels u_short fport, lport; 381*25202Skarels int wild; 382*25202Skarels { 383*25202Skarels register struct inpcb *inp; 384*25202Skarels 385*25202Skarels /* try exact match */ 386*25202Skarels for(inp = head->inp_next; inp != head; inp = inp->inp_next) 387*25202Skarels { 388*25202Skarels /* ports check */ 389*25202Skarels if (inp->inp_lport != lport) 390*25202Skarels continue; 391*25202Skarels 392*25202Skarels if (fport && (inp->inp_fport != fport)) 393*25202Skarels continue; 394*25202Skarels 395*25202Skarels if ((inp->inp_faddr.s_addr != faddr) || (inp->inp_laddr.s_addr != laddr)) 396*25202Skarels continue; 397*25202Skarels 398*25202Skarels /* keep it! */ 399*25202Skarels return(inp); 400*25202Skarels } 401*25202Skarels 402*25202Skarels /* try wildcard ? */ 403*25202Skarels if (wild) 404*25202Skarels { 405*25202Skarels for(inp = head->inp_next; inp != head; inp = inp->inp_next) 406*25202Skarels { 407*25202Skarels /* ports again */ 408*25202Skarels if (inp->inp_lport != lport) 409*25202Skarels continue; 410*25202Skarels 411*25202Skarels if (fport && (inp->inp_fport != fport) && inp->inp_fport) 412*25202Skarels continue; 413*25202Skarels 414*25202Skarels if ((inp->inp_faddr.s_addr) && (inp->inp_faddr.s_addr != faddr)) 415*25202Skarels continue; 416*25202Skarels 417*25202Skarels if ((inp->inp_laddr.s_addr) && (inp->inp_laddr.s_addr != laddr)) 418*25202Skarels continue; 419*25202Skarels 420*25202Skarels return(inp); 421*25202Skarels } 422*25202Skarels } 423*25202Skarels 424*25202Skarels return((struct inpcb *) NULL); 425*25202Skarels } 426*25202Skarels 427*25202Skarels 428*25202Skarels /* 429*25202Skarels * This only advises process and does not internally close socket, 430*25202Skarels * not so much because the user can do much but close when he gets a 431*25202Skarels * HOSTDEAD/HOSTUNREACH indication, but because it is possible that 432*25202Skarels * the destination host has saved connection state information. (His IMP 433*25202Skarels * interface went down for PM, but the machine stayed up...) 434*25202Skarels * 435*25202Skarels * Also, this makes addition of new protocols easy, since we don't need to 436*25202Skarels * know the name and calling sequence of their close/abort routine. 437*25202Skarels * 438*25202Skarels * We do not close child sockets of listen(2)ers for connection oriented 439*25202Skarels * protocols. We let the protocol do that by timing out connection 440*25202Skarels * establishment. 441*25202Skarels */ 442*25202Skarels inpcb_notify(head, laddr, faddr, error) 443*25202Skarels register struct inpcb *head; 444*25202Skarels register u_long laddr; 445*25202Skarels register u_long faddr; 446*25202Skarels { 447*25202Skarels register struct inpcb *inp; 448*25202Skarels 449*25202Skarels for(inp = head->inp_next; inp != head; inp = inp->inp_next) 450*25202Skarels if (((inp->inp_faddr.s_addr == faddr) || (faddr == 0)) && 451*25202Skarels ((inp->inp_laddr.s_addr == laddr) || (laddr == 0))) 452*25202Skarels advise_user(inp->inp_socket, error); 453*25202Skarels } 454*25202Skarels 455*25202Skarels advise_user(so, error) 456*25202Skarels struct socket *so; 457*25202Skarels int error; 458*25202Skarels { 459*25202Skarels if (so == 0) 460*25202Skarels return; 461*25202Skarels 462*25202Skarels so->so_error = error; 463*25202Skarels 464*25202Skarels wakeup((caddr_t) &so->so_timeo); /* in connect(2) */ 465*25202Skarels sowwakeup(so); 466*25202Skarels sorwakeup(so); 467*25202Skarels } 468