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