libnl: /data/src/libnl3/lib/route/link/inet.c Source File

libnl 3.10.0

inet.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup link_API
8 * @defgroup link_inet IPv4 Link Module
9 * @brief Implementation of IPv4 specific link attributes
10 *
11 *
12 *
13 * @par Example: Reading the value of IPV4_DEVCONF_FORWARDING
14 * @code
15 * struct nl_cache *cache;
16 * struct rtnl_link *link;
17 * uint32_t value;
18 *
19 * // Allocate a link cache
20 * rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache);
21 *
22 * // Search for the link we wish to see the value from
23 * link = rtnl_link_get_by_name(cache, "eth0");
24 *
25 * // Read the value of the setting IPV4_DEVCONF_FORWARDING
26 * if (rtnl_link_inet_get_conf(link, IPV4_DEVCONF_FORWARDING, &value) < 0)
27 * // Error: Unable to read config setting
28 *
29 * printf("forwarding is %s\n", value ? "enabled" : "disabled");
30 * @endcode
31 *
32 * @par Example: Changing the value of IPV4_DEVCONF_FOWARDING
33 * @code
34 * //
35 * // ... Continueing from the previous example ...
36 * //
37 *
38 * struct rtnl_link *new;
39 *
40 * // Allocate a new link to store the changes we wish to make.
41 * new = rtnl_link_alloc();
42 *
43 * // Set IPV4_DEVCONF_FORWARDING to '1'
44 * rtnl_link_inet_set_conf(new, IPV4_DEVCONF_FORWARDING, 1);
45 *
46 * // Send the change request to the kernel.
47 * rtnl_link_change(sock, link, new, 0);
48 * @endcode
49 *
50 * @{
51 */
52
53
54#include "nl-default.h"
55
56#include <linux/ip.h>
57
58#include <netlink/netlink.h>
59#include <netlink/attr.h>
60#include <netlink/route/rtnl.h>
61#include <netlink/route/link/inet.h>
62
63#include "link-api.h"
64
65/** @cond SKIP */
66struct inet_data
67{
68 uint8_t i_confset[IPV4_DEVCONF_MAX];
69 uint32_t i_conf[IPV4_DEVCONF_MAX];
70};
71/** @endcond */
72
73static void *inet_alloc(struct rtnl_link *link)
74{
75 return calloc(1, sizeof(struct inet_data));
76}
77
78static void *inet_clone(struct rtnl_link *link, void *data)
79{
80 struct inet_data *id;
81
82 if ((id = inet_alloc(link)))
83 memcpy(id, data, sizeof(*id));
84
85 return id;
86}
87
88static void inet_free(struct rtnl_link *link, void *data)
89{
90 free(data);
91}
92
93static struct nla_policy inet_policy[IFLA_INET_MAX+1] = {
94 [IFLA_INET_CONF] = { .minlen = 4 },
95};
96
97static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data)
98{
99 struct inet_data *id = data;
100 struct nlattr *tb[IFLA_INET_MAX+1];
101 int err;
102
103 err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy);
104 if (err < 0)
105 return err;
106 if (tb[IFLA_INET_CONF] && nla_len(tb[IFLA_INET_CONF]) % 4)
107 return -EINVAL;
108
109 if (tb[IFLA_INET_CONF]) {
110 int i;
111 int len = _NL_MIN(IPV4_DEVCONF_MAX, nla_len(tb[IFLA_INET_CONF]) / 4);
112
113 for (i = 0; i < len; i++)
114 id->i_confset[i] = 1;
115 nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf));
116 }
117
118 return 0;
119}
120
121static int inet_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data)
122{
123 struct inet_data *id = data;
124 struct nlattr *nla;
125 int i;
126
127 if (!(nla = nla_nest_start(msg, IFLA_INET_CONF)))
128 return -NLE_MSGSIZE;
129
130 for (i = 0; i < IPV4_DEVCONF_MAX; i++)
131 if (id->i_confset[i])
132 NLA_PUT_U32(msg, i+1, id->i_conf[i]);
133
134 nla_nest_end(msg, nla);
135
136 return 0;
137
138nla_put_failure:
139 return -NLE_MSGSIZE;
140}
141
142static const struct trans_tbl inet_devconf[] = {
143 __ADD(IPV4_DEVCONF_FORWARDING, forwarding),
144 __ADD(IPV4_DEVCONF_MC_FORWARDING, mc_forwarding),
145 __ADD(IPV4_DEVCONF_PROXY_ARP, proxy_arp),
146 __ADD(IPV4_DEVCONF_ACCEPT_REDIRECTS, accept_redirects),
147 __ADD(IPV4_DEVCONF_SECURE_REDIRECTS, secure_redirects),
148 __ADD(IPV4_DEVCONF_SEND_REDIRECTS, send_redirects),
149 __ADD(IPV4_DEVCONF_SHARED_MEDIA, shared_media),
150 __ADD(IPV4_DEVCONF_RP_FILTER, rp_filter),
151 __ADD(IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route),
152 __ADD(IPV4_DEVCONF_BOOTP_RELAY, bootp_relay),
153 __ADD(IPV4_DEVCONF_LOG_MARTIANS, log_martians),
154 __ADD(IPV4_DEVCONF_TAG, tag),
155 __ADD(IPV4_DEVCONF_ARPFILTER, arpfilter),
156 __ADD(IPV4_DEVCONF_MEDIUM_ID, medium_id),
157 __ADD(IPV4_DEVCONF_NOXFRM, noxfrm),
158 __ADD(IPV4_DEVCONF_NOPOLICY, nopolicy),
159 __ADD(IPV4_DEVCONF_FORCE_IGMP_VERSION, force_igmp_version),
160 __ADD(IPV4_DEVCONF_ARP_ANNOUNCE, arp_announce),
161 __ADD(IPV4_DEVCONF_ARP_IGNORE, arp_ignore),
162 __ADD(IPV4_DEVCONF_PROMOTE_SECONDARIES, promote_secondaries),
163 __ADD(IPV4_DEVCONF_ARP_ACCEPT, arp_accept),
164 __ADD(IPV4_DEVCONF_ARP_NOTIFY, arp_notify),
165 __ADD(IPV4_DEVCONF_ACCEPT_LOCAL, accept_local),
166 __ADD(IPV4_DEVCONF_SRC_VMARK, src_vmark),
167 __ADD(IPV4_DEVCONF_PROXY_ARP_PVLAN, proxy_arp_pvlan),
168 __ADD(IPV4_DEVCONF_ROUTE_LOCALNET, route_localnet),
169 __ADD(IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL, igmpv2_unsolicited_report_interval),
170 __ADD(IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL, igmpv3_unsolicited_report_interval),
171};
172
173const char *rtnl_link_inet_devconf2str(int type, char *buf, size_t len)
174{
175 return __type2str(type, buf, len, inet_devconf,
176 ARRAY_SIZE(inet_devconf));
177}
178
179int rtnl_link_inet_str2devconf(const char *name)
180{
181 return __str2type(name, inet_devconf, ARRAY_SIZE(inet_devconf));
182}
183
184static void inet_dump_details(struct rtnl_link *link,
185 struct nl_dump_params *p, void *data)
186{
187 struct inet_data *id = data;
188 char buf[64];
189 int i, n = 0;
190
191 nl_dump_line(p, " ipv4 devconf:\n");
192 nl_dump_line(p, " ");
193
194 for (i = 0; i < IPV4_DEVCONF_MAX; i++) {
195 nl_dump_line(p, "%-19s %3u",
196 rtnl_link_inet_devconf2str(i+1, buf, sizeof(buf)),
197 id->i_confset[i] ? id->i_conf[i] : 0);
198
199 if (++n == 3) {
200 nl_dump(p, "\n");
201 nl_dump_line(p, " ");
202 n = 0;
203 } else
204 nl_dump(p, " ");
205 }
206
207 if (n != 0)
208 nl_dump(p, "\n");
209}
210
211static struct rtnl_link_af_ops inet_ops = {
212 .ao_family = AF_INET,
213 .ao_alloc = &inet_alloc,
214 .ao_clone = &inet_clone,
215 .ao_free = &inet_free,
216 .ao_parse_af = &inet_parse_af,
217 .ao_fill_af = &inet_fill_af,
218 .ao_dump[NL_DUMP_DETAILS] = &inet_dump_details,
219};
220
221/**
222 * Get value of a ipv4 link configuration setting
223 * @arg link Link object
224 * @arg cfgid Configuration identifier
225 * @arg res Result pointer
226 *
227 * Stores the value of the specified configuration setting in the provided
228 * result pointer.
229 *
230 * @return 0 on success or a negative error code.
231 * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
232 * @return -NLE_NOATTR configuration setting not available
233 * @return -NLE_INVAL cfgid not set. If the link was received via netlink,
234 * it means that the cfgid is not supported.
235 */
236 int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid,
237 uint32_t *res)
238{
239 struct inet_data *id;
240
241 if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
242 return -NLE_RANGE;
243
244 if (!(id = rtnl_link_af_data(link, &inet_ops)))
245 return -NLE_NOATTR;
246
247 if (!id->i_confset[cfgid - 1])
248 return -NLE_INVAL;
249 *res = id->i_conf[cfgid - 1];
250
251 return 0;
252}
253
254/**
255 * Change value of a ipv4 link configuration setting
256 * @arg link Link object
257 * @arg cfgid Configuration identifier
258 * @arg value New value
259 *
260 * Changes the value in the per link ipv4 configuration array.
261 *
262 * @return 0 on success or a negative error code.
263 * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
264 * @return -NLE_NOMEM memory allocation failed
265 */
266 int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid,
267 uint32_t value)
268{
269 struct inet_data *id;
270
271 if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
272 return -NLE_NOMEM;
273
274 if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
275 return -NLE_RANGE;
276
277 id->i_confset[cfgid - 1] = 1;
278 id->i_conf[cfgid - 1] = value;
279
280 return 0;
281}
282
283
284static void _nl_init inet_init(void)
285{
286 rtnl_link_af_register(&inet_ops);
287}
288
289static void _nl_exit inet_exit(void)
290{
291 rtnl_link_af_unregister(&inet_ops);
292}
293
294/** @} */
NLA_PUT_U32
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:230
nla_memcpy
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:353
nla_nest_start
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:908
nla_parse_nested
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition attr.c:1035
nla_len
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition attr.c:130
nla_nest_end
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:971
rtnl_link_af_alloc
void * rtnl_link_af_alloc(struct rtnl_link *link, const struct rtnl_link_af_ops *ops)
Allocate and return data buffer for link address family modules.
Definition api.c:249
rtnl_link_af_unregister
int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
Unregister operations for a link address family.
Definition api.c:344
rtnl_link_af_register
int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
Register operations for a link address family.
Definition api.c:305
rtnl_link_af_data
void * rtnl_link_af_data(const struct rtnl_link *link, const struct rtnl_link_af_ops *ops)
Return data buffer for link address family modules.
Definition api.c:284
rtnl_link_inet_get_conf
int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid, uint32_t *res)
Get value of a ipv4 link configuration setting.
Definition inet.c:236
rtnl_link_inet_set_conf
int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid, uint32_t value)
Change value of a ipv4 link configuration setting.
Definition inet.c:266
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
NL_DUMP_DETAILS
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
nl_dump_params
Dumping parameters.
Definition types.h:32
nla_policy
Attribute validation policy.
Definition attr.h:63
nla_policy::minlen
uint16_t minlen
Minimal length of payload required.
Definition attr.h:68
nla_policy::type
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65
rtnl_link_af_ops
Available operations to modules implementing a link address family.
Definition link-api.h:76
rtnl_link_af_ops::ao_family
const unsigned int ao_family
The address family this operations set implements.
Definition link-api.h:78
rtnl_link
Link object.
Definition nl-route.h:29