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