libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/link/inet.c
00001 /*
00002  * lib/route/link/inet.c        AF_INET link operations
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup link_API
00014  * @defgroup link_inet IPv4 Link Module
00015  * @brief Implementation of IPv4 specific link attributes
00016  *
00017  *
00018  *
00019  * @par Example: Reading the value of IPV4_DEVCONF_FORWARDING
00020  * @code
00021  * struct nl_cache *cache;
00022  * struct rtnl_link *link;
00023  * uint32_t value;
00024  *
00025  * // Allocate a link cache
00026  * rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache);
00027  *
00028  * // Search for the link we wish to see the value from
00029  * link = rtnl_link_get_by_name(cache, "eth0");
00030  *
00031  * // Read the value of the setting IPV4_DEVCONF_FORWARDING
00032  * if (rtnl_link_inet_get_conf(link, IPV4_DEVCONF_FORWARDING, &value) < 0)
00033  *         // Error: Unable to read config setting
00034  *
00035  * printf("forwarding is %s\n", value ? "enabled" : "disabled");
00036  * @endcode
00037  *
00038  * @par Example: Changing the value of IPV4_DEVCONF_FOWARDING
00039  * @code
00040  * //
00041  * // ... Continueing from the previous example ...
00042  * //
00043  *
00044  * struct rtnl_link *new;
00045  *
00046  * // Allocate a new link to store the changes we wish to make.
00047  * new = rtnl_link_alloc();
00048  *
00049  * // Set IPV4_DEVCONF_FORWARDING to '1'
00050  * rtnl_link_inet_set_conf(new, IPV4_DEVCONF_FORWARDING, 1);
00051  *
00052  * // Send the change request to the kernel.
00053  * rtnl_link_change(sock, link, new, 0);
00054  * @endcode
00055  *
00056  * @{
00057  */
00058 
00059 
00060 #include <netlink-local.h>
00061 #include <netlink/netlink.h>
00062 #include <netlink/attr.h>
00063 #include <netlink/route/rtnl.h>
00064 #include <netlink/route/link/api.h>
00065 
00066 /** @cond SKIP */
00067 struct inet_data
00068 {
00069         uint8_t                 i_confset[IPV4_DEVCONF_MAX];
00070         uint32_t                i_conf[IPV4_DEVCONF_MAX];
00071 };
00072 /** @endcond */
00073 
00074 static void *inet_alloc(struct rtnl_link *link)
00075 {
00076         return calloc(1, sizeof(struct inet_data));
00077 }
00078 
00079 static void *inet_clone(struct rtnl_link *link, void *data)
00080 {
00081         struct inet_data *id;
00082 
00083         if ((id = inet_alloc(link)))
00084                 memcpy(id, data, sizeof(*id));
00085 
00086         return id;
00087 }
00088 
00089 static void inet_free(struct rtnl_link *link, void *data)
00090 {
00091         free(data);
00092 }
00093 
00094 static struct nla_policy inet_policy[IFLA_INET6_MAX+1] = {
00095         [IFLA_INET_CONF]        = { .minlen = IPV4_DEVCONF_MAX * 4 },
00096 };
00097 
00098 static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data)
00099 {
00100         struct inet_data *id = data;
00101         struct nlattr *tb[IFLA_INET_MAX+1];
00102         int err;
00103 
00104         err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy);
00105         if (err < 0)
00106                 return err;
00107 
00108         if (tb[IFLA_INET_CONF])
00109                 nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf));
00110 
00111         return 0;
00112 }
00113 
00114 static int inet_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data)
00115 {
00116         struct inet_data *id = data;
00117         struct nlattr *nla;
00118         int i;
00119 
00120         if (!(nla = nla_nest_start(msg, IFLA_INET_CONF)))
00121                 return -NLE_MSGSIZE;
00122 
00123         for (i = 0; i < IPV4_DEVCONF_MAX; i++)
00124                 if (id->i_confset[i])
00125                         NLA_PUT_U32(msg, i+1, id->i_conf[i]);
00126 
00127         nla_nest_end(msg, nla);
00128 
00129         return 0;
00130 
00131 nla_put_failure:
00132         return -NLE_MSGSIZE;
00133 }
00134 
00135 static const struct trans_tbl inet_devconf[] = {
00136         __ADD(IPV4_DEVCONF_FORWARDING, forwarding)
00137         __ADD(IPV4_DEVCONF_MC_FORWARDING, mc_forwarding)
00138         __ADD(IPV4_DEVCONF_PROXY_ARP, proxy_arp)
00139         __ADD(IPV4_DEVCONF_ACCEPT_REDIRECTS, accept_redirects)
00140         __ADD(IPV4_DEVCONF_SECURE_REDIRECTS, secure_redirects)
00141         __ADD(IPV4_DEVCONF_SEND_REDIRECTS, send_redirects)
00142         __ADD(IPV4_DEVCONF_SHARED_MEDIA, shared_media)
00143         __ADD(IPV4_DEVCONF_RP_FILTER, rp_filter)
00144         __ADD(IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route)
00145         __ADD(IPV4_DEVCONF_BOOTP_RELAY, bootp_relay)
00146         __ADD(IPV4_DEVCONF_LOG_MARTIANS, log_martians)
00147         __ADD(IPV4_DEVCONF_TAG, tag)
00148         __ADD(IPV4_DEVCONF_ARPFILTER, arpfilter)
00149         __ADD(IPV4_DEVCONF_MEDIUM_ID, medium_id)
00150         __ADD(IPV4_DEVCONF_NOXFRM, noxfrm)
00151         __ADD(IPV4_DEVCONF_NOPOLICY, nopolicy)
00152         __ADD(IPV4_DEVCONF_FORCE_IGMP_VERSION, force_igmp_version)
00153         __ADD(IPV4_DEVCONF_ARP_ANNOUNCE, arp_announce)
00154         __ADD(IPV4_DEVCONF_ARP_IGNORE, arp_ignore)
00155         __ADD(IPV4_DEVCONF_PROMOTE_SECONDARIES, promote_secondaries)
00156         __ADD(IPV4_DEVCONF_ARP_ACCEPT, arp_accept)
00157         __ADD(IPV4_DEVCONF_ARP_NOTIFY, arp_notify)
00158         __ADD(IPV4_DEVCONF_ACCEPT_LOCAL, accept_local)
00159         __ADD(IPV4_DEVCONF_SRC_VMARK, src_vmark)
00160         __ADD(IPV4_DEVCONF_PROXY_ARP_PVLAN, proxy_arp_pvlan)
00161 };
00162 
00163 const char *rtnl_link_inet_devconf2str(int type, char *buf, size_t len)
00164 {
00165         return __type2str(type, buf, len, inet_devconf,
00166                           ARRAY_SIZE(inet_devconf));
00167 }
00168 
00169 int rtnl_link_inet_str2devconf(const char *name)
00170 {
00171         return __str2type(name, inet_devconf, ARRAY_SIZE(inet_devconf));
00172 }
00173 
00174 static void inet_dump_details(struct rtnl_link *link,
00175                               struct nl_dump_params *p, void *data)
00176 {
00177         struct inet_data *id = data;
00178         char buf[64];
00179         int i, n = 0;
00180 
00181         nl_dump_line(p, "    ipv4 devconf:\n");
00182         nl_dump_line(p, "      ");
00183 
00184         for (i = 0; i < IPV4_DEVCONF_MAX; i++) {
00185                 nl_dump_line(p, "%-19s %3u",
00186                         rtnl_link_inet_devconf2str(i+1, buf, sizeof(buf)),
00187                         id->i_conf[i]);
00188 
00189                 if (++n == 3) {
00190                         nl_dump(p, "\n");
00191                         nl_dump_line(p, "      ");
00192                         n = 0;
00193                 } else
00194                         nl_dump(p, "  ");
00195         }
00196 
00197         if (n != 0)
00198                 nl_dump(p, "\n");
00199 }
00200 
00201 static struct rtnl_link_af_ops inet_ops = {
00202         .ao_family                      = AF_INET,
00203         .ao_alloc                       = &inet_alloc,
00204         .ao_clone                       = &inet_clone,
00205         .ao_free                        = &inet_free,
00206         .ao_parse_af                    = &inet_parse_af,
00207         .ao_fill_af                     = &inet_fill_af,
00208         .ao_dump[NL_DUMP_DETAILS]       = &inet_dump_details,
00209 };
00210 
00211 /**
00212  * Get value of a ipv4 link configuration setting
00213  * @arg link            Link object
00214  * @arg cfgid           Configuration identifier
00215  * @arg res             Result pointer
00216  *
00217  * Stores the value of the specified configuration setting in the provided
00218  * result pointer.
00219  *
00220  * @return 0 on success or a negative error code.
00221  * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
00222  * @return -NLE_NOATTR configuration setting not available
00223  */
00224 int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid,
00225                             uint32_t *res)
00226 {
00227         struct inet_data *id;
00228 
00229         if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
00230                 return -NLE_RANGE;
00231 
00232         if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
00233                 return -NLE_NOATTR;
00234 
00235         *res = id->i_conf[cfgid - 1];
00236 
00237         return 0;
00238 }
00239 
00240 /**
00241  * Change value of a ipv4 link configuration setting
00242  * @arg link            Link object
00243  * @arg cfgid           Configuration identifier
00244  * @arg value           New value
00245  *
00246  * Changes the value in the per link ipv4 configuration array. 
00247  *
00248  * @return 0 on success or a negative error code.
00249  * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
00250  * @return -NLE_NOMEM memory allocation failed
00251  */
00252 int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid,
00253                             uint32_t value)
00254 {
00255         struct inet_data *id;
00256 
00257         if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
00258                 return -NLE_NOMEM;
00259 
00260         if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
00261                 return -NLE_RANGE;
00262 
00263         id->i_confset[cfgid - 1] = 1;
00264         id->i_conf[cfgid - 1] = value;
00265 
00266         return 0;
00267 }
00268 
00269 
00270 static void __init inet_init(void)
00271 {
00272         rtnl_link_af_register(&inet_ops);
00273 }
00274 
00275 static void __exit inet_exit(void)
00276 {
00277         rtnl_link_af_unregister(&inet_ops);
00278 }
00279 
00280 /** @} */