1 /* uipc_syscalls.c 4.37 82/11/15 */ 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 if (copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, sizeof (namelen))) { 125 u.u_error = EFAULT; 126 return; 127 } 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); 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 if (copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen, sizeof (fromlen))) { 366 u.u_error = EFAULT; 367 return; 368 } 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 if (copyout(mtod(from, caddr_t), uap->from, (u_int)fromlen)) { 397 u.u_error = EFAULT; 398 goto bad; 399 } 400 } 401 if (copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr, 402 sizeof (fromlen))) { 403 u.u_error = EFAULT; 404 goto bad; 405 } 406 u.u_r.r_val1 = uap->len - auio.uio_resid; 407 bad: 408 if (from) 409 m_freem(from); 410 return; 411 } 412 413 recv() 414 { 415 register struct a { 416 int s; 417 caddr_t buf; 418 int len; 419 int flags; 420 } *uap = (struct a *)u.u_ap; 421 register struct file *fp; 422 struct uio auio; 423 struct iovec aiov; 424 425 fp = getf(uap->s); 426 if (fp == 0) 427 return; 428 if (fp->f_type != DTYPE_SOCKET) { 429 u.u_error = ENOTSOCK; 430 return; 431 } 432 auio.uio_iov = &aiov; 433 auio.uio_iovcnt = 1; 434 aiov.iov_base = uap->buf; 435 aiov.iov_len = uap->len; 436 auio.uio_resid = uap->len; 437 auio.uio_segflg = 0; 438 auio.uio_offset = 0; /* XXX */ 439 if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { 440 u.u_error = EFAULT; 441 return; 442 } 443 u.u_error = 444 soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags); 445 u.u_r.r_val1 = uap->len - auio.uio_resid; 446 } 447 448 sendmsg() 449 { 450 451 u.u_error = EINVAL; 452 } 453 454 recvmsg() 455 { 456 457 u.u_error = EINVAL; 458 } 459 460 shutdown() 461 { 462 463 u.u_error = EINVAL; 464 } 465 466 pipe() 467 { 468 register struct file *rf, *wf; 469 struct socket *rso, *wso; 470 int r; 471 472 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, 473 (struct socketopt *)0); 474 if (u.u_error) 475 return; 476 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, 477 (struct socketopt *)0); 478 if (u.u_error) 479 goto free; 480 rf = falloc(); 481 if (rf == NULL) 482 goto free2; 483 r = u.u_r.r_val1; 484 rf->f_flag = FREAD; 485 rf->f_type = DTYPE_SOCKET; 486 rf->f_socket = rso; 487 wf = falloc(); 488 if (wf == NULL) 489 goto free3; 490 wf->f_flag = FWRITE; 491 wf->f_type = DTYPE_SOCKET; 492 wf->f_socket = wso; 493 u.u_r.r_val2 = u.u_r.r_val1; 494 u.u_r.r_val1 = r; 495 if (piconnect(wso, rso) == 0) 496 goto free4; 497 return; 498 free4: 499 wf->f_count = 0; 500 u.u_ofile[u.u_r.r_val2] = 0; 501 free3: 502 rf->f_count = 0; 503 u.u_ofile[r] = 0; 504 free2: 505 wso->so_state |= SS_NOFDREF; 506 sofree(wso); 507 free: 508 rso->so_state |= SS_NOFDREF; 509 sofree(rso); 510 } 511 512 /* 513 * Get socket address. 514 */ 515 ssocketaddr() 516 { 517 register struct a { 518 int fdes; 519 struct sockaddr *asa; 520 } *uap = (struct a *)u.u_ap; 521 register struct file *fp; 522 register struct socket *so; 523 struct mbuf *m; 524 525 fp = getf(uap->fdes); 526 if (fp == 0) 527 return; 528 if (fp->f_type != DTYPE_SOCKET) { 529 u.u_error = ENOTSOCK; 530 return; 531 } 532 so = fp->f_socket; 533 m = m_getclr(M_WAIT); 534 u.u_error = 535 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); 536 if (u.u_error) 537 goto bad; 538 if (copyout(mtod(m, caddr_t), (caddr_t)uap->asa, sizeof (struct sockaddr))) 539 u.u_error = EFAULT; 540 bad: 541 m_freem(m); 542 } 543 544 sockname(aname, name, namelen) 545 struct mbuf **aname; 546 caddr_t name; 547 int namelen; 548 { 549 register struct mbuf *m; 550 551 if (namelen > MLEN) 552 return (EINVAL); 553 m = m_get(M_WAIT); 554 m->m_len = namelen; 555 if (copyin(name, mtod(m, caddr_t), (u_int)namelen)) { 556 (void) m_free(m); 557 return (EFAULT); 558 } 559 *aname = m; 560 return (0); 561 } 562 563 sockopt(so, opt) 564 register struct socketopt *so; 565 caddr_t opt; 566 { 567 register struct mbuf *m; 568 569 if (opt == 0) { 570 so->so_optlen = 0; 571 so->so_optdata = 0; 572 return (0); 573 } 574 if (copyin((caddr_t)opt, (caddr_t)so, sizeof (struct socketopt))) 575 return (EFAULT); 576 if (so->so_optlen < 0 || so->so_optlen > MLEN) 577 return (EINVAL); 578 m = m_get(M_WAIT); 579 m->m_len = so->so_optlen; 580 if (copyin(so->so_optdata, mtod(m, caddr_t), (u_int)m->m_len)) { 581 (void) m_free(m); 582 return (EFAULT); 583 } 584 so->so_optdata = mtod(m, caddr_t); 585 return (0); 586 } 587