/* Open a NETLINK socket. */ int __netlink_open (struct netlink_handle *h) { struct sockaddr_nl nladdr; h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (h->fd < 0) goto out; memset (&nladdr, '\0', sizeof (nladdr)); nladdr.nl_family = AF_NETLINK; if (__bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0) { close_and_out: __netlink_close (h); out: #if __ASSUME_NETLINK_SUPPORT == 0 __no_netlink_support = 1; #endif return -1; } /* Determine the ID the kernel assigned for this netlink connection. It is not necessarily the PID if there is more than one socket open. */ socklen_t addr_len = sizeof (nladdr); if (__getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0) goto close_and_out; h->pid = nladdr.nl_pid; return 0; }
/* * Create a socket that is locally bound to a non-reserve port. For * any failures, -1 is returned which will cause the RPC code to * create the socket. */ int internal_function __get_socket (struct sockaddr_in *saddr) { int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (so < 0) return -1; struct sockaddr_in laddr; socklen_t namelen = sizeof (laddr); laddr.sin_family = AF_INET; laddr.sin_port = 0; laddr.sin_addr.s_addr = htonl (INADDR_ANY); int cc = __bind (so, (struct sockaddr *) &laddr, namelen); if (__glibc_unlikely (cc < 0)) { fail: __close (so); return -1; } cc = __connect (so, (struct sockaddr *) saddr, namelen); if (__glibc_unlikely (cc < 0)) goto fail; return so; }
/* * Bind a socket to a privileged IP port */ int bindresvport (int sd, struct sockaddr_in *sin) { static short port; struct sockaddr_in myaddr; int i; #define STARTPORT 600 #define LOWPORT 512 #define ENDPORT (IPPORT_RESERVED - 1) #define NPORTS (ENDPORT - STARTPORT + 1) static short startport = STARTPORT; if (sin == (struct sockaddr_in *) 0) { sin = &myaddr; __bzero (sin, sizeof (*sin)); sin->sin_family = AF_INET; } else if (sin->sin_family != AF_INET) { __set_errno (EAFNOSUPPORT); return -1; } if (port == 0) { port = (__getpid () % NPORTS) + STARTPORT; } /* Initialize to make gcc happy. */ int res = -1; int nports = ENDPORT - startport + 1; int endport = ENDPORT; again: for (i = 0; i < nports; ++i) { sin->sin_port = htons (port++); if (port > endport) port = startport; res = __bind (sd, (const struct sockaddr *)sin, sizeof (struct sockaddr_in)); if (res >= 0 || errno != EADDRINUSE) break; } if (i == nports && startport != LOWPORT) { startport = LOWPORT; endport = STARTPORT - 1; nports = STARTPORT - LOWPORT; port = LOWPORT + port % (STARTPORT - LOWPORT); goto again; } return res; }
/* * bind stub, legacy version */ int bind(int s, const struct sockaddr *name, socklen_t namelen) { int ret = __bind(s, name, namelen); /* use ENOTSUP for legacy behavior */ if (ret < 0 && errno == EOPNOTSUPP) errno = ENOTSUP; return ret; }
/* * Usage: * xprt = svcunix_create(sock, send_buf_size, recv_buf_size); * * Creates, registers, and returns a (rpc) unix based transporter. * Once *xprt is initialized, it is registered as a transporter * see (svc.h, xprt_register). This routine returns * a NULL if a problem occurred. * * If sock<0 then a socket is created, else sock is used. * If the socket, sock is not bound to a port then svcunix_create * binds it to an arbitrary port. The routine then starts a unix * listener on the socket's associated port. In any (successful) case, * xprt->xp_sock is the registered socket number and xprt->xp_port is the * associated port number. * * Since unix streams do buffered io similar to stdio, the caller can specify * how big the send and receive buffers are via the second and third parms; * 0 => use the system default. */ SVCXPRT * svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) { bool_t madesock = FALSE; SVCXPRT *xprt; struct unix_rendezvous *r; struct sockaddr_un addr; socklen_t len = sizeof (struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0) { perror (_("svc_unix.c - AF_UNIX socket creation problem")); return (SVCXPRT *) NULL; } madesock = TRUE; } memset (&addr, '\0', sizeof (addr)); addr.sun_family = AF_UNIX; len = strlen (path) + 1; memcpy (addr.sun_path, path, len); len += sizeof (addr.sun_family); __bind (sock, (struct sockaddr *) &addr, len); if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0 || __listen (sock, SOMAXCONN) != 0) { perror (_("svc_unix.c - cannot getsockname or listen")); if (madesock) __close (sock); return (SVCXPRT *) NULL; } r = (struct unix_rendezvous *) mem_alloc (sizeof (*r)); xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); if (r == NULL || xprt == NULL) { __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); mem_free (r, sizeof (*r)); mem_free (xprt, sizeof (SVCXPRT)); return NULL; } r->sendsize = sendsize; r->recvsize = recvsize; xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t) r; xprt->xp_verf = _null_auth; xprt->xp_ops = &svcunix_rendezvous_op; xprt->xp_port = -1; xprt->xp_sock = sock; xprt_register (xprt); return xprt; }
/* * Usage: * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); * * Creates, registers, and returns a (rpc) tcp based transporter. * Once *xprt is initialized, it is registered as a transporter * see (svc.h, xprt_register). This routine returns * a NULL if a problem occurred. * * If sock<0 then a socket is created, else sock is used. * If the socket, sock is not bound to a port then svctcp_create * binds it to an arbitrary port. The routine then starts a tcp * listener on the socket's associated port. In any (successful) case, * xprt->xp_sock is the registered socket number and xprt->xp_port is the * associated port number. * * Since tcp streams do buffered io similar to stdio, the caller can specify * how big the send and receive buffers are via the second and third parms; * 0 => use the system default. */ SVCXPRT * svctcp_create (int sock, u_int sendsize, u_int recvsize) { bool_t madesock = FALSE; SVCXPRT *xprt; struct tcp_rendezvous *r; struct sockaddr_in addr; socklen_t len = sizeof (struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror (_("svc_tcp.c - tcp socket creation problem")); return (SVCXPRT *) NULL; } madesock = TRUE; } __bzero ((char *) &addr, sizeof (addr)); addr.sin_family = AF_INET; if (bindresvport (sock, &addr)) { addr.sin_port = 0; (void) __bind (sock, (struct sockaddr *) &addr, len); } if ((__getsockname (sock, (struct sockaddr *) &addr, &len) != 0) || (__listen (sock, SOMAXCONN) != 0)) { perror (_("svc_tcp.c - cannot getsockname or listen")); if (madesock) (void) __close (sock); return (SVCXPRT *) NULL; } r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r)); xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); if (r == NULL || xprt == NULL) { (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); mem_free (r, sizeof (*r)); mem_free (xprt, sizeof (SVCXPRT)); return NULL; } r->sendsize = sendsize; r->recvsize = recvsize; xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t) r; xprt->xp_verf = _null_auth; xprt->xp_ops = &svctcp_rendezvous_op; xprt->xp_port = ntohs (addr.sin_port); xprt->xp_sock = sock; xprt_register (xprt); return xprt; }
/* * Swap in a new table (destroying old one). */ int dm_swap_table(struct mapped_device *md, struct dm_table *table) { int r = -EINVAL; down(&md->suspend_lock); /* device must be suspended */ if (!dm_suspended(md)) goto out; __unbind(md); r = __bind(md, table); out: up(&md->suspend_lock); return r; }
/* * Swap in a new table (destroying old one). */ int dm_swap_table(struct mapped_device *md, struct dm_table *table) { int r; down_write(&md->lock); /* device must be suspended */ if (!test_bit(DMF_SUSPENDED, &md->flags)) { up_write(&md->lock); return -EPERM; } __unbind(md); r = __bind(md, table); if (r) return r; up_write(&md->lock); return 0; }
/* * Swap in a new table (destroying old one). */ int dm_swap_table(struct mapped_device *md, struct dm_table *table) { int r = -EINVAL; down(&md->suspend_lock); /* device must be suspended */ if (!dm_suspended(md)) goto out; /* without bdev, the device size cannot be changed */ if (!md->suspended_bdev) if (get_capacity(md->disk) != dm_table_get_size(table)) goto out; __unbind(md); r = __bind(md, table); out: up(&md->suspend_lock); return r; }