libnl  1.1
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-2006 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  * @ingroup nlfam
16  * @defgroup nfnl Netfilter Netlink
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(nl_handle, 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(nl_handle, SUBSYS, TYPE, 0, FAMILY, RES_ID);
61  * @endcode
62  * @{
63  */
64 
65 #include <netlink-local.h>
66 #include <netlink/netlink.h>
67 #include <netlink/netfilter/nfnl.h>
68 
69 /**
70  * @name Socket Creating
71  * @{
72  */
73 
74 /**
75  * Create and connect netfilter netlink socket.
76  * @arg handle Netlink handle.
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  */
85 int nfnl_connect(struct nl_handle *handle)
86 {
87  return nl_connect(handle, NETLINK_NETFILTER);
88 }
89 
90 /** @} */
91 
92 /**
93  * @name Sending
94  * @{
95  */
96 
97 /**
98  * Send trivial netfilter netlink message
99  * @arg handle Netlink handle.
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 Newly allocated netlink message or NULL.
107  */
108 int nfnl_send_simple(struct nl_handle *handle, 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(handle, 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 nl_errno(ENOMEM);
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 nl_get_errno();
240 
241  return nfnlmsg_append(msg, family, res_id);
242 }
243 
244 /** @} */
245 
246 /** @} */