Print this page
3769 Implement SOCK_NONBLOCK flag to socket()
Reviewed-by: Robert Mustacchi <rm@joyent.com>


  92  * Kernel component of socket creation.
  93  *
  94  * The socket library determines which version number to use.
  95  * First the library calls this with a NULL devpath. If this fails
  96  * to find a transport (using solookup) the library will look in /etc/netconfig
  97  * for the appropriate transport. If one is found it will pass in the
  98  * devpath for the kernel to use.
  99  */
 100 int
 101 so_socket(int family, int type_w_flags, int protocol, char *devpath,
 102     int version)
 103 {
 104         struct sonode *so;
 105         vnode_t *vp;
 106         struct file *fp;
 107         int fd;
 108         int error;
 109         int type;
 110 
 111         type = type_w_flags & SOCK_TYPE_MASK;




 112         if (devpath != NULL) {
 113                 char *buf;
 114                 size_t kdevpathlen = 0;
 115 
 116                 buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 117                 if ((error = copyinstr(devpath, buf,
 118                     MAXPATHLEN, &kdevpathlen)) != 0) {
 119                         kmem_free(buf, MAXPATHLEN);
 120                         return (set_errno(error));
 121                 }
 122                 so = socket_create(family, type, protocol, buf, NULL,
 123                     SOCKET_SLEEP, version, CRED(), &error);
 124                 kmem_free(buf, MAXPATHLEN);
 125         } else {
 126                 so = socket_create(family, type, protocol, NULL, NULL,
 127                     SOCKET_SLEEP, version, CRED(), &error);
 128         }
 129         if (so == NULL)
 130                 return (set_errno(error));
 131 
 132         /* Allocate a file descriptor for the socket */
 133         vp = SOTOV(so);
 134         if (error = falloc(vp, FWRITE|FREAD, &fp, &fd)) {
 135                 (void) socket_close(so, 0, CRED());
 136                 socket_destroy(so);
 137                 return (set_errno(error));
 138         }
 139 
 140         /*
 141          * Now fill in the entries that falloc reserved
 142          */








 143         mutex_exit(&fp->f_tlock);
 144         setf(fd, fp);
 145         if ((type_w_flags & SOCK_CLOEXEC) != 0) {
 146                 f_setfd(fd, FD_CLOEXEC);
 147         }
 148 
 149         return (fd);
 150 }
 151 
 152 /*
 153  * Map from a file descriptor to a socket node.
 154  * Returns with the file descriptor held i.e. the caller has to
 155  * use releasef when done with the file descriptor.
 156  */
 157 struct sonode *
 158 getsonode(int sock, int *errorp, file_t **fpp)
 159 {
 160         file_t *fp;
 161         vnode_t *vp;
 162         struct sonode *so;


 471 
 472                 /* wait for so2 being SS_CONNECTED ignoring signals */
 473                 mutex_enter(&so2->so_lock);
 474                 error = sowaitconnected(so2, 0, 1);
 475                 mutex_exit(&so2->so_lock);
 476                 if (error != 0) {
 477                         (void) socket_close(nso, 0, CRED());
 478                         socket_destroy(nso);
 479                         eprintsoline(so2, error);
 480                         goto done;
 481                 }
 482 
 483                 nvp = SOTOV(nso);
 484                 if (error = falloc(nvp, FWRITE|FREAD, &nfp, &nfd)) {
 485                         (void) socket_close(nso, 0, CRED());
 486                         socket_destroy(nso);
 487                         eprintsoline(nso, error);
 488                         goto done;
 489                 }
 490                 /*








 491                  * fill in the entries that falloc reserved
 492                  */
 493                 mutex_exit(&nfp->f_tlock);
 494                 setf(nfd, nfp);
 495 





 496                 releasef(svs[0]);
 497                 releasef(svs[1]);
 498 
 499                 /*
 500                  * If FD_CLOEXEC was set on the filedescriptor we're
 501                  * swapping out, we should set it on the new one too.
 502                  */
 503                 VERIFY(f_getfd_error(svs[0], &orig_flags) == 0);
 504                 if (orig_flags & FD_CLOEXEC) {
 505                         f_setfd(nfd, FD_CLOEXEC);
 506                 }
 507 
 508                 /*
 509                  * The socketpair library routine will close the original
 510                  * svs[0] when this code passes out a different file
 511                  * descriptor.
 512                  */
 513                 svs[0] = nfd;
 514 
 515                 if (copyout(svs, sv, sizeof (svs))) {
 516                         (void) closeandsetf(nfd, NULL);
 517                         eprintline(EFAULT);
 518                         return (set_errno(EFAULT));
 519                 }
 520         }
 521         return (0);
 522 
 523 done:




  92  * Kernel component of socket creation.
  93  *
  94  * The socket library determines which version number to use.
  95  * First the library calls this with a NULL devpath. If this fails
  96  * to find a transport (using solookup) the library will look in /etc/netconfig
  97  * for the appropriate transport. If one is found it will pass in the
  98  * devpath for the kernel to use.
  99  */
 100 int
 101 so_socket(int family, int type_w_flags, int protocol, char *devpath,
 102     int version)
 103 {
 104         struct sonode *so;
 105         vnode_t *vp;
 106         struct file *fp;
 107         int fd;
 108         int error;
 109         int type;
 110 
 111         type = type_w_flags & SOCK_TYPE_MASK;
 112         type_w_flags &= ~SOCK_TYPE_MASK;
 113         if (type_w_flags & ~(SOCK_CLOEXEC|SOCK_NDELAY|SOCK_NONBLOCK))
 114                 return (set_errno(EINVAL));
 115 
 116         if (devpath != NULL) {
 117                 char *buf;
 118                 size_t kdevpathlen = 0;
 119 
 120                 buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 121                 if ((error = copyinstr(devpath, buf,
 122                     MAXPATHLEN, &kdevpathlen)) != 0) {
 123                         kmem_free(buf, MAXPATHLEN);
 124                         return (set_errno(error));
 125                 }
 126                 so = socket_create(family, type, protocol, buf, NULL,
 127                     SOCKET_SLEEP, version, CRED(), &error);
 128                 kmem_free(buf, MAXPATHLEN);
 129         } else {
 130                 so = socket_create(family, type, protocol, NULL, NULL,
 131                     SOCKET_SLEEP, version, CRED(), &error);
 132         }
 133         if (so == NULL)
 134                 return (set_errno(error));
 135 
 136         /* Allocate a file descriptor for the socket */
 137         vp = SOTOV(so);
 138         if (error = falloc(vp, FWRITE|FREAD, &fp, &fd)) {
 139                 (void) socket_close(so, 0, CRED());
 140                 socket_destroy(so);
 141                 return (set_errno(error));
 142         }
 143 
 144         /*
 145          * Now fill in the entries that falloc reserved
 146          */
 147         if (type_w_flags & SOCK_NDELAY) {
 148                 so->so_state |= SS_NDELAY;
 149                 fp->f_flag |= FNDELAY;
 150         }
 151         if (type_w_flags & SOCK_NONBLOCK) {
 152                 so->so_state |= SS_NONBLOCK;
 153                 fp->f_flag |= FNONBLOCK;
 154         }
 155         mutex_exit(&fp->f_tlock);
 156         setf(fd, fp);
 157         if ((type_w_flags & SOCK_CLOEXEC) != 0) {
 158                 f_setfd(fd, FD_CLOEXEC);
 159         }
 160 
 161         return (fd);
 162 }
 163 
 164 /*
 165  * Map from a file descriptor to a socket node.
 166  * Returns with the file descriptor held i.e. the caller has to
 167  * use releasef when done with the file descriptor.
 168  */
 169 struct sonode *
 170 getsonode(int sock, int *errorp, file_t **fpp)
 171 {
 172         file_t *fp;
 173         vnode_t *vp;
 174         struct sonode *so;


 483 
 484                 /* wait for so2 being SS_CONNECTED ignoring signals */
 485                 mutex_enter(&so2->so_lock);
 486                 error = sowaitconnected(so2, 0, 1);
 487                 mutex_exit(&so2->so_lock);
 488                 if (error != 0) {
 489                         (void) socket_close(nso, 0, CRED());
 490                         socket_destroy(nso);
 491                         eprintsoline(so2, error);
 492                         goto done;
 493                 }
 494 
 495                 nvp = SOTOV(nso);
 496                 if (error = falloc(nvp, FWRITE|FREAD, &nfp, &nfd)) {
 497                         (void) socket_close(nso, 0, CRED());
 498                         socket_destroy(nso);
 499                         eprintsoline(nso, error);
 500                         goto done;
 501                 }
 502                 /*
 503                  * copy over FNONBLOCK and FNDELAY flags should they exist
 504                  */
 505                 if (so1->so_state & SS_NONBLOCK)
 506                         nfp->f_flag |= FNONBLOCK;
 507                 if (so1->so_state & SS_NDELAY)
 508                         nfp->f_flag |= FNDELAY;
 509 
 510                 /*
 511                  * fill in the entries that falloc reserved
 512                  */
 513                 mutex_exit(&nfp->f_tlock);
 514                 setf(nfd, nfp);
 515 
 516                 /*
 517                  * get the original flags before we release
 518                  */
 519                 VERIFY(f_getfd_error(svs[0], &orig_flags) == 0);
 520 
 521                 releasef(svs[0]);
 522                 releasef(svs[1]);
 523 
 524                 /*
 525                  * If FD_CLOEXEC was set on the filedescriptor we're
 526                  * swapping out, we should set it on the new one too.
 527                  */

 528                 if (orig_flags & FD_CLOEXEC) {
 529                         f_setfd(nfd, FD_CLOEXEC);
 530                 }
 531 
 532                 /*
 533                  * The socketpair library routine will close the original
 534                  * svs[0] when this code passes out a different file
 535                  * descriptor.
 536                  */
 537                 svs[0] = nfd;
 538 
 539                 if (copyout(svs, sv, sizeof (svs))) {
 540                         (void) closeandsetf(nfd, NULL);
 541                         eprintline(EFAULT);
 542                         return (set_errno(EFAULT));
 543                 }
 544         }
 545         return (0);
 546 
 547 done: