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