int sock_bind(net_sock_t *nsock, char *address, int port) { network_sock_t *sock = (network_sock_t *)nsock; if (sock == NULL) return(1); sock->fd = fd_bind(address, port); if (sock->fd < 0) return(1); return(0); }
/*! @decl int bind_unix(string path, void|function accept_callback) *! *! Opens a Unix domain socket at the given path in the file system. *! If the second argument is present, the socket is set to *! nonblocking and the callback funcition is called whenever *! something connects to it. The callback will receive the id for *! this port as argument and should typically call @[accept] to *! establish a connection. *! *! @returns *! 1 is returned on success, zero on failure. @[errno] provides *! further details about the error in the latter case. *! *! @note *! This function is only available on systems that support Unix domain *! sockets. *! *! @note *! @[path] had a quite restrictive length limit (~100 characters) *! prior to Pike 7.8.334. *! *! @seealso *! @[accept], @[set_id] */ static void bind_unix(INT32 args) { struct port *p = THIS; struct sockaddr_un *addr; struct pike_string *path; struct svalue *cb = NULL; int addr_len,fd,tmp; do_close(p); get_all_args(NULL, args, "%n.%*", &path, &cb); /* NOTE: Some operating systems (eg Linux 2.6) do not support * paths longer than what fits into a plain struct sockaddr_un. */ addr_len = sizeof(struct sockaddr_un) + path->len + 1 - sizeof(addr->sun_path); addr = xalloc(addr_len); strcpy(addr->sun_path, path->str); addr->sun_family = AF_UNIX; #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN /* Length including NUL. */ addr->sun_len = path->len + 1; #endif fd=fd_socket(AF_UNIX, SOCK_STREAM, 0); if(fd < 0) { free(addr); p->my_errno=errno; pop_n_elems(args); push_int(0); return; } #ifndef __NT__ { int o=1; do { tmp = fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)); } while ((tmp < 0) && (errno == EINTR)); } #endif my_set_close_on_exec(fd,1); THREADS_ALLOW_UID(); do { tmp = fd_bind(fd, (struct sockaddr *)addr, addr_len); } while ((tmp < 0) && (errno == EINTR)); if (tmp >= 0) { do { tmp = fd_listen(fd, 16384); } while ((tmp < 0) && (errno == EINTR)); } THREADS_DISALLOW_UID(); free(addr); if(!Pike_fp->current_object->prog) { if (fd >= 0) while (fd_close(fd) && errno == EINTR) {} Pike_error("Object destructed in Stdio.Port->bind_unix()\n"); } if(tmp < 0) { p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } change_fd_for_box (&p->box, fd); if (cb) assign_accept_cb (p, cb); p->my_errno=0; pop_n_elems(args); push_int(1); }
struct glfs_fd * glfs_h_opendir (struct glfs *fs, struct glfs_object *object) { int ret = -1; struct glfs_fd *glfd = NULL; xlator_t *subvol = NULL; inode_t *inode = NULL; loc_t loc = {0, }; /* validate in args */ if ((fs == NULL) || (object == NULL)) { errno = EINVAL; return NULL; } __glfs_entry_fs (fs); /* get the active volume */ subvol = glfs_active_subvol (fs); if (!subvol) { ret = -1; errno = EIO; goto out; } /* get/refresh the in arg objects inode in correlation to the xlator */ inode = glfs_resolve_inode (fs, subvol, object); if (!inode) { errno = ESTALE; goto out; } if (!IA_ISDIR (inode->ia_type)) { ret = -1; errno = ENOTDIR; goto out; } glfd = glfs_fd_new (fs); if (!glfd) goto out; INIT_LIST_HEAD (&glfd->entries); glfd->fd = fd_create (inode, getpid()); if (!glfd->fd) { ret = -1; errno = ENOMEM; goto out; } GLFS_LOC_FILL_INODE (inode, loc, out); /* fop/op */ ret = syncop_opendir (subvol, &loc, glfd->fd); DECODE_SYNCOP_ERR (ret); out: loc_wipe (&loc); if (inode) inode_unref (inode); if (ret && glfd) { glfs_fd_destroy (glfd); glfd = NULL; } else { fd_bind (glfd->fd); glfs_fd_bind (glfd); } glfs_subvol_done (fs, subvol); return glfd; }
/*! @decl int bind(int|string port, void|function accept_callback, @ *! void|string ip, void|string reuse_port) *! *! Opens a socket and binds it to port number on the local machine. *! If the second argument is present, the socket is set to *! nonblocking and the callback funcition is called whenever *! something connects to it. The callback will receive the id for *! this port as argument and should typically call @[accept] to *! establish a connection. *! *! If the optional argument @[ip] is given, @[bind] will try to bind *! to an interface with that host name or IP number. Omitting this *! will bind to all available IPv4 addresses; specifying "::" will *! bind to all IPv4 and IPv6 addresses. *! *! If the OS supports TCP_FASTOPEN it is enabled automatically. *! *! If the OS supports SO_REUSEPORT it is enabled if the fourth argument is true. *! *! @returns *! 1 is returned on success, zero on failure. @[errno] provides *! further details about the error in the latter case. *! *! @seealso *! @[accept], @[set_id] */ static void port_bind(INT32 args) { struct port *p = THIS; PIKE_SOCKADDR addr; int addr_len,fd,tmp; do_close(p); if(args < 1) SIMPLE_WRONG_NUM_ARGS_ERROR("bind", 1); if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT && (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING || Pike_sp[-args].u.string->size_shift)) SIMPLE_ARG_TYPE_ERROR("bind", 1, "int|string(8bit)"); addr_len = get_inet_addr(&addr, (args > 2 && TYPEOF(Pike_sp[2-args])==PIKE_T_STRING? Pike_sp[2-args].u.string->str : NULL), (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING? Pike_sp[-args].u.string->str : NULL), (TYPEOF(Pike_sp[-args]) == PIKE_T_INT? Pike_sp[-args].u.integer : -1), 0); INVALIDATE_CURRENT_TIME(); fd=fd_socket(SOCKADDR_FAMILY(addr), SOCK_STREAM, 0); if(fd < 0) { p->my_errno=errno; pop_n_elems(args); push_int(0); return; } #ifdef SO_REUSEPORT if( args > 3 && Pike_sp[3-args].u.integer ) { /* FreeBSD 7.x wants this to reuse portnumbers. * Linux 2.6.x seems to have reserved a slot for the option, but not * enabled it. Survive libc's with the option on kernels without. * * The emulated Linux runtime on MS Windows 10 fails this with EINVAL. */ int o=1; if((fd_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&o, sizeof(int)) < 0) #ifdef ENOPROTOOPT && (errno != ENOPROTOOPT) #endif #ifdef EINVAL && (errno != EINVAL) #endif #ifdef WSAENOPROTOOPT && (errno != WSAENOPROTOOPT) #endif ){ p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } } #endif #ifndef __NT__ { int o=1; if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) { p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } } #endif #if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6) if (SOCKADDR_FAMILY(addr) == AF_INET6) { /* Attempt to enable dual-stack (ie mapped IPv4 adresses). * Needed on WIN32. * cf http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx */ int o = 0; fd_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int)); } #endif my_set_close_on_exec(fd,1); THREADS_ALLOW_UID(); if( !(tmp=fd_bind(fd, (struct sockaddr *)&addr, addr_len) < 0) ) #ifdef TCP_FASTOPEN tmp = 256, setsockopt(fd,SOL_TCP, TCP_FASTOPEN, &tmp, sizeof(tmp)), #endif (tmp = fd_listen(fd, 16384) < 0); THREADS_DISALLOW_UID(); if(!Pike_fp->current_object->prog) { if (fd >= 0) while (fd_close(fd) && errno == EINTR) {} Pike_error("Object destructed in Stdio.Port->bind()\n"); } if(tmp) { p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } change_fd_for_box (&p->box, fd); if(args > 1) assign_accept_cb (p, Pike_sp+1-args); p->my_errno=0; pop_n_elems(args); push_int(1); }