/* Create a new socket of type TYPE in domain DOMAIN, using protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. Returns a file descriptor for the new socket, or -1 for errors. */ int __socket (int domain, int type, int protocol) { error_t err; socket_t sock, server; /* Find the socket server for DOMAIN. */ server = _hurd_socket_server (domain, 0); if (server == MACH_PORT_NULL) return -1; err = __socket_create (server, type, protocol, &sock); if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED || err == MIG_BAD_ID || err == EOPNOTSUPP) { /* On the first use of the socket server during the operation, allow for the old server port dying. */ server = _hurd_socket_server (domain, 1); if (server == MACH_PORT_NULL) return -1; err = __socket_create (server, type, protocol, &sock); } /* These errors all mean that the server node doesn't support the socket.defs protocol, which we'll take to mean that the protocol isn't supported. */ if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED || err == MIG_BAD_ID || err == EOPNOTSUPP) err = EAFNOSUPPORT; if (err) return __hurd_fail (err); return _hurd_intern_fd (sock, O_IGNORE_CTTY, 1); }
void internal_function __protocol_available (int *have_inet, int *have_inet6) { *have_inet = _hurd_socket_server (PF_INET, 0) != MACH_PORT_NULL; *have_inet6 = _hurd_socket_server (PF_INET6, 0) != MACH_PORT_NULL; }
/* Return an array of if_nameindex structures, one for each network interface present, plus one indicating the end of the array. On error, return NULL. */ struct if_nameindex * if_nameindex (void) { error_t err = 0; char data[2048]; file_t server; int fd = __opensock (); struct ifconf ifc; unsigned int nifs, i; struct if_nameindex *idx = NULL; ifc.ifc_buf = data; if (fd < 0) return NULL; server = _hurd_socket_server (PF_INET, 0); if (server == MACH_PORT_NULL) nifs = 0; else { size_t len = sizeof data; err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len); if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED) { /* On the first use of the socket server during the operation, allow for the old server port dying. */ server = _hurd_socket_server (PF_INET, 1); if (server == MACH_PORT_NULL) goto out; err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len); } if (err) goto out; ifc.ifc_len = len; nifs = len / sizeof (struct ifreq); } idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); if (idx == NULL) { err = ENOBUFS; goto out; } for (i = 0; i < nifs; ++i) { struct ifreq *ifr = &ifc.ifc_req[i]; idx[i].if_name = __strdup (ifr->ifr_name); if (idx[i].if_name == NULL || __ioctl (fd, SIOCGIFINDEX, ifr) < 0) { unsigned int j; err = errno; for (j = 0; j < i; ++j) free (idx[j].if_name); free (idx); idx = NULL; if (err == EINVAL) err = ENOSYS; else if (err == ENOMEM) err = ENOBUFS; goto out; } idx[i].if_index = ifr->ifr_ifindex; } idx[i].if_index = 0; idx[i].if_name = NULL; out: __close (fd); if (data != ifc.ifc_buf) __vm_deallocate (__mach_task_self (), (vm_address_t) ifc.ifc_buf, ifc.ifc_len); __set_errno (err); return idx; }
/* Create two new sockets, of type TYPE in domain DOMAIN and using protocol PROTOCOL, which are connected to each other, and put file descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, one will be chosen automatically. Returns 0 on success, -1 for errors. */ int __socketpair (int domain, int type, int protocol, int fds[2]) { error_t err; socket_t server, sock1, sock2; int d1, d2; if (fds == NULL) return __hurd_fail (EINVAL); /* Find the domain's socket server. */ server = _hurd_socket_server (domain, 0); if (server == MACH_PORT_NULL) return -1; /* Create two sockets and connect them together. */ err = __socket_create (server, type, protocol, &sock1); if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED || err == MIG_BAD_ID || err == EOPNOTSUPP) { /* On the first use of the socket server during the operation, allow for the old server port dying. */ server = _hurd_socket_server (domain, 1); if (server == MACH_PORT_NULL) return -1; err = __socket_create (server, type, protocol, &sock1); } if (err) return __hurd_fail (err); if (err = __socket_create (server, type, protocol, &sock2)) { __mach_port_deallocate (__mach_task_self (), sock1); return __hurd_fail (err); } if (err = __socket_connect2 (sock1, sock2)) { __mach_port_deallocate (__mach_task_self (), sock1); __mach_port_deallocate (__mach_task_self (), sock2); return __hurd_fail (err); } /* Put the sockets into file descriptors. */ d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY, 1); if (d1 < 0) { __mach_port_deallocate (__mach_task_self (), sock2); return -1; } d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY, 1); if (d2 < 0) { err = errno; (void) close (d1); return __hurd_fail (err); } fds[0] = d1; fds[1] = d2; return 0; }