libnl 3.10.0
nfnl.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
4 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
5 * Copyright (c) 2007 Secure Computing Corporation
6 */
7
8/**
9 * @defgroup nfnl Netfilter Library (libnl-nf)
10 *
11 * @par Message Format
12 * @code
13 * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
14 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
15 * | Header | Pad | Payload | Pad |
16 * | struct nlmsghdr | | | |
17 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
18 * @endcode
19 * @code
20 * <-------- NFNL_HDRLEN --------->
21 * +--------------------------+- - -+------------+
22 * | Netfilter Netlink Header | Pad | Attributes |
23 * | struct nfgenmsg | | |
24 * +--------------------------+- - -+------------+
25 * nfnlmsg_attrdata(nfg, hdrlen)-----^
26 * @endcode
27 *
28 * @par 1) Creating a new netfilter netlink message
29 * @code
30 * struct nl_msg *msg;
31 *
32 * // Create a new empty netlink message
33 * msg = nlmsg_alloc();
34 *
35 * // Append the netlink and netfilter netlink message header
36 * hdr = nfnlmsg_put(msg, PID, SEQ, SUBSYS, TYPE, NLM_F_ECHO,
37 * FAMILY, RES_ID);
38 *
39 * // Append the attributes.
40 * nla_put_u32(msg, 1, 0x10);
41 *
42 * // Message is ready to be sent.
43 * nl_send_auto_complete(sk, msg);
44 *
45 * // All done? Free the message.
46 * nlmsg_free(msg);
47 * @endcode
48 *
49 * @par 2) Sending of trivial messages
50 * @code
51 * // For trivial messages not requiring any subsys specific header or
52 * // attributes, nfnl_send_simple() may be used to send messages directly.
53 * nfnl_send_simple(sk, SUBSYS, TYPE, 0, FAMILY, RES_ID);
54 * @endcode
55 * @{
56 */
57
58#include "nl-default.h"
59
60#include <linux/netfilter/nfnetlink.h>
61
62#include <netlink/netlink.h>
63#include <netlink/netfilter/nfnl.h>
64#include <netlink/data.h>
65#include <netlink/msg.h>
66
67#include "nl-aux-core/nl-core.h"
68
69/**
70 * @name Socket Creating
71 * @{
72 */
73
74/**
75 * Create and connect netfilter netlink socket.
76 * @arg sk Netlink socket.
77 *
78 * Creates a NETLINK_NETFILTER netlink socket, binds the socket and
79 * issues a connection attempt.
80 *
81 * @see nl_connect()
82 *
83 * @return 0 on success or a negative error code.
84 */
85int nfnl_connect(struct nl_sock *sk)
86{
87 return nl_connect(sk, NETLINK_NETFILTER);
88}
89
90/** @} */
91
92/**
93 * @name Sending
94 * @{
95 */
96
97/**
98 * Send trivial netfilter netlink message
99 * @arg sk Netlink socket.
100 * @arg subsys_id nfnetlink subsystem
101 * @arg type nfnetlink message type
102 * @arg flags message flags
103 * @arg family nfnetlink address family
104 * @arg res_id nfnetlink resource id
105 *
106 * @return 0 on success or a negative error code. Due to a bug, this function
107 * returns the number of bytes sent. Treat any non-negative number as success.
108 */
109int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type,
110 int flags, uint8_t family, uint16_t res_id)
111{
112 struct nfgenmsg hdr = {
113 .nfgen_family = family,
114 .version = NFNETLINK_V0,
115 .res_id = htons(res_id),
116 };
117
118 return nl_send_simple(sk, NFNLMSG_TYPE(subsys_id, type), flags,
119 &hdr, sizeof(hdr));
120}
121
122/** @} */
123
124/**
125 * @name Message Parsing
126 * @{
127 */
128
129/**
130 * Get netfilter subsystem id from message
131 * @arg nlh netlink messsage header
132 */
133uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh)
134{
135 return NFNL_SUBSYS_ID(nlh->nlmsg_type);
136}
137
138/**
139 * Get netfilter message type from message
140 * @arg nlh netlink messsage header
141 */
142uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
143{
144 return NFNL_MSG_TYPE(nlh->nlmsg_type);
145}
146
147/**
148 * Get netfilter family from message
149 * @arg nlh netlink messsage header
150 */
151uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
152{
153 struct nfgenmsg *nfg = nlmsg_data(nlh);
154
155 return nfg->nfgen_family;
156}
157
158/**
159 * Get netfilter resource id from message
160 * @arg nlh netlink messsage header
161 */
162uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh)
163{
164 struct nfgenmsg *nfg = nlmsg_data(nlh);
165
166 return ntohs(nfg->res_id);
167}
168
169/** @} */
170
171/**
172 * @name Message Building
173 * @{
174 */
175
176static int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id)
177{
178 struct nfgenmsg *nfg;
179
180 nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO);
181 if (nfg == NULL)
182 return -NLE_NOMEM;
183
184 nfg->nfgen_family = family;
185 nfg->version = NFNETLINK_V0;
186 nfg->res_id = htons(res_id);
187 NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n",
188 msg, family, res_id);
189 return 0;
190}
191
192/**
193 * Allocate a new netfilter netlink message
194 * @arg subsys_id nfnetlink subsystem
195 * @arg type nfnetlink message type
196 * @arg flags message flags
197 * @arg family nfnetlink address family
198 * @arg res_id nfnetlink resource id
199 *
200 * @return Newly allocated netlink message or NULL.
201 */
202struct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags,
203 uint8_t family, uint16_t res_id)
204{
205 struct nl_msg *msg;
206
207 msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags);
208 if (msg == NULL)
209 return NULL;
210
211 if (nfnlmsg_append(msg, family, res_id) < 0)
212 goto nla_put_failure;
213
214 return msg;
215
216nla_put_failure:
217 nlmsg_free(msg);
218 return NULL;
219}
220
221/**
222 * Add netlink and netfilter netlink headers to netlink message
223 * @arg msg netlink message
224 * @arg pid netlink process id
225 * @arg seq sequence number of message
226 * @arg subsys_id nfnetlink subsystem
227 * @arg type nfnetlink message type
228 * @arg flags message flags
229 * @arg family nfnetlink address family
230 * @arg res_id nfnetlink resource id
231 */
232int nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq,
233 uint8_t subsys_id, uint8_t type, int flags, uint8_t family,
234 uint16_t res_id)
235{
236 struct nlmsghdr *nlh;
237
238 nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags);
239 if (nlh == NULL)
240 return -NLE_MSGSIZE;
241
242 return nfnlmsg_append(msg, family, res_id);
243}
244
245/** @} */
246
247/** @} */
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition msg.c:352
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition msg.c:108
void * nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
Reserve room for additional data in a netlink message.
Definition msg.c:418
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition msg.c:572
struct nlmsghdr * nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags)
Add a netlink message header to a netlink message.
Definition msg.c:517
uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh)
Get netfilter resource id from message.
Definition nfnl.c:162
uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh)
Get netfilter subsystem id from message.
Definition nfnl.c:133
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
Definition nfnl.c:151
int nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Add netlink and netfilter netlink headers to netlink message.
Definition nfnl.c:232
int nfnl_connect(struct nl_sock *sk)
Create and connect netfilter netlink socket.
Definition nfnl.c:85
int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Send trivial netfilter netlink message.
Definition nfnl.c:109
uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
Get netfilter message type from message.
Definition nfnl.c:142
struct nl_msg * nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Allocate a new netfilter netlink message.
Definition nfnl.c:202
int nl_connect(struct nl_sock *sk, int protocol)
Create file descriptor and bind socket.
Definition nl.c:102
int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, size_t size)
Construct and transmit a Netlink message.
Definition nl.c:579