1 /* uipc_usrreq.c 1.5 82/12/14 */ 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 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 } 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 goto bad; 204 m = m_getclr(M_DONTWAIT, MT_PCB); 205 if (m == 0) { 206 error = ENOBUFS; 207 goto bad; 208 } 209 unp = mtod(m, struct unpcb *); 210 so->so_pcb = (caddr_t)unp; 211 unp->unp_socket = so; 212 return (0); 213 bad: 214 return (error); 215 } 216 217 unp_detach(unp) 218 register struct unpcb *unp; 219 { 220 221 if (unp->unp_inode) { 222 irele(unp->unp_inode); 223 unp->unp_inode = 0; 224 } 225 if (unp->unp_conn) 226 unp_disconnect(unp); 227 while (unp->unp_refs) 228 unp_drop(unp->unp_refs, ECONNRESET); 229 soisdisconnected(unp->unp_socket); 230 unp->unp_socket->so_pcb = 0; 231 m_freem(unp->unp_remaddr); 232 (void) m_free(dtom(unp)); 233 } 234 235 unp_bind(unp, nam) 236 struct unpcb *unp; 237 struct mbuf *nam; 238 { 239 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 240 register struct inode *ip; 241 extern schar(); 242 int error; 243 244 u.u_dirp = soun->sun_path; 245 soun->sun_path[sizeof(soun->sun_path)-1] = 0; 246 ip = namei(schar, CREATE, 1); 247 if (ip) { 248 iput(ip); 249 return (EEXIST); 250 } 251 ip = maknode(IFSOCK | 0777); 252 if (ip == NULL) { 253 error = u.u_error; /* XXX */ 254 u.u_error = 0; /* XXX */ 255 return (error); 256 } 257 ip->i_socket = unp->unp_socket; 258 unp->unp_inode = ip; 259 iunlock(ip); /* but keep reference */ 260 return (0); 261 } 262 263 unp_connect(so, nam) 264 struct socket *so; 265 struct mbuf *nam; 266 { 267 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 268 struct unpcb *unp = sotounpcb(so); 269 register struct inode *ip; 270 int error; 271 struct socket *so2; 272 struct unpcb *unp2; 273 274 u.u_dirp = soun->sun_path; 275 soun->sun_path[sizeof(soun->sun_path)-1] = 0; 276 ip = namei(schar, LOOKUP, 1); 277 if (ip == 0) { 278 error = u.u_error; 279 u.u_error = 0; 280 return (ENOENT); 281 } 282 if ((ip->i_mode&IFMT) != IFSOCK) { 283 error = ENOTSOCK; 284 goto bad; 285 } 286 so2 = ip->i_socket; 287 if (so2 == 0) { 288 error = ECONNREFUSED; 289 goto bad; 290 } 291 if (so2->so_type != so->so_type) { 292 error = EPROTOTYPE; 293 goto bad; 294 } 295 switch (so->so_type) { 296 297 case SOCK_DGRAM: 298 unp->unp_conn = sotounpcb(so2); 299 unp2 = sotounpcb(so2); 300 unp->unp_nextref = unp2->unp_refs; 301 unp2->unp_refs = unp; 302 break; 303 304 case SOCK_STREAM: 305 if ((so2->so_options&SO_ACCEPTCONN) == 0 || 306 (so2 = sonewconn(so2)) == 0) { 307 error = ECONNREFUSED; 308 goto bad; 309 } 310 unp2 = sotounpcb(so2); 311 unp->unp_conn = unp2; 312 unp2->unp_conn = unp; 313 unp2->unp_remaddr = m_copy(nam, 0, (int)M_COPYALL); 314 break; 315 316 default: 317 panic("uipc connip"); 318 } 319 soisconnected(so2); 320 soisconnected(so); 321 iput(ip); 322 return (0); 323 bad: 324 iput(ip); 325 return (error); 326 } 327 328 unp_disconnect(unp) 329 struct unpcb *unp; 330 { 331 register struct unpcb *unp2 = unp->unp_conn; 332 333 if (unp2 == 0) 334 return; 335 unp->unp_conn = 0; 336 soisdisconnected(unp->unp_socket); 337 switch (unp->unp_socket->so_type) { 338 339 case SOCK_DGRAM: 340 if (unp2->unp_refs == unp) 341 unp2->unp_refs = unp->unp_nextref; 342 else { 343 unp2 = unp2->unp_refs; 344 for (;;) { 345 if (unp2 == 0) 346 panic("unp_disconnect"); 347 if (unp2->unp_nextref == unp) 348 break; 349 unp2 = unp2->unp_nextref; 350 } 351 unp2->unp_nextref = unp->unp_nextref; 352 } 353 unp->unp_nextref = 0; 354 break; 355 356 case SOCK_STREAM: 357 unp2->unp_conn = 0; 358 soisdisconnected(unp2->unp_socket); 359 break; 360 } 361 } 362 363 unp_abort(unp) 364 struct unpcb *unp; 365 { 366 367 unp_detach(unp); 368 } 369 370 /*ARGSUSED*/ 371 unp_usrclosed(unp) 372 struct unpcb *unp; 373 { 374 375 } 376 377 unp_drop(unp, errno) 378 struct unpcb *unp; 379 int errno; 380 { 381 382 unp->unp_socket->so_error = errno; 383 unp_disconnect(unp); 384 } 385 386 unp_drain() 387 { 388 389 } 390