libnl  3.7.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 <netlink-private/netlink.h>
59 #include <netlink/netlink.h>
60 #include <netlink/netfilter/nfnl.h>
61 
62 #include <linux/netfilter/nfnetlink.h>
63 
64 /**
65  * @name Socket Creating
66  * @{
67  */
68 
69 /**
70  * Create and connect netfilter netlink socket.
71  * @arg sk Netlink socket.
72  *
73  * Creates a NETLINK_NETFILTER netlink socket, binds the socket and
74  * issues a connection attempt.
75  *
76  * @see nl_connect()
77  *
78  * @return 0 on success or a negative error code.
79  */
80 int nfnl_connect(struct nl_sock *sk)
81 {
82  return nl_connect(sk, NETLINK_NETFILTER);
83 }
84 
85 /** @} */
86 
87 /**
88  * @name Sending
89  * @{
90  */
91 
92 /**
93  * Send trivial netfilter netlink message
94  * @arg sk Netlink socket.
95  * @arg subsys_id nfnetlink subsystem
96  * @arg type nfnetlink message type
97  * @arg flags message flags
98  * @arg family nfnetlink address family
99  * @arg res_id nfnetlink resource id
100  *
101  * @return 0 on success or a negative error code. Due to a bug, this function
102  * returns the number of bytes sent. Treat any non-negative number as success.
103  */
104 int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type,
105  int flags, uint8_t family, uint16_t res_id)
106 {
107  struct nfgenmsg hdr = {
108  .nfgen_family = family,
109  .version = NFNETLINK_V0,
110  .res_id = htons(res_id),
111  };
112 
113  return nl_send_simple(sk, NFNLMSG_TYPE(subsys_id, type), flags,
114  &hdr, sizeof(hdr));
115 }
116 
117 /** @} */
118 
119 /**
120  * @name Message Parsing
121  * @{
122  */
123 
124 /**
125  * Get netfilter subsystem id from message
126  * @arg nlh netlink messsage header
127  */
128 uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh)
129 {
130  return NFNL_SUBSYS_ID(nlh->nlmsg_type);
131 }
132 
133 /**
134  * Get netfilter message type from message
135  * @arg nlh netlink messsage header
136  */
137 uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
138 {
139  return NFNL_MSG_TYPE(nlh->nlmsg_type);
140 }
141 
142 /**
143  * Get netfilter family from message
144  * @arg nlh netlink messsage header
145  */
146 uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
147 {
148  struct nfgenmsg *nfg = nlmsg_data(nlh);
149 
150  return nfg->nfgen_family;
151 }
152 
153 /**
154  * Get netfilter resource id from message
155  * @arg nlh netlink messsage header
156  */
157 uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh)
158 {
159  struct nfgenmsg *nfg = nlmsg_data(nlh);
160 
161  return ntohs(nfg->res_id);
162 }
163 
164 /** @} */
165 
166 /**
167  * @name Message Building
168  * @{
169  */
170 
171 static int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id)
172 {
173  struct nfgenmsg *nfg;
174 
175  nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO);
176  if (nfg == NULL)
177  return -NLE_NOMEM;
178 
179  nfg->nfgen_family = family;
180  nfg->version = NFNETLINK_V0;
181  nfg->res_id = htons(res_id);
182  NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n",
183  msg, family, res_id);
184  return 0;
185 }
186 
187 /**
188  * Allocate a new netfilter netlink message
189  * @arg subsys_id nfnetlink subsystem
190  * @arg type nfnetlink message type
191  * @arg flags message flags
192  * @arg family nfnetlink address family
193  * @arg res_id nfnetlink resource id
194  *
195  * @return Newly allocated netlink message or NULL.
196  */
197 struct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags,
198  uint8_t family, uint16_t res_id)
199 {
200  struct nl_msg *msg;
201 
202  msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags);
203  if (msg == NULL)
204  return NULL;
205 
206  if (nfnlmsg_append(msg, family, res_id) < 0)
207  goto nla_put_failure;
208 
209  return msg;
210 
211 nla_put_failure:
212  nlmsg_free(msg);
213  return NULL;
214 }
215 
216 /**
217  * Add netlink and netfilter netlink headers to netlink message
218  * @arg msg netlink message
219  * @arg pid netlink process id
220  * @arg seq sequence number of message
221  * @arg subsys_id nfnetlink subsystem
222  * @arg type nfnetlink message type
223  * @arg flags message flags
224  * @arg family nfnetlink address family
225  * @arg res_id nfnetlink resource id
226  */
227 int nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq,
228  uint8_t subsys_id, uint8_t type, int flags, uint8_t family,
229  uint16_t res_id)
230 {
231  struct nlmsghdr *nlh;
232 
233  nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags);
234  if (nlh == NULL)
235  return -NLE_MSGSIZE;
236 
237  return nfnlmsg_append(msg, family, res_id);
238 }
239 
240 /** @} */
241 
242 /** @} */
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:503
void * nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
Reserve room for additional data in a netlink message.
Definition: msg.c:404
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:341
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:558
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition: msg.c:100
uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh)
Get netfilter resource id from message.
Definition: nfnl.c:157
uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh)
Get netfilter subsystem id from message.
Definition: nfnl.c:128
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
Definition: nfnl.c:146
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:227
int nfnl_connect(struct nl_sock *sk)
Create and connect netfilter netlink socket.
Definition: nfnl.c:80
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:104
uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
Get netfilter message type from message.
Definition: nfnl.c:137
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:197
int nl_connect(struct nl_sock *sk, int protocol)
Create file descriptor and bind socket.
Definition: nl.c:97
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:574