• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
nfnl_connect(struct nl_sock * sk)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  */
nfnl_send_simple(struct nl_sock * sk,uint8_t subsys_id,uint8_t type,int flags,uint8_t family,uint16_t res_id)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  */
nfnlmsg_subsys(struct nlmsghdr * nlh)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  */
nfnlmsg_subtype(struct nlmsghdr * nlh)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  */
nfnlmsg_family(struct nlmsghdr * nlh)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  */
nfnlmsg_res_id(struct nlmsghdr * nlh)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 
nfnlmsg_append(struct nl_msg * msg,uint8_t family,uint16_t res_id)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  */
nfnlmsg_alloc_simple(uint8_t subsys_id,uint8_t type,int flags,uint8_t family,uint16_t res_id)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  */
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)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 /** @} */
243