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