mirror of
https://gitee.com/openharmony/third_party_libnl
synced 2024-11-30 13:40:43 +00:00
link: AF_INET link module
Note: The code for this is not upstream yet. Extends the link api to allow address family modules to fill a link message and implements a AF_INET address family link module which uses the new interface.
This commit is contained in:
parent
2e3ca4db0c
commit
53015f8381
@ -147,6 +147,14 @@ enum {
|
||||
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
|
||||
#endif
|
||||
|
||||
enum {
|
||||
IFLA_INET_UNSPEC,
|
||||
IFLA_INET_CONF,
|
||||
__IFLA_INET_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_INET_MAX (__IFLA_INET_MAX - 1)
|
||||
|
||||
/* ifi_flags.
|
||||
|
||||
IFF_* flags.
|
||||
|
36
include/linux/inetdevice.h
Normal file
36
include/linux/inetdevice.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef _LINUX_INETDEVICE_H
|
||||
#define _LINUX_INETDEVICE_H
|
||||
|
||||
enum
|
||||
{
|
||||
IPV4_DEVCONF_FORWARDING=1,
|
||||
IPV4_DEVCONF_MC_FORWARDING,
|
||||
IPV4_DEVCONF_PROXY_ARP,
|
||||
IPV4_DEVCONF_ACCEPT_REDIRECTS,
|
||||
IPV4_DEVCONF_SECURE_REDIRECTS,
|
||||
IPV4_DEVCONF_SEND_REDIRECTS,
|
||||
IPV4_DEVCONF_SHARED_MEDIA,
|
||||
IPV4_DEVCONF_RP_FILTER,
|
||||
IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
|
||||
IPV4_DEVCONF_BOOTP_RELAY,
|
||||
IPV4_DEVCONF_LOG_MARTIANS,
|
||||
IPV4_DEVCONF_TAG,
|
||||
IPV4_DEVCONF_ARPFILTER,
|
||||
IPV4_DEVCONF_MEDIUM_ID,
|
||||
IPV4_DEVCONF_NOXFRM,
|
||||
IPV4_DEVCONF_NOPOLICY,
|
||||
IPV4_DEVCONF_FORCE_IGMP_VERSION,
|
||||
IPV4_DEVCONF_ARP_ANNOUNCE,
|
||||
IPV4_DEVCONF_ARP_IGNORE,
|
||||
IPV4_DEVCONF_PROMOTE_SECONDARIES,
|
||||
IPV4_DEVCONF_ARP_ACCEPT,
|
||||
IPV4_DEVCONF_ARP_NOTIFY,
|
||||
IPV4_DEVCONF_ACCEPT_LOCAL,
|
||||
IPV4_DEVCONF_SRC_VMARK,
|
||||
IPV4_DEVCONF_PROXY_ARP_PVLAN,
|
||||
__IPV4_DEVCONF_MAX
|
||||
};
|
||||
|
||||
#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
|
||||
|
||||
#endif /* _LINUX_INETDEVICE_H */
|
@ -48,7 +48,7 @@
|
||||
#include <linux/gen_stats.h>
|
||||
#include <linux/ip_mp_alg.h>
|
||||
#include <linux/atm.h>
|
||||
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/snmp.h>
|
||||
|
||||
|
@ -110,6 +110,11 @@ struct rtnl_link_af_ops
|
||||
int (*ao_parse_af)(struct rtnl_link *,
|
||||
struct nlattr *, void *);
|
||||
|
||||
/** Called if a link message is sent to the kernel. Must append the
|
||||
* link address family specific attributes to the message. */
|
||||
int (*ao_fill_af)(struct rtnl_link *,
|
||||
struct nl_msg *msg, void *);
|
||||
|
||||
/** Dump address family specific link attributes */
|
||||
void (*ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *,
|
||||
struct nl_dump_params *,
|
||||
@ -118,6 +123,10 @@ struct rtnl_link_af_ops
|
||||
|
||||
extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int);
|
||||
extern void rtnl_link_af_ops_put(struct rtnl_link_af_ops *);
|
||||
extern void * rtnl_link_af_alloc(struct rtnl_link *,
|
||||
const struct rtnl_link_af_ops *);
|
||||
extern void * rtnl_link_af_data(const struct rtnl_link *,
|
||||
const struct rtnl_link_af_ops *);
|
||||
extern int rtnl_link_af_register(struct rtnl_link_af_ops *);
|
||||
extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *);
|
||||
|
||||
|
29
include/netlink/route/link/inet.h
Normal file
29
include/netlink/route/link/inet.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* netlink/route/link/inet.h INET Link Module
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_INET_H_
|
||||
#define NETLINK_LINK_INET_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char * rtnl_link_inet_devconf2str(int, char *, size_t);
|
||||
extern unsigned int rtnl_link_inet_str2devconf(const char *);
|
||||
|
||||
extern int rtnl_link_inet_get_conf(struct rtnl_link *,
|
||||
const unsigned int, uint32_t *);
|
||||
extern int rtnl_link_inet_set_conf(struct rtnl_link *,
|
||||
const unsigned int, uint32_t);
|
||||
|
||||
#endif
|
@ -59,7 +59,7 @@ libnl_route_la_SOURCES = \
|
||||
route/cls/ematch/meta.c \
|
||||
\
|
||||
route/link/api.c route/link/vlan.c \
|
||||
route/link/bridge.c route/link/inet6.c \
|
||||
route/link/bridge.c route/link/inet6.c route/link/inet.c \
|
||||
\
|
||||
route/sch/blackhole.c route/sch/cbq.c route/sch/dsmark.c \
|
||||
route/sch/fifo.c route/sch/htb.c route/sch/netem.c route/sch/prio.c \
|
||||
|
@ -187,18 +187,14 @@ static struct rtnl_link_af_ops *af_lookup_and_alloc(struct rtnl_link *link,
|
||||
int family)
|
||||
{
|
||||
struct rtnl_link_af_ops *af_ops;
|
||||
void *data;
|
||||
|
||||
af_ops = rtnl_link_af_ops_lookup(family);
|
||||
if (!af_ops)
|
||||
return NULL;
|
||||
|
||||
if (!link->l_af_data[family] && af_ops->ao_alloc) {
|
||||
link->l_af_data[family] = af_ops->ao_alloc(link);
|
||||
if (!link->l_af_data[family]) {
|
||||
rtnl_link_af_ops_put(af_ops);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!(data = rtnl_link_af_data(link, af_ops)))
|
||||
return NULL;
|
||||
|
||||
return af_ops;
|
||||
}
|
||||
@ -226,6 +222,27 @@ static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int af_fill(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
|
||||
void *data, void *arg)
|
||||
{
|
||||
struct nl_msg *msg = arg;
|
||||
struct nlattr *af_attr;
|
||||
int err;
|
||||
|
||||
if (!ops->ao_fill_af)
|
||||
return 0;
|
||||
|
||||
if (!(af_attr = nla_nest_start(msg, ops->ao_family)))
|
||||
return -NLE_MSGSIZE;
|
||||
|
||||
if ((err = ops->ao_fill_af(link, arg, data)) < 0)
|
||||
return err;
|
||||
|
||||
nla_nest_end(msg, af_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int af_dump_line(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
|
||||
void *data, void *arg)
|
||||
{
|
||||
@ -1096,6 +1113,9 @@ int rtnl_link_build_change_request(struct rtnl_link *old,
|
||||
nla_nest_end(msg, info);
|
||||
}
|
||||
|
||||
if (do_foreach_af(tmpl, af_fill, msg) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
|
||||
|
@ -190,6 +190,64 @@ void rtnl_link_af_ops_put(struct rtnl_link_af_ops *ops)
|
||||
ops->ao_refcnt--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and return data buffer for link address family modules
|
||||
* @arg link Link object
|
||||
* @arg ops Address family operations
|
||||
*
|
||||
* This function must be called by link address family modules in all
|
||||
* cases where the API does not provide the data buffer as argument
|
||||
* already. This typically includes set functions the module provides.
|
||||
* Calling this function is strictly required to ensure proper allocation
|
||||
* of the buffer upon first use. Link objects will NOT proactively
|
||||
* allocate a data buffer for each registered link address family.
|
||||
*
|
||||
* @return Pointer to data buffer or NULL on error.
|
||||
*/
|
||||
void *rtnl_link_af_alloc(struct rtnl_link *link,
|
||||
const struct rtnl_link_af_ops *ops)
|
||||
{
|
||||
int family;
|
||||
|
||||
if (!link || !ops)
|
||||
BUG();
|
||||
|
||||
family = ops->ao_family;
|
||||
|
||||
if (!link->l_af_data[family]) {
|
||||
if (!ops->ao_alloc)
|
||||
BUG();
|
||||
|
||||
link->l_af_data[family] = ops->ao_alloc(link);
|
||||
if (!link->l_af_data[family])
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return link->l_af_data[family];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return data buffer for link address family modules
|
||||
* @arg link Link object
|
||||
* @arg ops Address family operations
|
||||
*
|
||||
* This function returns a pointer to the data buffer for the specified link
|
||||
* address family module or NULL if the buffer was not allocated yet. This
|
||||
* function is typically used by get functions of modules which are not
|
||||
* interested in having the data buffer allocated if no values have been set
|
||||
* yet.
|
||||
*
|
||||
* @return Pointer to data buffer or NULL on error.
|
||||
*/
|
||||
void *rtnl_link_af_data(const struct rtnl_link *link,
|
||||
const struct rtnl_link_af_ops *ops)
|
||||
{
|
||||
if (!link || !ops)
|
||||
BUG();
|
||||
|
||||
return link->l_af_data[ops->ao_family];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register operations for a link address family
|
||||
* @arg ops Address family operations
|
||||
|
228
lib/route/link/inet.c
Normal file
228
lib/route/link/inet.c
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* lib/route/link/inet.c AF_INET link operations
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/route/rtnl.h>
|
||||
#include <netlink/route/link/api.h>
|
||||
|
||||
struct inet_data
|
||||
{
|
||||
uint8_t i_confset[IPV4_DEVCONF_MAX];
|
||||
uint32_t i_conf[IPV4_DEVCONF_MAX];
|
||||
};
|
||||
|
||||
static void *inet_alloc(struct rtnl_link *link)
|
||||
{
|
||||
return calloc(1, sizeof(struct inet_data));
|
||||
}
|
||||
|
||||
static void *inet_clone(struct rtnl_link *link, void *data)
|
||||
{
|
||||
struct inet_data *id;
|
||||
|
||||
if ((id = inet_alloc(link)))
|
||||
memcpy(id, data, sizeof(*id));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static void inet_free(struct rtnl_link *link, void *data)
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
static struct nla_policy inet_policy[IFLA_INET6_MAX+1] = {
|
||||
[IFLA_INET_CONF] = { .minlen = IPV4_DEVCONF_MAX * 4 },
|
||||
};
|
||||
|
||||
static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data)
|
||||
{
|
||||
struct inet_data *id = data;
|
||||
struct nlattr *tb[IFLA_INET_MAX+1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[IFLA_INET_CONF])
|
||||
nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inet_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data)
|
||||
{
|
||||
struct inet_data *id = data;
|
||||
struct nlattr *nla;
|
||||
int i;
|
||||
|
||||
if (!(nla = nla_nest_start(msg, IFLA_INET_CONF)))
|
||||
return -NLE_MSGSIZE;
|
||||
|
||||
for (i = 0; i < IPV4_DEVCONF_MAX; i++)
|
||||
if (id->i_confset[i])
|
||||
NLA_PUT_U32(msg, i+1, id->i_conf[i]);
|
||||
|
||||
nla_nest_end(msg, nla);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static struct trans_tbl inet_devconf[] = {
|
||||
__ADD(IPV4_DEVCONF_FORWARDING, forwarding)
|
||||
__ADD(IPV4_DEVCONF_MC_FORWARDING, mc_forwarding)
|
||||
__ADD(IPV4_DEVCONF_PROXY_ARP, proxy_arp)
|
||||
__ADD(IPV4_DEVCONF_ACCEPT_REDIRECTS, accept_redirects)
|
||||
__ADD(IPV4_DEVCONF_SECURE_REDIRECTS, secure_redirects)
|
||||
__ADD(IPV4_DEVCONF_SEND_REDIRECTS, send_redirects)
|
||||
__ADD(IPV4_DEVCONF_SHARED_MEDIA, shared_media)
|
||||
__ADD(IPV4_DEVCONF_RP_FILTER, rp_filter)
|
||||
__ADD(IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route)
|
||||
__ADD(IPV4_DEVCONF_BOOTP_RELAY, bootp_relay)
|
||||
__ADD(IPV4_DEVCONF_LOG_MARTIANS, log_martians)
|
||||
__ADD(IPV4_DEVCONF_TAG, tag)
|
||||
__ADD(IPV4_DEVCONF_ARPFILTER, arpfilter)
|
||||
__ADD(IPV4_DEVCONF_MEDIUM_ID, medium_id)
|
||||
__ADD(IPV4_DEVCONF_NOXFRM, noxfrm)
|
||||
__ADD(IPV4_DEVCONF_NOPOLICY, nopolicy)
|
||||
__ADD(IPV4_DEVCONF_FORCE_IGMP_VERSION, force_igmp_version)
|
||||
__ADD(IPV4_DEVCONF_ARP_ANNOUNCE, arp_announce)
|
||||
__ADD(IPV4_DEVCONF_ARP_IGNORE, arp_ignore)
|
||||
__ADD(IPV4_DEVCONF_PROMOTE_SECONDARIES, promote_secondaries)
|
||||
__ADD(IPV4_DEVCONF_ARP_ACCEPT, arp_accept)
|
||||
__ADD(IPV4_DEVCONF_ARP_NOTIFY, arp_notify)
|
||||
__ADD(IPV4_DEVCONF_ACCEPT_LOCAL, accept_local)
|
||||
__ADD(IPV4_DEVCONF_SRC_VMARK, src_vmark)
|
||||
__ADD(IPV4_DEVCONF_PROXY_ARP_PVLAN, proxy_arp_pvlan)
|
||||
};
|
||||
|
||||
const char *rtnl_link_inet_devconf2str(int type, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(type, buf, len, inet_devconf,
|
||||
ARRAY_SIZE(inet_devconf));
|
||||
}
|
||||
|
||||
unsigned int rtnl_link_inet_str2devconf(const char *name)
|
||||
{
|
||||
return __str2type(name, inet_devconf, ARRAY_SIZE(inet_devconf));
|
||||
}
|
||||
|
||||
static void inet_dump_details(struct rtnl_link *link,
|
||||
struct nl_dump_params *p, void *data)
|
||||
{
|
||||
struct inet_data *id = data;
|
||||
char buf[64];
|
||||
int i, n = 0;
|
||||
|
||||
nl_dump_line(p, " ipv4 devconf:\n");
|
||||
nl_dump_line(p, " ");
|
||||
|
||||
for (i = 0; i < IPV4_DEVCONF_MAX; i++) {
|
||||
nl_dump_line(p, "%s %u",
|
||||
rtnl_link_inet_devconf2str(i+1, buf, sizeof(buf)),
|
||||
id->i_conf[i]);
|
||||
|
||||
if (++n == 4) {
|
||||
nl_dump(p, "\n");
|
||||
nl_dump_line(p, " ");
|
||||
n = 0;
|
||||
} else
|
||||
nl_dump(p, " ");
|
||||
}
|
||||
|
||||
if (n != 0)
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
|
||||
static struct rtnl_link_af_ops inet_ops = {
|
||||
.ao_family = AF_INET,
|
||||
.ao_alloc = &inet_alloc,
|
||||
.ao_clone = &inet_clone,
|
||||
.ao_free = &inet_free,
|
||||
.ao_parse_af = &inet_parse_af,
|
||||
.ao_fill_af = &inet_fill_af,
|
||||
.ao_dump[NL_DUMP_DETAILS] = &inet_dump_details,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get value of a ipv4 link configuration setting
|
||||
* @arg link Link object
|
||||
* @arg cfgid Configuration identifier
|
||||
* @arg res Result pointer
|
||||
*
|
||||
* Stores the value of the specified configuration setting in the provided
|
||||
* result pointer.
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
* @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
|
||||
* @return -NLE_NOATTR configuration setting not available
|
||||
*/
|
||||
int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid,
|
||||
uint32_t *res)
|
||||
{
|
||||
struct inet_data *id;
|
||||
|
||||
if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
|
||||
return -NLE_RANGE;
|
||||
|
||||
if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
|
||||
return -NLE_NOATTR;
|
||||
|
||||
*res = id->i_conf[cfgid];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change value of a ipv4 link configuration setting
|
||||
* @arg link Link object
|
||||
* @arg cfgid Configuration identifier
|
||||
* @arg value New value
|
||||
*
|
||||
* Changes the value in the per link ipv4 configuration array.
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
* @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
|
||||
* @return -NLE_NOMEM memory allocation failed
|
||||
*/
|
||||
int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid,
|
||||
uint32_t value)
|
||||
{
|
||||
struct inet_data *id;
|
||||
|
||||
if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX)
|
||||
return -NLE_RANGE;
|
||||
|
||||
id->i_confset[cfgid - 1] = 1;
|
||||
id->i_conf[cfgid - 1] = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void __init inet_init(void)
|
||||
{
|
||||
rtnl_link_af_register(&inet_ops);
|
||||
}
|
||||
|
||||
static void __exit inet_exit(void)
|
||||
{
|
||||
rtnl_link_af_unregister(&inet_ops);
|
||||
}
|
Loading…
Reference in New Issue
Block a user