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