1*8925Sroot /* uipc_usrreq.c 1.1 82/10/28 */ 2*8925Sroot 3*8925Sroot #include "../h/param.h" 4*8925Sroot #include "../h/dir.h" 5*8925Sroot #include "../h/user.h" 6*8925Sroot #include "../h/mbuf.h" 7*8925Sroot #include "../h/protosw.h" 8*8925Sroot #include "../h/socket.h" 9*8925Sroot #include "../h/socketvar.h" 10*8925Sroot #include "../h/unpcb.h" 11*8925Sroot #include "../h/un.h" 12*8925Sroot #include "../h/inode.h" 13*8925Sroot 14*8925Sroot /* 15*8925Sroot * Unix communications domain. 16*8925Sroot */ 17*8925Sroot 18*8925Sroot /*ARGSUSED*/ 19*8925Sroot uipc_usrreq(so, req, m, addr) 20*8925Sroot struct socket *so; 21*8925Sroot int req; 22*8925Sroot struct mbuf *m; 23*8925Sroot caddr_t addr; 24*8925Sroot { 25*8925Sroot struct unpcb *unp = sotounpcb(so); 26*8925Sroot register struct socket *so2; 27*8925Sroot int error = 0; 28*8925Sroot 29*8925Sroot if (unp == 0 && req != PRU_ATTACH) 30*8925Sroot return (EINVAL); /* XXX */ 31*8925Sroot switch (req) { 32*8925Sroot 33*8925Sroot case PRU_ATTACH: 34*8925Sroot if (unp) { 35*8925Sroot error = EINVAL; 36*8925Sroot break; 37*8925Sroot } 38*8925Sroot error = unp_attach(so, (struct sockaddr *)addr); 39*8925Sroot break; 40*8925Sroot 41*8925Sroot case PRU_DETACH: 42*8925Sroot unp_detach(unp); 43*8925Sroot break; 44*8925Sroot 45*8925Sroot case PRU_CONNECT: 46*8925Sroot error = unp_connect(so, (struct sockaddr_un *)addr); 47*8925Sroot break; 48*8925Sroot 49*8925Sroot case PRU_DISCONNECT: 50*8925Sroot unp_disconnect(unp); 51*8925Sroot break; 52*8925Sroot 53*8925Sroot /* BEGIN QUESTIONABLE */ 54*8925Sroot case PRU_ACCEPT: { 55*8925Sroot struct sockaddr_un *soun = (struct sockaddr_un *)addr; 56*8925Sroot 57*8925Sroot if (soun) { 58*8925Sroot bzero((caddr_t)soun, sizeof (*soun)); 59*8925Sroot soun->sun_family = AF_UNIX; 60*8925Sroot /* XXX */ 61*8925Sroot } 62*8925Sroot } 63*8925Sroot break; 64*8925Sroot 65*8925Sroot case PRU_SHUTDOWN: 66*8925Sroot socantsendmore(so); 67*8925Sroot unp_usrclosed(unp); 68*8925Sroot break; 69*8925Sroot /* END QUESTIONABLE */ 70*8925Sroot 71*8925Sroot case PRU_RCVD: 72*8925Sroot switch (so->so_type) { 73*8925Sroot 74*8925Sroot case SOCK_DGRAM: 75*8925Sroot panic("uipc 1"); 76*8925Sroot 77*8925Sroot case SOCK_STREAM: { 78*8925Sroot #define rcv (&so->so_rcv) 79*8925Sroot #define snd (&so2->so_snd) 80*8925Sroot if (unp->unp_conn == 0) 81*8925Sroot break; 82*8925Sroot so2 = unp->unp_conn->unp_socket; 83*8925Sroot /* 84*8925Sroot * Transfer resources back to send port 85*8925Sroot * and wakeup any waiting to write. 86*8925Sroot */ 87*8925Sroot snd->sb_mbmax += rcv->sb_mbmax - rcv->sb_mbcnt; 88*8925Sroot rcv->sb_mbmax = rcv->sb_mbcnt; 89*8925Sroot snd->sb_hiwat += rcv->sb_hiwat - rcv->sb_cc; 90*8925Sroot rcv->sb_hiwat = rcv->sb_cc; 91*8925Sroot sbwakeup(snd); 92*8925Sroot #undef snd 93*8925Sroot #undef rcv 94*8925Sroot } 95*8925Sroot break; 96*8925Sroot 97*8925Sroot default: 98*8925Sroot panic("uipc 2"); 99*8925Sroot } 100*8925Sroot break; 101*8925Sroot 102*8925Sroot case PRU_SEND: 103*8925Sroot switch (so->so_type) { 104*8925Sroot 105*8925Sroot case SOCK_DGRAM: 106*8925Sroot if (addr) { 107*8925Sroot if (unp->unp_conn) { 108*8925Sroot error = EISCONN; 109*8925Sroot break; 110*8925Sroot } 111*8925Sroot error = unp_connect(so, addr); 112*8925Sroot if (error) 113*8925Sroot break; 114*8925Sroot } else { 115*8925Sroot if (unp->unp_conn == 0) { 116*8925Sroot error = ENOTCONN; 117*8925Sroot break; 118*8925Sroot } 119*8925Sroot } 120*8925Sroot so2 = unp->unp_conn->unp_socket; 121*8925Sroot if (sbspace(&so2->so_rcv) > 0) /* XXX */ 122*8925Sroot sbappendaddr(so2, m, addr); /* XXX */ 123*8925Sroot if (addr) 124*8925Sroot unp_disconnect(so); 125*8925Sroot break; 126*8925Sroot 127*8925Sroot case SOCK_STREAM: 128*8925Sroot #define rcv (&so2->so_rcv) 129*8925Sroot #define snd (&so->so_snd) 130*8925Sroot if (unp->unp_conn == 0) 131*8925Sroot panic("uipc 3"); 132*8925Sroot so2 = unp->unp_conn->unp_socket; 133*8925Sroot /* 134*8925Sroot * Send to paired receive port, and then 135*8925Sroot * give it enough resources to hold what it already has. 136*8925Sroot * Wake up readers. 137*8925Sroot */ 138*8925Sroot sbappend(rcv, m); 139*8925Sroot snd->sb_mbmax -= rcv->sb_mbcnt - rcv->sb_mbmax; 140*8925Sroot rcv->sb_mbmax = rcv->sb_mbcnt; 141*8925Sroot snd->sb_hiwat -= rcv->sb_cc - rcv->sb_hiwat; 142*8925Sroot rcv->sb_hiwat = rcv->sb_cc; 143*8925Sroot sbwakeup(rcv); 144*8925Sroot #undef snd 145*8925Sroot #undef rcv 146*8925Sroot break; 147*8925Sroot 148*8925Sroot default: 149*8925Sroot panic("uipc 4"); 150*8925Sroot } 151*8925Sroot break; 152*8925Sroot 153*8925Sroot case PRU_ABORT: 154*8925Sroot unp_drop(unp, ECONNABORTED); 155*8925Sroot break; 156*8925Sroot 157*8925Sroot /* SOME AS YET UNIMPLEMENTED HOOKS */ 158*8925Sroot case PRU_CONTROL: 159*8925Sroot error = EOPNOTSUPP; 160*8925Sroot break; 161*8925Sroot 162*8925Sroot case PRU_SENSE: 163*8925Sroot error = EOPNOTSUPP; 164*8925Sroot break; 165*8925Sroot /* END UNIMPLEMENTED HOOKS */ 166*8925Sroot 167*8925Sroot case PRU_RCVOOB: 168*8925Sroot break; 169*8925Sroot 170*8925Sroot case PRU_SENDOOB: 171*8925Sroot break; 172*8925Sroot 173*8925Sroot case PRU_SOCKADDR: 174*8925Sroot break; 175*8925Sroot 176*8925Sroot case PRU_SLOWTIMO: 177*8925Sroot break; 178*8925Sroot 179*8925Sroot default: 180*8925Sroot panic("piusrreq"); 181*8925Sroot } 182*8925Sroot return (0); 183*8925Sroot } 184*8925Sroot 185*8925Sroot int unp_sendspace = 1024*2; 186*8925Sroot int unp_recvspace = 1024*2; 187*8925Sroot 188*8925Sroot unp_attach(so, soun) 189*8925Sroot struct socket *so; 190*8925Sroot struct sockaddr_un *soun; 191*8925Sroot { 192*8925Sroot register struct unpcb *unp; 193*8925Sroot struct mbuf *m; 194*8925Sroot int error; 195*8925Sroot 196*8925Sroot error = soreserve(so, unp_sendspace, unp_recvspace); 197*8925Sroot if (error) 198*8925Sroot goto bad; 199*8925Sroot m = m_getclr(M_DONTWAIT); 200*8925Sroot if (m == 0) { 201*8925Sroot error = ENOBUFS; 202*8925Sroot goto bad; 203*8925Sroot } 204*8925Sroot unp = mtod(m, struct unpcb *); 205*8925Sroot so->so_pcb = (caddr_t)unp; 206*8925Sroot unp->unp_socket = so; 207*8925Sroot if (soun) { 208*8925Sroot error = unp_bind(unp, soun); 209*8925Sroot if (error) { 210*8925Sroot unp_detach(unp); 211*8925Sroot goto bad; 212*8925Sroot } 213*8925Sroot } 214*8925Sroot return (0); 215*8925Sroot bad: 216*8925Sroot return (error); 217*8925Sroot } 218*8925Sroot 219*8925Sroot unp_disconnect(unp) 220*8925Sroot struct unpcb *unp; 221*8925Sroot { 222*8925Sroot register struct unpcb *unp2 = unp->unp_conn; 223*8925Sroot 224*8925Sroot if (unp2 == 0) 225*8925Sroot return; 226*8925Sroot unp->unp_conn = 0; 227*8925Sroot soisdisconnected(unp->unp_socket); 228*8925Sroot switch (unp->unp_socket->so_type) { 229*8925Sroot 230*8925Sroot case SOCK_DGRAM: 231*8925Sroot if (unp2->unp_refs == unp) 232*8925Sroot unp2->unp_refs = unp->unp_nextref; 233*8925Sroot else { 234*8925Sroot unp2 = unp2->unp_refs; 235*8925Sroot for (;;) { 236*8925Sroot if (unp2 == 0) 237*8925Sroot panic("unp_disconnect"); 238*8925Sroot if (unp2->unp_nextref == unp) 239*8925Sroot break; 240*8925Sroot unp2 = unp2->unp_nextref; 241*8925Sroot } 242*8925Sroot unp2->unp_nextref = unp->unp_nextref; 243*8925Sroot } 244*8925Sroot unp->unp_nextref = 0; 245*8925Sroot break; 246*8925Sroot 247*8925Sroot case SOCK_STREAM: 248*8925Sroot unp2->unp_conn = 0; 249*8925Sroot soisdisconnected(unp2->unp_socket); 250*8925Sroot unp_drop(unp2, ECONNRESET); 251*8925Sroot break; 252*8925Sroot } 253*8925Sroot } 254*8925Sroot 255*8925Sroot unp_abort(unp) 256*8925Sroot struct unpcb *unp; 257*8925Sroot { 258*8925Sroot 259*8925Sroot unp_detach(unp); 260*8925Sroot } 261*8925Sroot 262*8925Sroot unp_detach(unp) 263*8925Sroot struct unpcb *unp; 264*8925Sroot { 265*8925Sroot 266*8925Sroot if (unp->unp_inode) { 267*8925Sroot irele(unp->unp_inode); 268*8925Sroot unp->unp_inode = 0; 269*8925Sroot } 270*8925Sroot if (unp->unp_conn) 271*8925Sroot unp_disconnect(unp); 272*8925Sroot while (unp->unp_refs) 273*8925Sroot unp_drop(unp->unp_refs, ECONNRESET); 274*8925Sroot soisdisconnected(unp->unp_socket); 275*8925Sroot unp->unp_socket->so_pcb = 0; 276*8925Sroot m_free(dtom(unp)); 277*8925Sroot } 278*8925Sroot 279*8925Sroot unp_usrclosed(unp) 280*8925Sroot struct unpcb *unp; 281*8925Sroot { 282*8925Sroot register struct socket *so = unp->unp_socket; 283*8925Sroot 284*8925Sroot #ifdef sometimes /* ??? */ 285*8925Sroot soisdisconnected(unp->unp_socket); 286*8925Sroot #endif 287*8925Sroot } 288*8925Sroot 289*8925Sroot unp_drop(unp, errno) 290*8925Sroot struct unpcb *unp; 291*8925Sroot int errno; 292*8925Sroot { 293*8925Sroot 294*8925Sroot unp->unp_socket->so_error = errno; 295*8925Sroot unp_disconnect(unp); 296*8925Sroot } 297*8925Sroot 298*8925Sroot unp_drain() 299*8925Sroot { 300*8925Sroot 301*8925Sroot } 302*8925Sroot 303*8925Sroot unp_bind(unp, soun) 304*8925Sroot struct unpcb *unp; 305*8925Sroot struct sockaddr_un *soun; 306*8925Sroot { 307*8925Sroot register struct inode *ip; 308*8925Sroot int error; 309*8925Sroot extern schar(); 310*8925Sroot 311*8925Sroot u.u_dirp = soun->sun_path; 312*8925Sroot soun->sun_path[sizeof(soun->sun_path)-1] = 0; 313*8925Sroot ip = namei(schar, 1, 1); 314*8925Sroot if (ip) { 315*8925Sroot iput(ip); 316*8925Sroot return (EEXIST); 317*8925Sroot } 318*8925Sroot ip = maknode(IFSOCK | 0777); 319*8925Sroot if (ip == NULL) { 320*8925Sroot error = u.u_error; /* XXX */ 321*8925Sroot u.u_error = 0; /* XXX */ 322*8925Sroot return (error); 323*8925Sroot } 324*8925Sroot ip->i_socket = unp->unp_socket; 325*8925Sroot unp->unp_inode = ip; 326*8925Sroot iunlock(ip); /* but keep reference */ 327*8925Sroot return (0); 328*8925Sroot } 329*8925Sroot 330*8925Sroot unp_connect(so, soun) 331*8925Sroot struct socket *so; 332*8925Sroot struct sockaddr_un *soun; 333*8925Sroot { 334*8925Sroot struct inode *ip; 335*8925Sroot int error; 336*8925Sroot 337*8925Sroot u.u_dirp = soun->sun_path; 338*8925Sroot soun->sun_path[sizeof(soun->sun_path)-1] = 0; 339*8925Sroot ip = namei(schar, 0, 1); 340*8925Sroot if (ip == 0) { 341*8925Sroot error = u.u_error; 342*8925Sroot u.u_error = 0; 343*8925Sroot return (ENOENT); 344*8925Sroot } 345*8925Sroot error = unp_connectip(so, ip); 346*8925Sroot return (error); 347*8925Sroot } 348*8925Sroot 349*8925Sroot unp_connectip(so, ip) 350*8925Sroot struct socket *so; 351*8925Sroot struct inode *ip; 352*8925Sroot { 353*8925Sroot struct unpcb *unp = sotounpcb(so); 354*8925Sroot struct socket *so2, *so3; 355*8925Sroot int error; 356*8925Sroot struct unpcb *unp2; 357*8925Sroot 358*8925Sroot if ((ip->i_mode&IFMT) != IFSOCK) { 359*8925Sroot error = ENOTSOCK; 360*8925Sroot goto bad; 361*8925Sroot } 362*8925Sroot so2 = ip->i_socket; 363*8925Sroot if (so2 == 0) { 364*8925Sroot error = ECONNREFUSED; 365*8925Sroot goto bad; 366*8925Sroot } 367*8925Sroot if (so2->so_type != so->so_type) { 368*8925Sroot error = EPROTOTYPE; 369*8925Sroot goto bad; 370*8925Sroot } 371*8925Sroot switch (so->so_type) { 372*8925Sroot 373*8925Sroot case SOCK_DGRAM: 374*8925Sroot unp->unp_conn = sotounpcb(so2); 375*8925Sroot unp2 = sotounpcb(so2); 376*8925Sroot unp->unp_nextref = unp2->unp_refs; 377*8925Sroot unp2->unp_refs = unp; 378*8925Sroot break; 379*8925Sroot 380*8925Sroot case SOCK_STREAM: 381*8925Sroot if ((so2->so_options&SO_ACCEPTCONN) == 0 || 382*8925Sroot (so3 = sonewconn(so2)) == 0) { 383*8925Sroot error = ECONNREFUSED; 384*8925Sroot goto bad; 385*8925Sroot } 386*8925Sroot unp->unp_conn = sotounpcb(so3); 387*8925Sroot break; 388*8925Sroot 389*8925Sroot default: 390*8925Sroot panic("uipc connip"); 391*8925Sroot } 392*8925Sroot soisconnected(unp->unp_conn->unp_socket); 393*8925Sroot soisconnected(so); 394*8925Sroot iput(ip); 395*8925Sroot return (0); 396*8925Sroot bad: 397*8925Sroot iput(ip); 398*8925Sroot return (error); 399*8925Sroot } 400