1 /* uipc_usrreq.c 1.7 83/01/13 */ 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 (0); 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 ip = maknode(IFSOCK | 0777); 247 if (ip == NULL) { 248 error = u.u_error; /* XXX */ 249 u.u_error = 0; /* XXX */ 250 return (error); 251 } 252 ip->i_socket = unp->unp_socket; 253 unp->unp_inode = ip; 254 iunlock(ip); /* but keep reference */ 255 return (0); 256 } 257 258 unp_connect(so, nam) 259 struct socket *so; 260 struct mbuf *nam; 261 { 262 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 263 struct unpcb *unp = sotounpcb(so); 264 register struct inode *ip; 265 int error; 266 struct socket *so2; 267 struct unpcb *unp2; 268 269 u.u_dirp = soun->sun_path; 270 soun->sun_path[sizeof(soun->sun_path)-1] = 0; 271 ip = namei(schar, LOOKUP, 1); 272 if (ip == 0) { 273 error = u.u_error; 274 u.u_error = 0; 275 return (error); /* XXX */ 276 } 277 if ((ip->i_mode&IFMT) != IFSOCK) { 278 error = ENOTSOCK; 279 goto bad; 280 } 281 so2 = ip->i_socket; 282 if (so2 == 0) { 283 error = ECONNREFUSED; 284 goto bad; 285 } 286 if (so2->so_type != so->so_type) { 287 error = EPROTOTYPE; 288 goto bad; 289 } 290 switch (so->so_type) { 291 292 case SOCK_DGRAM: 293 unp->unp_conn = sotounpcb(so2); 294 unp2 = sotounpcb(so2); 295 unp->unp_nextref = unp2->unp_refs; 296 unp2->unp_refs = unp; 297 break; 298 299 case SOCK_STREAM: 300 if ((so2->so_options&SO_ACCEPTCONN) == 0 || 301 (so2 = sonewconn(so2)) == 0) { 302 error = ECONNREFUSED; 303 goto bad; 304 } 305 unp2 = sotounpcb(so2); 306 unp->unp_conn = unp2; 307 unp2->unp_conn = unp; 308 unp2->unp_remaddr = m_copy(nam, 0, (int)M_COPYALL); 309 break; 310 311 default: 312 panic("uipc connip"); 313 } 314 soisconnected(so2); 315 soisconnected(so); 316 iput(ip); 317 return (0); 318 bad: 319 iput(ip); 320 return (error); 321 } 322 323 unp_disconnect(unp) 324 struct unpcb *unp; 325 { 326 register struct unpcb *unp2 = unp->unp_conn; 327 328 if (unp2 == 0) 329 return; 330 unp->unp_conn = 0; 331 soisdisconnected(unp->unp_socket); 332 switch (unp->unp_socket->so_type) { 333 334 case SOCK_DGRAM: 335 if (unp2->unp_refs == unp) 336 unp2->unp_refs = unp->unp_nextref; 337 else { 338 unp2 = unp2->unp_refs; 339 for (;;) { 340 if (unp2 == 0) 341 panic("unp_disconnect"); 342 if (unp2->unp_nextref == unp) 343 break; 344 unp2 = unp2->unp_nextref; 345 } 346 unp2->unp_nextref = unp->unp_nextref; 347 } 348 unp->unp_nextref = 0; 349 break; 350 351 case SOCK_STREAM: 352 unp2->unp_conn = 0; 353 soisdisconnected(unp2->unp_socket); 354 break; 355 } 356 } 357 358 unp_abort(unp) 359 struct unpcb *unp; 360 { 361 362 unp_detach(unp); 363 } 364 365 /*ARGSUSED*/ 366 unp_usrclosed(unp) 367 struct unpcb *unp; 368 { 369 370 } 371 372 unp_drop(unp, errno) 373 struct unpcb *unp; 374 int errno; 375 { 376 377 unp->unp_socket->so_error = errno; 378 unp_disconnect(unp); 379 } 380 381 unp_drain() 382 { 383 384 } 385