2 * lib/route/link/inet.c AF_INET link operations
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
9 * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
14 * @defgroup link_inet IPv4 Link Module
15 * @brief Implementation of IPv4 specific link attributes
19 * @par Example: Reading the value of IPV4_DEVCONF_FORWARDING
21 * struct nl_cache *cache;
22 * struct rtnl_link *link;
25 * // Allocate a link cache
26 * rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache);
28 * // Search for the link we wish to see the value from
29 * link = rtnl_link_get_by_name(cache, "eth0");
31 * // Read the value of the setting IPV4_DEVCONF_FORWARDING
32 * if (rtnl_link_inet_get_conf(link, IPV4_DEVCONF_FORWARDING, &value) < 0)
33 * // Error: Unable to read config setting
35 * printf("forwarding is %s\n", value ? "enabled" : "disabled");
38 * @par Example: Changing the value of IPV4_DEVCONF_FOWARDING
41 * // ... Continueing from the previous example ...
44 * struct rtnl_link *new;
46 * // Allocate a new link to store the changes we wish to make.
47 * new = rtnl_link_alloc();
49 * // Set IPV4_DEVCONF_FORWARDING to '1'
50 * rtnl_link_inet_set_conf(new, IPV4_DEVCONF_FORWARDING, 1);
52 * // Send the change request to the kernel.
53 * rtnl_link_change(sock, link, new, 0);
60 #include <netlink-private/netlink.h>
61 #include <netlink/netlink.h>
62 #include <netlink/attr.h>
63 #include <netlink/route/rtnl.h>
64 #include <netlink-private/route/link/api.h>
69 uint8_t i_confset[IPV4_DEVCONF_MAX];
70 uint32_t i_conf[IPV4_DEVCONF_MAX];
74 static void *inet_alloc(struct rtnl_link *link)
76 return calloc(1, sizeof(struct inet_data));
79 static void *inet_clone(struct rtnl_link *link, void *data)
83 if ((id = inet_alloc(link)))
84 memcpy(id, data, sizeof(*id));
89 static void inet_free(struct rtnl_link *link, void *data)
94 static struct nla_policy inet_policy[IFLA_INET6_MAX+1] = {
95 [IFLA_INET_CONF] = { .minlen = IPV4_DEVCONF_MAX * 4 },
98 static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data)
100 struct inet_data *id = data;
101 struct nlattr *tb[IFLA_INET_MAX+1];
104 err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy);
108 if (tb[IFLA_INET_CONF])
109 nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf));
114 static int inet_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data)
116 struct inet_data *id = data;
120 if (!(nla = nla_nest_start(msg, IFLA_INET_CONF)))
123 for (i = 0; i < IPV4_DEVCONF_MAX; i++)
124 if (id->i_confset[i])
125 NLA_PUT_U32(msg, i+1, id->i_conf[i]);
127 nla_nest_end(msg, nla);
135 static const struct trans_tbl inet_devconf[] = {
136 __ADD(IPV4_DEVCONF_FORWARDING, forwarding)
137 __ADD(IPV4_DEVCONF_MC_FORWARDING, mc_forwarding)
138 __ADD(IPV4_DEVCONF_PROXY_ARP, proxy_arp)
139 __ADD(IPV4_DEVCONF_ACCEPT_REDIRECTS, accept_redirects)
140 __ADD(IPV4_DEVCONF_SECURE_REDIRECTS, secure_redirects)
141 __ADD(IPV4_DEVCONF_SEND_REDIRECTS, send_redirects)
142 __ADD(IPV4_DEVCONF_SHARED_MEDIA, shared_media)
143 __ADD(IPV4_DEVCONF_RP_FILTER, rp_filter)
144 __ADD(IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route)
145 __ADD(IPV4_DEVCONF_BOOTP_RELAY, bootp_relay)
146 __ADD(IPV4_DEVCONF_LOG_MARTIANS, log_martians)
147 __ADD(IPV4_DEVCONF_TAG, tag)
148 __ADD(IPV4_DEVCONF_ARPFILTER, arpfilter)
149 __ADD(IPV4_DEVCONF_MEDIUM_ID, medium_id)
150 __ADD(IPV4_DEVCONF_NOXFRM, noxfrm)
151 __ADD(IPV4_DEVCONF_NOPOLICY, nopolicy)
152 __ADD(IPV4_DEVCONF_FORCE_IGMP_VERSION, force_igmp_version)
153 __ADD(IPV4_DEVCONF_ARP_ANNOUNCE, arp_announce)
154 __ADD(IPV4_DEVCONF_ARP_IGNORE, arp_ignore)
155 __ADD(IPV4_DEVCONF_PROMOTE_SECONDARIES, promote_secondaries)
156 __ADD(IPV4_DEVCONF_ARP_ACCEPT, arp_accept)
157 __ADD(IPV4_DEVCONF_ARP_NOTIFY, arp_notify)
158 __ADD(IPV4_DEVCONF_ACCEPT_LOCAL, accept_local)
159 __ADD(IPV4_DEVCONF_SRC_VMARK, src_vmark)
160 __ADD(IPV4_DEVCONF_PROXY_ARP_PVLAN, proxy_arp_pvlan)
163 const char *rtnl_link_inet_devconf2str(int type, char *buf, size_t len)
165 return __type2str(type, buf, len, inet_devconf,
166 ARRAY_SIZE(inet_devconf));
169 int rtnl_link_inet_str2devconf(const char *name)
171 return __str2type(name, inet_devconf, ARRAY_SIZE(inet_devconf));
174 static void inet_dump_details(struct rtnl_link *link,
175 struct nl_dump_params *p, void *data)
177 struct inet_data *id = data;
181 nl_dump_line(p, " ipv4 devconf:\n");
182 nl_dump_line(p, " ");
184 for (i = 0; i < IPV4_DEVCONF_MAX; i++) {
185 nl_dump_line(p, "%-19s %3u",
186 rtnl_link_inet_devconf2str(i+1, buf, sizeof(buf)),
191 nl_dump_line(p, " ");
201 static struct rtnl_link_af_ops inet_ops = {
202 .ao_family = AF_INET,
203 .ao_alloc = &inet_alloc,
204 .ao_clone = &inet_clone,
205 .ao_free = &inet_free,
206 .ao_parse_af = &inet_parse_af,
207 .ao_fill_af = &inet_fill_af,
208 .ao_dump[NL_DUMP_DETAILS] = &inet_dump_details,
212 * Get value of a ipv4 link configuration setting
213 * @arg link Link object
214 * @arg cfgid Configuration identifier
215 * @arg res Result pointer
217 * Stores the value of the specified configuration setting in the provided
220 * @return 0 on success or a negative error code.
221 * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
222 * @return -NLE_NOATTR configuration setting not available
224 int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid,
227 struct inet_data *id;
229 if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
232 if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
235 *res = id->i_conf[cfgid - 1];
241 * Change value of a ipv4 link configuration setting
242 * @arg link Link object
243 * @arg cfgid Configuration identifier
244 * @arg value New value
246 * Changes the value in the per link ipv4 configuration array.
248 * @return 0 on success or a negative error code.
249 * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
250 * @return -NLE_NOMEM memory allocation failed
252 int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid,
255 struct inet_data *id;
257 if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
260 if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
263 id->i_confset[cfgid - 1] = 1;
264 id->i_conf[cfgid - 1] = value;
270 static void __init inet_init(void)
272 rtnl_link_af_register(&inet_ops);
275 static void __exit inet_exit(void)
277 rtnl_link_af_unregister(&inet_ops);