1 /* uipc_syscalls.c 4.39 82/12/28 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/proc.h" 8 #include "../h/file.h" 9 #include "../h/inode.h" 10 #include "../h/buf.h" 11 #include "../h/mbuf.h" 12 #include "../h/protosw.h" 13 #include "../h/socket.h" 14 #include "../h/socketvar.h" 15 #include "../h/descrip.h" 16 #include "../h/uio.h" 17 18 /* 19 * System call interface to the socket abstraction. 20 */ 21 22 socket() 23 { 24 register struct a { 25 int domain; 26 int type; 27 int protocol; 28 struct socketopt *opt; 29 } *uap = (struct a *)u.u_ap; 30 struct socket *so; 31 register struct file *fp; 32 struct socketopt aopt; 33 34 u.u_error = sockopt(&aopt, (caddr_t)uap->opt); 35 if (u.u_error) 36 return; 37 if ((fp = falloc()) == NULL) 38 goto freeopt; 39 fp->f_flag = FREAD|FWRITE; 40 fp->f_type = DTYPE_SOCKET; 41 u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol, &aopt); 42 if (u.u_error) 43 goto bad; 44 fp->f_socket = so; 45 freeopt: 46 if (uap->opt) 47 (void) m_free(dtom(aopt.so_optdata)); 48 return; 49 bad: 50 u.u_ofile[u.u_r.r_val1] = 0; 51 fp->f_count = 0; 52 goto freeopt; 53 } 54 55 bind() 56 { 57 register struct a { 58 int s; 59 caddr_t name; 60 int namelen; 61 struct socketopt *opt; 62 } *uap = (struct a *)u.u_ap; 63 register struct file *fp; 64 struct mbuf *nam; 65 struct socketopt aopt; 66 67 fp = getf(uap->s); 68 if (fp == 0) 69 return; 70 if (fp->f_type != DTYPE_SOCKET) { 71 u.u_error = ENOTSOCK; 72 return; 73 } 74 u.u_error = sockname(&nam, uap->name, uap->namelen); 75 if (u.u_error) 76 return; 77 u.u_error = sockopt(&aopt, (caddr_t)uap->opt); 78 if (u.u_error) { 79 m_freem(nam); 80 goto freeopt; 81 } 82 u.u_error = sobind(fp->f_socket, nam, &aopt); 83 m_freem(nam); 84 freeopt: 85 if (uap->opt) 86 (void) m_free(dtom(aopt.so_optdata)); 87 } 88 89 listen() 90 { 91 register struct a { 92 int s; 93 int backlog; 94 } *uap = (struct a *)u.u_ap; 95 register struct file *fp; 96 97 fp = getf(uap->s); 98 if (fp == 0) 99 return; 100 if (fp->f_type != DTYPE_SOCKET) { 101 u.u_error = ENOTSOCK; 102 return; 103 } 104 u.u_error = solisten(fp->f_socket, uap->backlog); 105 } 106 107 accept() 108 { 109 register struct a { 110 int s; 111 caddr_t name; 112 int *anamelen; 113 struct socketopt *opt; 114 } *uap = (struct a *)u.u_ap; 115 register struct file *fp; 116 struct mbuf *nam; 117 struct socketopt aopt; 118 int namelen; 119 int s; 120 register struct socket *so; 121 122 if (uap->name == 0) 123 goto noname; 124 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 125 sizeof (namelen)); 126 if (u.u_error) 127 return; 128 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { 129 u.u_error = EFAULT; 130 return; 131 } 132 noname: 133 u.u_error = sockopt(&aopt, (caddr_t)uap->opt); 134 if (u.u_error) 135 return; 136 fp = getf(uap->s); 137 if (fp == 0) 138 goto bad; 139 if (fp->f_type != DTYPE_SOCKET) { 140 u.u_error = ENOTSOCK; 141 goto bad; 142 } 143 s = splnet(); 144 so = fp->f_socket; 145 if ((so->so_options & SO_ACCEPTCONN) == 0) { 146 u.u_error = EINVAL; 147 splx(s); 148 goto bad; 149 } 150 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 151 u.u_error = EWOULDBLOCK; 152 splx(s); 153 goto bad; 154 } 155 while (so->so_qlen == 0 && so->so_error == 0) { 156 if (so->so_state & SS_CANTRCVMORE) { 157 so->so_error = ECONNABORTED; 158 break; 159 } 160 sleep((caddr_t)&so->so_timeo, PZERO+1); 161 } 162 if (so->so_error) { 163 u.u_error = so->so_error; 164 splx(s); 165 goto bad; 166 } 167 if ((so->so_options & SO_NEWFDONCONN) == 0) { 168 struct socket *nso = so->so_q; 169 (void) soqremque(nso, 1); 170 u.u_error = soclose(so, 1); 171 fp->f_socket = nso; 172 nso->so_q = 0; 173 so = nso; 174 goto ret; 175 } 176 if (ufalloc() < 0) { 177 splx(s); 178 goto bad; 179 } 180 fp = falloc(); 181 if (fp == 0) { 182 u.u_ofile[u.u_r.r_val1] = 0; 183 splx(s); 184 goto bad; 185 } 186 { struct socket *aso = so->so_q; 187 if (soqremque(aso, 1) == 0) 188 panic("accept"); 189 so = aso; 190 } 191 fp->f_type = DTYPE_SOCKET; 192 fp->f_flag = FREAD|FWRITE; 193 fp->f_socket = so; 194 ret: 195 nam = m_get(M_WAIT, MT_SONAME); 196 (void) soaccept(so, nam, &aopt); 197 if (uap->name) { 198 if (namelen > nam->m_len) 199 namelen = nam->m_len; 200 /* SHOULD COPY OUT A CHAIN HERE */ 201 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, 202 (u_int)namelen); 203 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, 204 sizeof (*uap->anamelen)); 205 } 206 m_freem(nam); 207 splx(s); 208 bad: 209 if (uap->opt) 210 (void) m_free(dtom(aopt.so_optdata)); 211 } 212 213 connect() 214 { 215 register struct a { 216 int s; 217 caddr_t name; 218 int namelen; 219 struct socketopt *opt; 220 } *uap = (struct a *)u.u_ap; 221 register struct file *fp; 222 register struct socket *so; 223 struct mbuf *nam; 224 struct socketopt aopt; 225 int s; 226 227 fp = getf(uap->s); 228 if (fp == 0) 229 return; 230 if (fp->f_type != DTYPE_SOCKET) { 231 u.u_error = ENOTSOCK; 232 return; 233 } 234 so = fp->f_socket; 235 u.u_error = sockname(&nam, uap->name, uap->namelen); 236 if (u.u_error) 237 return; 238 u.u_error = sockopt(&aopt, (caddr_t)uap->opt); 239 if (u.u_error) { 240 m_freem(nam); 241 return; 242 } 243 u.u_error = soconnect(so, nam, &aopt); 244 if (u.u_error) 245 goto bad; 246 s = splnet(); 247 if ((so->so_state & SS_NBIO) && 248 (so->so_state & SS_ISCONNECTING)) { 249 u.u_error = EINPROGRESS; 250 splx(s); 251 goto bad; 252 } 253 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 254 sleep((caddr_t)&so->so_timeo, PZERO+1); 255 u.u_error = so->so_error; 256 so->so_error = 0; 257 splx(s); 258 bad: 259 m_freem(nam); 260 if (uap->opt) 261 (void) m_free(dtom(aopt.so_optdata)); 262 return; 263 } 264 265 socketpair() 266 { 267 268 u.u_error = ENOENT; 269 } 270 271 sendto() 272 { 273 register struct a { 274 int s; 275 caddr_t buf; 276 int len; 277 int flags; 278 caddr_t to; 279 int tolen; 280 } *uap = (struct a *)u.u_ap; 281 register struct file *fp; 282 struct uio auio; 283 struct iovec aiov; 284 struct mbuf *to; 285 286 fp = getf(uap->s); 287 if (fp == 0) 288 return; 289 if (fp->f_type != DTYPE_SOCKET) { 290 u.u_error = ENOTSOCK; 291 return; 292 } 293 auio.uio_iov = &aiov; 294 auio.uio_iovcnt = 1; 295 aiov.iov_base = uap->buf; 296 aiov.iov_len = uap->len; 297 auio.uio_resid = uap->len; 298 auio.uio_segflg = 0; 299 auio.uio_offset = 0; /* XXX */ 300 if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { 301 u.u_error = EFAULT; 302 return; 303 } 304 u.u_error = sockname(&to, uap->to, uap->tolen); 305 if (u.u_error) 306 goto bad; 307 u.u_error = sosend(fp->f_socket, to, &auio, uap->flags); 308 u.u_r.r_val1 = uap->len - auio.uio_resid; 309 bad: 310 m_freem(to); 311 } 312 313 send() 314 { 315 register struct a { 316 int s; 317 caddr_t buf; 318 int len; 319 int flags; 320 } *uap = (struct a *)u.u_ap; 321 register struct file *fp; 322 struct uio auio; 323 struct iovec aiov; 324 325 fp = getf(uap->s); 326 if (fp == 0) 327 return; 328 if (fp->f_type != DTYPE_SOCKET) { 329 u.u_error = ENOTSOCK; 330 return; 331 } 332 auio.uio_iov = &aiov; 333 auio.uio_iovcnt = 1; 334 aiov.iov_base = uap->buf; 335 aiov.iov_len = uap->len; 336 auio.uio_resid = uap->len; 337 auio.uio_segflg = 0; 338 auio.uio_offset = 0; /* XXX */ 339 if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { 340 u.u_error = EFAULT; 341 return; 342 } 343 if (u.u_error) 344 return; 345 u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags); 346 u.u_r.r_val1 = uap->len - auio.uio_resid; 347 } 348 349 recvfrom() 350 { 351 register struct a { 352 int s; 353 caddr_t buf; 354 int len; 355 int flags; 356 caddr_t from; 357 int *fromlenaddr; 358 } *uap = (struct a *)u.u_ap; 359 register struct file *fp; 360 struct uio auio; 361 struct iovec aiov; 362 struct mbuf *from; 363 int fromlen; 364 365 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen, 366 sizeof (fromlen)); 367 if (u.u_error) 368 return; 369 fp = getf(uap->s); 370 if (fp == 0) 371 return; 372 if (fp->f_type != DTYPE_SOCKET) { 373 u.u_error = ENOTSOCK; 374 return; 375 } 376 auio.uio_iov = &aiov; 377 auio.uio_iovcnt = 1; 378 aiov.iov_base = uap->buf; 379 aiov.iov_len = uap->len; 380 auio.uio_resid = uap->len; 381 auio.uio_segflg = 0; 382 auio.uio_offset = 0; /* XXX */ 383 if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { 384 u.u_error = EFAULT; 385 return; 386 } 387 from = 0; 388 u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags); 389 if (u.u_error) 390 goto bad; 391 if (from == 0) 392 fromlen = 0; 393 else { 394 if (fromlen > from->m_len) 395 fromlen = from->m_len; 396 u.u_error = copyout(mtod(from, caddr_t), uap->from, 397 (u_int)fromlen); 398 if (u.u_error) 399 goto bad; 400 } 401 u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr, 402 sizeof (fromlen)); 403 if (u.u_error) 404 goto bad; 405 u.u_r.r_val1 = uap->len - auio.uio_resid; 406 bad: 407 if (from) 408 m_freem(from); 409 return; 410 } 411 412 recv() 413 { 414 register struct a { 415 int s; 416 caddr_t buf; 417 int len; 418 int flags; 419 } *uap = (struct a *)u.u_ap; 420 register struct file *fp; 421 struct uio auio; 422 struct iovec aiov; 423 424 fp = getf(uap->s); 425 if (fp == 0) 426 return; 427 if (fp->f_type != DTYPE_SOCKET) { 428 u.u_error = ENOTSOCK; 429 return; 430 } 431 auio.uio_iov = &aiov; 432 auio.uio_iovcnt = 1; 433 aiov.iov_base = uap->buf; 434 aiov.iov_len = uap->len; 435 auio.uio_resid = uap->len; 436 auio.uio_segflg = 0; 437 auio.uio_offset = 0; /* XXX */ 438 if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { 439 u.u_error = EFAULT; 440 return; 441 } 442 u.u_error = 443 soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags); 444 u.u_r.r_val1 = uap->len - auio.uio_resid; 445 } 446 447 sendmsg() 448 { 449 450 u.u_error = EINVAL; 451 } 452 453 recvmsg() 454 { 455 456 u.u_error = EINVAL; 457 } 458 459 shutdown() 460 { 461 462 u.u_error = EINVAL; 463 } 464 465 pipe() 466 { 467 register struct file *rf, *wf; 468 struct socket *rso, *wso; 469 int r; 470 471 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, 472 (struct socketopt *)0); 473 if (u.u_error) 474 return; 475 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, 476 (struct socketopt *)0); 477 if (u.u_error) 478 goto free; 479 rf = falloc(); 480 if (rf == NULL) 481 goto free2; 482 r = u.u_r.r_val1; 483 rf->f_flag = FREAD; 484 rf->f_type = DTYPE_SOCKET; 485 rf->f_socket = rso; 486 wf = falloc(); 487 if (wf == NULL) 488 goto free3; 489 wf->f_flag = FWRITE; 490 wf->f_type = DTYPE_SOCKET; 491 wf->f_socket = wso; 492 u.u_r.r_val2 = u.u_r.r_val1; 493 u.u_r.r_val1 = r; 494 if (piconnect(wso, rso) == 0) 495 goto free4; 496 return; 497 free4: 498 wf->f_count = 0; 499 u.u_ofile[u.u_r.r_val2] = 0; 500 free3: 501 rf->f_count = 0; 502 u.u_ofile[r] = 0; 503 free2: 504 wso->so_state |= SS_NOFDREF; 505 sofree(wso); 506 free: 507 rso->so_state |= SS_NOFDREF; 508 sofree(rso); 509 } 510 511 /* 512 * Get socket address. 513 */ 514 ssocketaddr() 515 { 516 register struct a { 517 int fdes; 518 struct sockaddr *asa; 519 } *uap = (struct a *)u.u_ap; 520 register struct file *fp; 521 register struct socket *so; 522 struct mbuf *m; 523 524 fp = getf(uap->fdes); 525 if (fp == 0) 526 return; 527 if (fp->f_type != DTYPE_SOCKET) { 528 u.u_error = ENOTSOCK; 529 return; 530 } 531 so = fp->f_socket; 532 m = m_getclr(M_WAIT, MT_SONAME); 533 u.u_error = 534 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); 535 if (u.u_error) 536 goto bad; 537 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, 538 sizeof (struct sockaddr)); 539 bad: 540 m_freem(m); 541 } 542 543 sockname(aname, name, namelen) 544 struct mbuf **aname; 545 caddr_t name; 546 int namelen; 547 { 548 register struct mbuf *m; 549 int error; 550 551 if (namelen > MLEN) 552 return (EINVAL); 553 m = m_get(M_WAIT, MT_SONAME); 554 m->m_len = namelen; 555 error = copyin(name, mtod(m, caddr_t), (u_int)namelen); 556 if (error) 557 (void) m_free(m); 558 else 559 *aname = m; 560 return (error); 561 } 562 563 sockopt(so, opt) 564 register struct socketopt *so; 565 caddr_t opt; 566 { 567 register struct mbuf *m; 568 int error; 569 570 if (opt == 0) { 571 so->so_optlen = 0; 572 so->so_optdata = 0; 573 return (0); 574 } 575 error = copyin((caddr_t)opt, (caddr_t)so, sizeof (struct socketopt)); 576 if (error) 577 return (error); 578 if (so->so_optlen < 0 || so->so_optlen > MLEN) 579 return (EINVAL); 580 m = m_get(M_WAIT, MT_SOOPTS); 581 m->m_len = so->so_optlen; 582 error = copyin(so->so_optdata, mtod(m, caddr_t), (u_int)m->m_len); 583 if (error) { 584 (void) m_free(m); 585 return (error); 586 } 587 so->so_optdata = mtod(m, caddr_t); 588 return (0); 589 } 590