summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netlink-private/types.h1
-rw-r--r--include/netlink/netlink.h2
-rw-r--r--include/netlink/socket.h3
-rw-r--r--lib/nl.c105
-rw-r--r--lib/socket.c68
-rw-r--r--libnl-3.sym1
6 files changed, 90 insertions, 90 deletions
diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h
index 7d044f1..54f06b5 100644
--- a/include/netlink-private/types.h
+++ b/include/netlink-private/types.h
@@ -77,7 +77,6 @@ struct nl_sock
int s_flags;
struct nl_cb * s_cb;
size_t s_bufsize;
- int s_cloexec;
};
struct nl_cache
diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h
index 7b6cb60..f8f2082 100644
--- a/include/netlink/netlink.h
+++ b/include/netlink/netlink.h
@@ -49,8 +49,6 @@ extern struct nl_dump_params nl_debug_dp;
/* Connection Management */
extern int nl_connect(struct nl_sock *, int);
-extern int nl_create_fd(struct nl_sock *, int);
-extern int nl_connect_fd(struct nl_sock *, int, int);
extern void nl_close(struct nl_sock *);
/* Send */
diff --git a/include/netlink/socket.h b/include/netlink/socket.h
index bda0ff3..9a68cad 100644
--- a/include/netlink/socket.h
+++ b/include/netlink/socket.h
@@ -60,11 +60,10 @@ extern void nl_socket_disable_auto_ack(struct nl_sock *);
extern void nl_socket_enable_auto_ack(struct nl_sock *);
extern int nl_socket_get_fd(const struct nl_sock *);
+extern int nl_socket_set_fd(struct nl_sock *sk, int protocol, int fd);
extern int nl_socket_set_nonblocking(const struct nl_sock *);
extern void nl_socket_enable_msg_peek(struct nl_sock *);
extern void nl_socket_disable_msg_peek(struct nl_sock *);
-extern int nl_socket_enable_cloexec(struct nl_sock *);
-extern void nl_socket_disable_cloexec(struct nl_sock *);
#ifdef __cplusplus
}
diff --git a/lib/nl.c b/lib/nl.c
index 4997e79..8fc9ec1 100644
--- a/lib/nl.c
+++ b/lib/nl.c
@@ -63,57 +63,19 @@
*/
/**
- * Create file descriptor.
+ * Create file descriptor and bind socket.
* @arg sk Netlink socket (required)
* @arg protocol Netlink protocol to use (required)
*
- * Creates a new Netlink socket using `socket()` . Fails if
- * the socket is already connected.
- */
-int nl_create_fd(struct nl_sock *sk, int protocol)
-{
- int err, flags = 0;
- int errsv;
- char buf[64];
-
-
-#ifdef SOCK_CLOEXEC
- if (sk->s_cloexec == 1)
- flags |= SOCK_CLOEXEC;
-#endif
-
- if (sk->s_fd != -1)
- return -NLE_BAD_SOCK;
-
- sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol);
- if (sk->s_fd < 0) {
- errsv = errno;
- NL_DBG(4, "nl_connect(%p): socket() failed with %d (%s)\n", sk, errsv,
- strerror_r(errsv, buf, sizeof(buf)));
- err = -nl_syserr2nlerr(errsv);
- goto errout;
- }
-
- return 0;
-
-errout:
- if (sk->s_fd != -1) {
- close(sk->s_fd);
- sk->s_fd = -1;
- }
-
- return err;
-}
-
-/**
- * Create file descriptor and bind socket.
- * @arg sk Netlink socket (required)
- * @arg protocol Netlink protocol to use (required)
- *
* Creates a new Netlink socket using `socket()` and binds the socket to the
* protocol and local port specified in the `sk` socket object. Fails if
* the socket is already connected.
*
+ * @note If available, the `close-on-exec` (`SOCK_CLOEXEC`) feature is enabled
+ * automatically on the new file descriptor. This causes the socket to
+ * be closed automatically if any of the `exec` family functions succeed.
+ * This is essential for multi threaded programs.
+ *
* @note The local port (`nl_socket_get_local_port()`) is unspecified after
* creating a new socket. It only gets determined when accessing the
* port the first time or during `nl_connect()`. When nl_connect()
@@ -124,8 +86,13 @@ errout:
* This capability is indicated by
* `%NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE`.
*
+ * @note nl_connect() creates and sets the file descriptor. You can setup the file
+ * descriptor yourself by creating and binding it, and then calling
+ * nl_socket_set_fd(). The result will be the same.
+ *
* @see nl_socket_alloc()
* @see nl_close()
+ * @see nl_socket_set_fd()
*
* @return 0 on success or a negative error code.
*
@@ -133,47 +100,27 @@ errout:
*/
int nl_connect(struct nl_sock *sk, int protocol)
{
- int err = nl_create_fd(sk, protocol);
- if (err != 0)
- return err;
-
- return nl_connect_fd(sk, protocol, sk->s_fd);
-}
-
-/**
- * @arg sk Netlink socket (required)
- * @arg protocol Netlink protocol to use (required)
- * @arg fd Socket file descriptor to use (required)
- *
- * @note The local port (`nl_socket_get_local_port()`) is unspecified after
- * creating a new socket. It only gets determined when accessing the
- * port the first time or during `nl_connect_fd()`. When nl_connect_fd()
- * fails during `bind()` due to `ADDRINUSE`, it will retry with
- * different ports if the port is unspecified. Unless you want to enforce
- * the use of a specific local port, don't access the local port (or
- * reset it to `unspecified` by calling `nl_socket_set_local_port(sk, 0)`).
- * This capability is indicated by
- * `%NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE`.
- *
- * @see nl_socket_alloc()
- * @see nl_close()
- *
- * @return 0 on success or a negative error code.
- *
- * @retval -NLE_BAD_SOCK Socket is not connected
- */
-int nl_connect_fd(struct nl_sock *sk, int protocol, int fd)
-{
- int err = 0;
+ int err, flags = 0;
int errsv;
socklen_t addrlen;
struct sockaddr_nl local = { 0 };
char buf[64];
- if (fd < 0)
- return -NLE_BAD_SOCK;
+#ifdef SOCK_CLOEXEC
+ flags |= SOCK_CLOEXEC;
+#endif
- sk->s_fd = fd;
+ if (sk->s_fd != -1)
+ return -NLE_BAD_SOCK;
+
+ sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol);
+ if (sk->s_fd < 0) {
+ errsv = errno;
+ NL_DBG(4, "nl_connect(%p): socket() failed with %d (%s)\n", sk, errsv,
+ strerror_r(errsv, buf, sizeof(buf)));
+ err = -nl_syserr2nlerr(errsv);
+ goto errout;
+ }
err = nl_socket_set_buffer_size(sk, 0, 0);
if (err < 0)
diff --git a/lib/socket.c b/lib/socket.c
index 01cc219..049b8b9 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -192,12 +192,6 @@ static struct nl_sock *__alloc_socket(struct nl_cb *cb)
sk->s_peer.nl_family = AF_NETLINK;
sk->s_seq_expect = sk->s_seq_next = time(NULL);
-#ifdef SOCK_CLOEXEC
- sk->s_cloexec = 1;
-#else
- sk->s_cloexec = 0;
-#endif
-
/* the port is 0 (unspecified), meaning NL_OWN_PORT */
sk->s_flags = NL_OWN_PORT;
@@ -579,6 +573,68 @@ int nl_socket_get_fd(const struct nl_sock *sk)
}
/**
+ * Set the socket file descriptor externally which initializes the
+ * socket similar to nl_connect().
+ *
+ * @arg sk Netlink socket (required)
+ * @arg protocol Netlink protocol to use (required)
+ * @arg fd Socket file descriptor to use (required)
+ *
+ * Set the socket file descriptor. @fd must be valid and bind'ed.
+ *
+ * This is an alternative to nl_connect(). nl_connect() creates, binds and
+ * sets the socket. With this function you can set the socket to an externally
+ * created file descriptor.
+ *
+ * @see nl_connect()
+ *
+ * @return 0 on success or a negative error code. On error, @fd is not closed but
+ * possibly unusable.
+ *
+ * @retval -NLE_BAD_SOCK Netlink socket is already connected
+ * @retval -NLE_INVAL Socket is not connected
+ */
+int nl_socket_set_fd(struct nl_sock *sk, int protocol, int fd)
+{
+ int err = 0;
+ socklen_t addrlen;
+ char buf[64];
+ struct sockaddr_nl local = { 0 };
+
+ if (sk->s_fd != -1)
+ return -NLE_BAD_SOCK;
+ if (fd < 0)
+ return -NLE_INVAL;
+
+ addrlen = sizeof(local);
+ err = getsockname(fd, (struct sockaddr *) &local,
+ &addrlen);
+ if (err < 0) {
+ NL_DBG(4, "nl_socket_set_fd(%p): getsockname() failed with %d (%s)\n",
+ sk, errno, strerror_r(errno, buf, sizeof(buf)));
+ return -nl_syserr2nlerr(errno);
+ }
+
+ if (addrlen != sizeof(local))
+ return -NLE_NOADDR;
+
+ if (local.nl_family != AF_NETLINK)
+ return -NLE_AF_NOSUPPORT;
+
+ if (sk->s_local.nl_pid != local.nl_pid) {
+ /* the port id differs. The socket is using a port id not managed by
+ * libnl, hence reset the local port id to release a possibly generated
+ * port. */
+ nl_socket_set_local_port (sk, local.nl_pid);
+ }
+ sk->s_local = local;
+ sk->s_fd = fd;
+ sk->s_proto = protocol;
+
+ return 0;
+}
+
+/**
* Set file descriptor of socket to non-blocking state
* @arg sk Netlink socket.
*
diff --git a/libnl-3.sym b/libnl-3.sym
index df61001..c8ef8a3 100644
--- a/libnl-3.sym
+++ b/libnl-3.sym
@@ -328,4 +328,5 @@ libnl_3_2_26 {
global:
nl_cache_pickup_checkdup;
nl_pickup_keep_syserr;
+ nl_socket_set_fd;
} libnl_3;