144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
21155370f520cb64657e25153255cf7dc1424317fThomas Graf * lib/socket.c		Netlink Socket
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
136782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @ingroup core
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup socket Socket
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h>
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/handlers.h>
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/msg.h>
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/attr.h>
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf
25680c54fd4616649763a50b122df6cff53b9e62bdThomas Grafstatic int default_cb = NL_CB_DEFAULT;
26680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf
27680c54fd4616649763a50b122df6cff53b9e62bdThomas Grafstatic void __init init_default_cb(void)
28680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf{
29680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf	char *nlcb;
30680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf
31680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf	if ((nlcb = getenv("NLCB"))) {
32680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf		if (!strcasecmp(nlcb, "default"))
33680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf			default_cb = NL_CB_DEFAULT;
34680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf		else if (!strcasecmp(nlcb, "verbose"))
35680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf			default_cb = NL_CB_VERBOSE;
36680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf		else if (!strcasecmp(nlcb, "debug"))
37680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf			default_cb = NL_CB_DEBUG;
38680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf		else {
39680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf			fprintf(stderr, "Unknown value for NLCB, valid values: "
40680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf				"{default | verbose | debug}\n");
41680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf		}
42680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf	}
43680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf}
44680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf
4544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint32_t used_ports_map[32];
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf
4744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint32_t generate_local_port(void)
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i, n;
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf	uint32_t pid = getpid() & 0x3FFFFF;
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (i = 0; i < 32; i++) {
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (used_ports_map[i] == 0xFFFFFFFF)
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf			continue;
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf		for (n = 0; n < 32; n++) {
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf			if (1UL & (used_ports_map[i] >> n))
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf				continue;
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf			used_ports_map[i] |= (1UL << n);
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf			n += (i * 32);
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf			/* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf			 * to, i.e. 1024 unique ports per application. */
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf			return pid + (n << 22);
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf	/* Out of sockets in our own PID namespace, what to do? FIXME */
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return UINT_MAX;
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf
7444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void release_local_port(uint32_t port)
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
7691c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf	int nr;
7744d362409d5469aed47d19e7908d19bd194493aThomas Graf
7891c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf	if (port == UINT_MAX)
7991c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf		return;
8091c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
8191c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf	nr = port >> 22;
82ef8ba32e0ca7ac7bbbaf87f6fd7b197af18aed25Inaky Perez-Gonzalez	used_ports_map[nr / 32] &= ~(1 << nr % 32);
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
8444d362409d5469aed47d19e7908d19bd194493aThomas Graf
8544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf
901155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic struct nl_sock *__alloc_socket(struct nl_cb *cb)
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
921155370f520cb64657e25153255cf7dc1424317fThomas Graf	struct nl_sock *sk;
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf
941155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk = calloc(1, sizeof(*sk));
951155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (!sk)
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf
981155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_fd = -1;
991155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_cb = cb;
1001155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_local.nl_family = AF_NETLINK;
1011155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_peer.nl_family = AF_NETLINK;
1021155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_seq_expect = sk->s_seq_next = time(0);
1031155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_local.nl_pid = generate_local_port();
1041155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_local.nl_pid == UINT_MAX) {
1051155370f520cb64657e25153255cf7dc1424317fThomas Graf		nl_socket_free(sk);
10691c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf		return NULL;
10791c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf	}
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf
1091155370f520cb64657e25153255cf7dc1424317fThomas Graf	return sk;
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1131155370f520cb64657e25153255cf7dc1424317fThomas Graf * Allocate new netlink socket
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1151155370f520cb64657e25153255cf7dc1424317fThomas Graf * @return Newly allocated netlink socket or NULL.
11644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1171155370f520cb64657e25153255cf7dc1424317fThomas Grafstruct nl_sock *nl_socket_alloc(void)
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
11944d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cb *cb;
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf
121680c54fd4616649763a50b122df6cff53b9e62bdThomas Graf	cb = nl_cb_alloc(default_cb);
1228a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if (!cb)
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
12444d362409d5469aed47d19e7908d19bd194493aThomas Graf
1251155370f520cb64657e25153255cf7dc1424317fThomas Graf	return __alloc_socket(cb);
12644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
12744d362409d5469aed47d19e7908d19bd194493aThomas Graf
12844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1291155370f520cb64657e25153255cf7dc1424317fThomas Graf * Allocate new socket with custom callbacks
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb		Callback handler
13144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
13244d362409d5469aed47d19e7908d19bd194493aThomas Graf * The reference to the callback handler is taken into account
1331155370f520cb64657e25153255cf7dc1424317fThomas Graf * automatically, it is released again upon calling nl_socket_free().
13444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf *@return Newly allocted socket handle or NULL.
13644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1371155370f520cb64657e25153255cf7dc1424317fThomas Grafstruct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
13844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
13944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (cb == NULL)
14044d362409d5469aed47d19e7908d19bd194493aThomas Graf		BUG();
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1421155370f520cb64657e25153255cf7dc1424317fThomas Graf	return __alloc_socket(nl_cb_get(cb));
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1461155370f520cb64657e25153255cf7dc1424317fThomas Graf * Free a netlink socket.
1471155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1491155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid nl_socket_free(struct nl_sock *sk)
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1511155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (!sk)
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return;
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf
1541155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_fd >= 0)
1551155370f520cb64657e25153255cf7dc1424317fThomas Graf		close(sk->s_fd);
15691c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
1571155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (!(sk->s_flags & NL_OWN_PORT))
1581155370f520cb64657e25153255cf7dc1424317fThomas Graf		release_local_port(sk->s_local.nl_pid);
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf
1601155370f520cb64657e25153255cf7dc1424317fThomas Graf	nl_cb_put(sk->s_cb);
1611155370f520cb64657e25153255cf7dc1424317fThomas Graf	free(sk);
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
16344d362409d5469aed47d19e7908d19bd194493aThomas Graf
16444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Sequence Numbers
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
16944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf
17144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int noop_seq_check(struct nl_msg *msg, void *arg)
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_OK;
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Disable sequence number checking.
1791155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
18044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1811155370f520cb64657e25153255cf7dc1424317fThomas Graf * Disables checking of sequence numbers on the netlink socket This is
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf * required to allow messages to be processed which were not requested by
18344d362409d5469aed47d19e7908d19bd194493aThomas Graf * a preceding request message, e.g. netlink events.
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note This function modifies the NL_CB_SEQ_CHECK configuration in
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf * the callback handle associated with the socket.
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
188724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Grafvoid nl_socket_disable_seq_check(struct nl_sock *sk)
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1901155370f520cb64657e25153255cf7dc1424317fThomas Graf	nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf		  NL_CB_CUSTOM, noop_seq_check, NULL);
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Use next sequence number
1961155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
19844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Uses the next available sequence number and increases the counter
19944d362409d5469aed47d19e7908d19bd194493aThomas Graf * by one for subsequent calls.
20044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
20144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Unique serial sequence number
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
2031155370f520cb64657e25153255cf7dc1424317fThomas Grafunsigned int nl_socket_use_seq(struct nl_sock *sk)
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
2051155370f520cb64657e25153255cf7dc1424317fThomas Graf	return sk->s_seq_next++;
20644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
20744d362409d5469aed47d19e7908d19bd194493aThomas Graf
2082bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf/**
2092bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * Disable automatic request for ACK
2102bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * @arg sk		Netlink socket.
2112bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf *
2122bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * The default behaviour of a socket is to request an ACK for
2132bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * each message sent to allow for the caller to synchronize to
2142bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * the completion of the netlink operation. This function
2152bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * disables this behaviour and will result in requests being
2162bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * sent which will not have the NLM_F_ACK flag set automatically.
2172bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * However, it is still possible for the caller to set the
2182bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * NLM_F_ACK flag explicitely.
2192bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf */
2202bdee95a765457fe4206b89d51974ae56e75c588Thomas Grafvoid nl_socket_disable_auto_ack(struct nl_sock *sk)
2212bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf{
2222bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf	sk->s_flags |= NL_NO_AUTO_ACK;
2232bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf}
2242bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf
2252bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf/**
2262bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * Enable automatic request for ACK (default)
2272bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * @arg sk		Netlink socket.
2282bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf * @see nl_socket_disable_auto_ack
2292bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf */
2302bdee95a765457fe4206b89d51974ae56e75c588Thomas Grafvoid nl_socket_enable_auto_ack(struct nl_sock *sk)
2312bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf{
2322bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf	sk->s_flags &= ~NL_NO_AUTO_ACK;
2332bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf}
2342bdee95a765457fe4206b89d51974ae56e75c588Thomas Graf
23544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
23644d362409d5469aed47d19e7908d19bd194493aThomas Graf
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
23844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Source Idenficiation
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
24044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
24144d362409d5469aed47d19e7908d19bd194493aThomas Graf
2421155370f520cb64657e25153255cf7dc1424317fThomas Grafuint32_t nl_socket_get_local_port(struct nl_sock *sk)
24344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
2441155370f520cb64657e25153255cf7dc1424317fThomas Graf	return sk->s_local.nl_pid;
24544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
24644d362409d5469aed47d19e7908d19bd194493aThomas Graf
24744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
24844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set local port of socket
2491155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
25044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg port		Local port identifier
25144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
25244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Assigns a local port identifier to the socket. If port is 0
25344d362409d5469aed47d19e7908d19bd194493aThomas Graf * a unique port identifier will be generated automatically.
25444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
2551155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
25644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
25744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (port == 0) {
25844d362409d5469aed47d19e7908d19bd194493aThomas Graf		port = generate_local_port();
2591155370f520cb64657e25153255cf7dc1424317fThomas Graf		sk->s_flags &= ~NL_OWN_PORT;
26044d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else  {
2611155370f520cb64657e25153255cf7dc1424317fThomas Graf		if (!(sk->s_flags & NL_OWN_PORT))
2621155370f520cb64657e25153255cf7dc1424317fThomas Graf			release_local_port(sk->s_local.nl_pid);
2631155370f520cb64657e25153255cf7dc1424317fThomas Graf		sk->s_flags |= NL_OWN_PORT;
26444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
26544d362409d5469aed47d19e7908d19bd194493aThomas Graf
2661155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_local.nl_pid = port;
26744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
26844d362409d5469aed47d19e7908d19bd194493aThomas Graf
26944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
27044d362409d5469aed47d19e7908d19bd194493aThomas Graf
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Group Subscriptions
27344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
27444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf
27644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
27772aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * Join groups
2781155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket
27944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg group		Group identifier
28044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
28172aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * Joins the specified groups using the modern socket option which
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf * is available since kernel version 2.6.14. It allows joining an
28372aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * almost arbitary number of groups without limitation.  The list
28472aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * of groups has to be terminated by 0 (%NFNLGRP_NONE).
28544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Make sure to use the correct group definitions as the older
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf * bitmask definitions for nl_join_groups() are likely to still
28844d362409d5469aed47d19e7908d19bd194493aThomas Graf * be present for backward compatibility reasons.
28944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error code.
29144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
29272aa861c48b6876e94d07470025155a6924a6983Holger Eitzenbergerint nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
29344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
29572aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	va_list ap;
29644d362409d5469aed47d19e7908d19bd194493aThomas Graf
2971155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_fd == -1)
2988a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_BAD_SOCK;
29991c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
30072aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	va_start(ap, group);
30172aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
30272aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	while (group != 0) {
30372aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		if (group < 0)
30472aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger			return -NLE_INVAL;
30572aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
30672aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
30772aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger						 &group, sizeof(group));
30872aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		if (err < 0)
30972aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger			return -nl_syserr2nlerr(errno);
31072aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
31172aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		group = va_arg(ap, int);
31272aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	}
31372aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
31472aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	va_end(ap);
31544d362409d5469aed47d19e7908d19bd194493aThomas Graf
31644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
31744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
31844d362409d5469aed47d19e7908d19bd194493aThomas Graf
319724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Grafint nl_socket_add_membership(struct nl_sock *sk, int group)
320724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf{
321724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf	return nl_socket_add_memberships(sk, group, 0);
322724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf}
323724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf
32444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
32572aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * Leave groups
3261155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket
32744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg group		Group identifier
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
32972aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * Leaves the specified groups using the modern socket option
33072aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * which is available since kernel version 2.6.14. The list of groups
33172aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger * has to terminated by 0 (%NFNLGRP_NONE).
33244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
33344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @see nl_socket_add_membership
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code.
33544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
33672aa861c48b6876e94d07470025155a6924a6983Holger Eitzenbergerint nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
33744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
33844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
33972aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	va_list ap;
34044d362409d5469aed47d19e7908d19bd194493aThomas Graf
3411155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_fd == -1)
3428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_BAD_SOCK;
34391c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
34472aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	va_start(ap, group);
34572aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
34672aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	while (group != 0) {
34772aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		if (group < 0)
34872aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger			return -NLE_INVAL;
34972aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
35072aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
35172aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger						 &group, sizeof(group));
35272aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		if (err < 0)
35372aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger			return -nl_syserr2nlerr(errno);
35472aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
35572aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger		group = va_arg(ap, int);
35672aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	}
35772aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger
35872aa861c48b6876e94d07470025155a6924a6983Holger Eitzenberger	va_end(ap);
35944d362409d5469aed47d19e7908d19bd194493aThomas Graf
36044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
36144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
36244d362409d5469aed47d19e7908d19bd194493aThomas Graf
363724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Grafint nl_socket_drop_membership(struct nl_sock *sk, int group)
364724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf{
365724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf	return nl_socket_drop_memberships(sk, group, 0);
366724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf}
367724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf
368724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Graf
36944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
37044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Join multicast groups (deprecated)
3711155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
37244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg groups		Bitmask of groups to join.
37344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
37444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This function defines the old way of joining multicast group which
37544d362409d5469aed47d19e7908d19bd194493aThomas Graf * has to be done prior to calling nl_connect(). It works on any kernel
37644d362409d5469aed47d19e7908d19bd194493aThomas Graf * version but is very limited as only 32 groups can be joined.
37744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
3781155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid nl_join_groups(struct nl_sock *sk, int groups)
37944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
3801155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_local.nl_groups |= groups;
38144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
38244d362409d5469aed47d19e7908d19bd194493aThomas Graf
38344d362409d5469aed47d19e7908d19bd194493aThomas Graf
38444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
38544d362409d5469aed47d19e7908d19bd194493aThomas Graf
38644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
38744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Peer Identfication
38844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
38944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
39044d362409d5469aed47d19e7908d19bd194493aThomas Graf
3911155370f520cb64657e25153255cf7dc1424317fThomas Grafuint32_t nl_socket_get_peer_port(struct nl_sock *sk)
39244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
3931155370f520cb64657e25153255cf7dc1424317fThomas Graf	return sk->s_peer.nl_pid;
39444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
39544d362409d5469aed47d19e7908d19bd194493aThomas Graf
3961155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
39744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
3981155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_peer.nl_pid = port;
39944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
40044d362409d5469aed47d19e7908d19bd194493aThomas Graf
40144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
40244d362409d5469aed47d19e7908d19bd194493aThomas Graf
40344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
40444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name File Descriptor
40544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
40644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
40744d362409d5469aed47d19e7908d19bd194493aThomas Graf
4081155370f520cb64657e25153255cf7dc1424317fThomas Grafint nl_socket_get_fd(struct nl_sock *sk)
40944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4101155370f520cb64657e25153255cf7dc1424317fThomas Graf	return sk->s_fd;
41144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
41244d362409d5469aed47d19e7908d19bd194493aThomas Graf
41344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
4141155370f520cb64657e25153255cf7dc1424317fThomas Graf * Set file descriptor of socket to non-blocking state
4151155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
41644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
41744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code.
41844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
4191155370f520cb64657e25153255cf7dc1424317fThomas Grafint nl_socket_set_nonblocking(struct nl_sock *sk)
42044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4211155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_fd == -1)
4228a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_BAD_SOCK;
42391c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
4241155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
4258a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -nl_syserr2nlerr(errno);
42644d362409d5469aed47d19e7908d19bd194493aThomas Graf
42744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
42844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
42944d362409d5469aed47d19e7908d19bd194493aThomas Graf
43044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
43144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Enable use of MSG_PEEK when reading from socket
4321155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
43344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
4341155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid nl_socket_enable_msg_peek(struct nl_sock *sk)
43544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4361155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_flags |= NL_MSG_PEEK;
43744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
43844d362409d5469aed47d19e7908d19bd194493aThomas Graf
43944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
44044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Disable use of MSG_PEEK when reading from socket
4411155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
44244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
4431155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid nl_socket_disable_msg_peek(struct nl_sock *sk)
44444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4451155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_flags &= ~NL_MSG_PEEK;
44644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
44744d362409d5469aed47d19e7908d19bd194493aThomas Graf
44844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
44944d362409d5469aed47d19e7908d19bd194493aThomas Graf
45044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
45144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Callback Handler
45244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
45344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
45444d362409d5469aed47d19e7908d19bd194493aThomas Graf
4551155370f520cb64657e25153255cf7dc1424317fThomas Grafstruct nl_cb *nl_socket_get_cb(struct nl_sock *sk)
45644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4571155370f520cb64657e25153255cf7dc1424317fThomas Graf	return nl_cb_get(sk->s_cb);
45844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
45944d362409d5469aed47d19e7908d19bd194493aThomas Graf
4601155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
46144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4621155370f520cb64657e25153255cf7dc1424317fThomas Graf	nl_cb_put(sk->s_cb);
4631155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_cb = nl_cb_get(cb);
46444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
46544d362409d5469aed47d19e7908d19bd194493aThomas Graf
46644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
46744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Modify the callback handler associated to the socket
4681155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
46944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type		which type callback to set
47044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg kind		kind of callback
47144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg func		callback function
47244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg		argument to be passwd to callback function
47344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
47444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @see nl_cb_set
47544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
4761155370f520cb64657e25153255cf7dc1424317fThomas Grafint nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
47744d362409d5469aed47d19e7908d19bd194493aThomas Graf			enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
47844d362409d5469aed47d19e7908d19bd194493aThomas Graf			void *arg)
47944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4801155370f520cb64657e25153255cf7dc1424317fThomas Graf	return nl_cb_set(sk->s_cb, type, kind, func, arg);
48144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
48244d362409d5469aed47d19e7908d19bd194493aThomas Graf
48344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
48444d362409d5469aed47d19e7908d19bd194493aThomas Graf
48544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
48644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Utilities
48744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
48844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
48944d362409d5469aed47d19e7908d19bd194493aThomas Graf
49044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
4911155370f520cb64657e25153255cf7dc1424317fThomas Graf * Set socket buffer size of netlink socket.
4921155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
49344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rxbuf		New receive socket buffer size in bytes.
49444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg txbuf		New transmit socket buffer size in bytes.
49544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
4961155370f520cb64657e25153255cf7dc1424317fThomas Graf * Sets the socket buffer size of a netlink socket to the specified
49744d362409d5469aed47d19e7908d19bd194493aThomas Graf * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
49844d362409d5469aed47d19e7908d19bd194493aThomas Graf * good default value.
49944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
50044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note It is not required to call this function prior to nl_connect().
50144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error code.
50244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
503724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Grafint nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
50444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
50544d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
50644d362409d5469aed47d19e7908d19bd194493aThomas Graf
50744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (rxbuf <= 0)
50844d362409d5469aed47d19e7908d19bd194493aThomas Graf		rxbuf = 32768;
50944d362409d5469aed47d19e7908d19bd194493aThomas Graf
51044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (txbuf <= 0)
51144d362409d5469aed47d19e7908d19bd194493aThomas Graf		txbuf = 32768;
51291c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
5131155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_fd == -1)
5148a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_BAD_SOCK;
51544d362409d5469aed47d19e7908d19bd194493aThomas Graf
5161155370f520cb64657e25153255cf7dc1424317fThomas Graf	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
51744d362409d5469aed47d19e7908d19bd194493aThomas Graf			 &txbuf, sizeof(txbuf));
51844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
5198a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -nl_syserr2nlerr(errno);
52044d362409d5469aed47d19e7908d19bd194493aThomas Graf
5211155370f520cb64657e25153255cf7dc1424317fThomas Graf	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
52244d362409d5469aed47d19e7908d19bd194493aThomas Graf			 &rxbuf, sizeof(rxbuf));
52344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
5248a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -nl_syserr2nlerr(errno);
52544d362409d5469aed47d19e7908d19bd194493aThomas Graf
5261155370f520cb64657e25153255cf7dc1424317fThomas Graf	sk->s_flags |= NL_SOCK_BUFSIZE_SET;
52744d362409d5469aed47d19e7908d19bd194493aThomas Graf
52844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
52944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
53044d362409d5469aed47d19e7908d19bd194493aThomas Graf
53144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
5321155370f520cb64657e25153255cf7dc1424317fThomas Graf * Enable/disable credential passing on netlink socket.
5331155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
53444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg state		New state (0 - disabled, 1 - enabled)
53544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
53644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code
53744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
538724dfa6d70943e0d4e3c8e54bff43050828a64d0Thomas Grafint nl_socket_set_passcred(struct nl_sock *sk, int state)
53944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
54044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
54144d362409d5469aed47d19e7908d19bd194493aThomas Graf
5421155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_fd == -1)
5438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_BAD_SOCK;
54491c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
5451155370f520cb64657e25153255cf7dc1424317fThomas Graf	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
54644d362409d5469aed47d19e7908d19bd194493aThomas Graf			 &state, sizeof(state));
54744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
5488a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -nl_syserr2nlerr(errno);
54944d362409d5469aed47d19e7908d19bd194493aThomas Graf
55044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (state)
5511155370f520cb64657e25153255cf7dc1424317fThomas Graf		sk->s_flags |= NL_SOCK_PASSCRED;
55244d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
5531155370f520cb64657e25153255cf7dc1424317fThomas Graf		sk->s_flags &= ~NL_SOCK_PASSCRED;
55444d362409d5469aed47d19e7908d19bd194493aThomas Graf
55544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
55644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
55744d362409d5469aed47d19e7908d19bd194493aThomas Graf
55844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
55944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Enable/disable receival of additional packet information
5601155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
56144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg state		New state (0 - disabled, 1 - enabled)
56244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
56344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code
56444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
5651155370f520cb64657e25153255cf7dc1424317fThomas Grafint nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
56644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
56744d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
56844d362409d5469aed47d19e7908d19bd194493aThomas Graf
5691155370f520cb64657e25153255cf7dc1424317fThomas Graf	if (sk->s_fd == -1)
5708a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_BAD_SOCK;
57191c330aae51cd6cd44ad730e10dc82724998c810Thomas Graf
5721155370f520cb64657e25153255cf7dc1424317fThomas Graf	err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
57344d362409d5469aed47d19e7908d19bd194493aThomas Graf			 &state, sizeof(state));
57444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
5758a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -nl_syserr2nlerr(errno);
57644d362409d5469aed47d19e7908d19bd194493aThomas Graf
57744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
57844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
57944d362409d5469aed47d19e7908d19bd194493aThomas Graf
58044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
58144d362409d5469aed47d19e7908d19bd194493aThomas Graf
58244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
583