libnl
3.2.3
|
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 /** @} */