From 8970c5cde659d76dc10cda00bb6823b6f34d9c30 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 11 Nov 2010 13:57:10 +0100 Subject: [PATCH] link: Support IFLA_IFALIAS attribute - parse IFLA_IFALIAS if available - provides API to access/change ifalias rtnl_link_get_ifalias(link) rtnl_link_set_ifalias(link, alias) - extends nl-link-set to test functionality --- include/linux/if.h | 19 +++++++++--- include/netlink-types.h | 1 + include/netlink/cli/link.h | 3 +- include/netlink/route/link.h | 5 ++- lib/route/link.c | 59 +++++++++++++++++++++++++++++++++++- src/lib/link.c | 13 +++++++- src/nl-link-set.c | 12 +++++--- 7 files changed, 99 insertions(+), 13 deletions(-) diff --git a/include/linux/if.h b/include/linux/if.h index 4c1bcfe..32f910f 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -19,9 +19,8 @@ #ifndef _LINUX_IF_H #define _LINUX_IF_H -#include /* for "__kernel_caddr_t" et al */ - #define IFNAMSIZ 16 +#define IFALIASZ 256 /* Standard interface flags (netdevice->flags). */ #define IFF_UP 0x1 /* interface is up */ @@ -61,6 +60,18 @@ #define IFF_BONDING 0x20 /* bonding master or slave */ #define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */ #define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */ +#define IFF_MASTER_ARPMON 0x100 /* bonding master, ARP mon in use */ +#define IFF_WAN_HDLC 0x200 /* WAN HDLC device */ +#define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to + * release skb->dst + */ +#define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */ +#define IFF_IN_NETPOLL 0x1000 /* whether we are processing netpoll */ +#define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */ +#define IFF_MACVLAN_PORT 0x4000 /* device used as macvlan port */ +#define IFF_BRIDGE_PORT 0x8000 /* device used as bridge port */ +#define IFF_OVS_DATAPATH 0x10000 /* device used as Open vSwitch + * datapath port */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 @@ -116,8 +127,7 @@ enum { * being very small might be worth keeping for clean configuration. */ -struct ifmap -{ +struct ifmap { unsigned long mem_start; unsigned long mem_end; unsigned short base_addr; @@ -127,5 +137,4 @@ struct ifmap /* 3 bytes spare */ }; - #endif /* _LINUX_IF_H */ diff --git a/include/netlink-types.h b/include/netlink-types.h index 7ec4c36..8616688 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -173,6 +173,7 @@ struct rtnl_link /* 2 byte hole */ struct rtnl_link_info_ops *l_info_ops; void * l_info; + char * l_ifalias; }; struct rtnl_ncacheinfo diff --git a/include/netlink/cli/link.h b/include/netlink/cli/link.h index c404019..7fe4972 100644 --- a/include/netlink/cli/link.h +++ b/include/netlink/cli/link.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2009 Thomas Graf + * Copyright (c) 2008-2010 Thomas Graf */ #ifndef __NETLINK_CLI_LINK_H_ @@ -26,5 +26,6 @@ extern void nl_cli_link_parse_mtu(struct rtnl_link *, char *); extern void nl_cli_link_parse_ifindex(struct rtnl_link *, char *); extern void nl_cli_link_parse_txqlen(struct rtnl_link *, char *); extern void nl_cli_link_parse_weight(struct rtnl_link *, char *); +extern void nl_cli_link_parse_ifalias(struct rtnl_link *, char *); #endif diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 2d410ec..ed1f4d6 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2010 Thomas Graf */ #ifndef NETLINK_LINK_H_ @@ -133,6 +133,9 @@ extern uint8_t rtnl_link_get_operstate(struct rtnl_link *); extern void rtnl_link_set_linkmode(struct rtnl_link *, uint8_t); extern uint8_t rtnl_link_get_linkmode(struct rtnl_link *); +extern const char * rtnl_link_get_ifalias(struct rtnl_link *); +extern void rtnl_link_set_ifalias(struct rtnl_link *, const char *); + extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int); extern int rtnl_link_set_info_type(struct rtnl_link *, const char *); diff --git a/lib/route/link.c b/lib/route/link.c index 27b12e5..12524e6 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2003-2010 Thomas Graf */ /** @@ -176,6 +176,7 @@ #define LINK_ATTR_OPERSTATE 0x10000 #define LINK_ATTR_LINKMODE 0x20000 #define LINK_ATTR_LINKINFO 0x40000 +#define LINK_ATTR_IFALIAS 0x80000 static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; @@ -204,6 +205,8 @@ static void link_free_data(struct nl_object *c) nl_addr_put(link->l_addr); nl_addr_put(link->l_bcast); + + free(link->l_ifalias); } } @@ -221,6 +224,10 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src) if (!(dst->l_bcast = nl_addr_clone(src->l_bcast))) return -NLE_NOMEM; + if (src->l_ifalias) + if (!(dst->l_ifalias = strdup(src->l_ifalias))) + return -NLE_NOMEM; + if (src->l_info_ops && src->l_info_ops->io_clone) { err = src->l_info_ops->io_clone(dst, src); if (err < 0) @@ -246,6 +253,7 @@ static struct nla_policy link_policy[IFLA_MAX+1] = { [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) }, [IFLA_STATS64] = { .minlen = sizeof(struct rtnl_link_stats64) }, [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) }, + [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, }; static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { @@ -426,6 +434,15 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->ce_mask |= LINK_ATTR_LINKMODE; } + if (tb[IFLA_IFALIAS]) { + link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]); + if (link->l_ifalias == NULL) { + err = -NLE_NOMEM; + goto errout; + } + link->ce_mask |= LINK_ATTR_IFALIAS; + } + if (tb[IFLA_LINKINFO]) { struct nlattr *li[IFLA_INFO_MAX+1]; @@ -522,6 +539,10 @@ static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) nl_dump(p, "\n"); + + if (link->ce_mask & LINK_ATTR_IFALIAS) + nl_dump_line(p, " alias %s\n", link->l_ifalias); + nl_dump_line(p, " "); if (link->ce_mask & LINK_ATTR_BRD) @@ -672,6 +693,7 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name)); diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr)); diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); + diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); if (flags & LOOSE_COMPARISON) diff |= LINK_DIFF(FLAGS, @@ -703,6 +725,7 @@ static struct trans_tbl link_attrs[] = { __ADD(LINK_ATTR_CHANGE, change) __ADD(LINK_ATTR_OPERSTATE, operstate) __ADD(LINK_ATTR_LINKMODE, linkmode) + __ADD(LINK_ATTR_IFALIAS, ifalias) }; static char *link_attrs2str(int attrs, char *buf, size_t len) @@ -875,6 +898,9 @@ int rtnl_link_build_change_request(struct rtnl_link *old, if (tmpl->ce_mask & LINK_ATTR_LINKMODE) NLA_PUT_U8(msg, IFLA_LINKMODE, tmpl->l_linkmode); + if (tmpl->ce_mask & LINK_ATTR_IFALIAS) + NLA_PUT_STRING(msg, IFLA_IFALIAS, tmpl->l_ifalias); + if ((tmpl->ce_mask & LINK_ATTR_LINKINFO) && tmpl->l_info_ops && tmpl->l_info_ops->io_put_attrs) { struct nlattr *info; @@ -1337,6 +1363,37 @@ uint8_t rtnl_link_get_linkmode(struct rtnl_link *link) return IF_LINK_MODE_DEFAULT; } +/** + * Return alias name of link (SNMP IfAlias) + * @arg link Link object + * + * @return Alias name or NULL if not set. + */ +const char *rtnl_link_get_ifalias(struct rtnl_link *link) +{ + return link->l_ifalias; +} + +/** + * Set alias name of link (SNMP IfAlias) + * @arg link Link object + * @arg alias Alias name or NULL to unset + * + * Sets the alias name of the link to the specified name. The alias + * name can be unset by specyfing NULL as the alias. The name will + * be strdup()ed, so no need to provide a persistent character string. + */ +void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) +{ + free(link->l_ifalias); + link->ce_mask &= ~LINK_ATTR_IFALIAS; + + if (alias) { + link->l_ifalias = strdup(alias); + link->ce_mask |= LINK_ATTR_IFALIAS; + } +} + uint64_t rtnl_link_get_stat(struct rtnl_link *link, int id) { if (id < 0 || id > RTNL_LINK_STATS_MAX) diff --git a/src/lib/link.c b/src/lib/link.c index c192569..88cea55 100644 --- a/src/lib/link.c +++ b/src/lib/link.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2008-2009 Thomas Graf + * Copyright (c) 2008-2010 Thomas Graf */ /** @@ -18,6 +18,7 @@ #include #include +#include struct rtnl_link *nl_cli_link_alloc(void) { @@ -70,4 +71,14 @@ void nl_cli_link_parse_weight(struct rtnl_link *link, char *arg) rtnl_link_set_weight(link, weight); } +void nl_cli_link_parse_ifalias(struct rtnl_link *link, char *arg) +{ + if (strlen(arg) > IFALIASZ) + nl_cli_fatal(ERANGE, + "Link ifalias too big, must not exceed %u in length.", + IFALIASZ); + + rtnl_link_set_ifalias(link, arg); +} + /** @} */ diff --git a/src/nl-link-set.c b/src/nl-link-set.c index 94c94e7..3178a98 100644 --- a/src/nl-link-set.c +++ b/src/nl-link-set.c @@ -6,7 +6,7 @@ * License as published by the Free Software Foundation version 2.1 * of the License. * - * Copyright (c) 2003-2009 Thomas Graf + * Copyright (c) 2003-2010 Thomas Graf */ #include @@ -41,6 +41,7 @@ static void print_usage(void) " --mtu=NUM MTU value\n" " --txqlen=NUM TX queue length\n" " --weight=NUM weight\n" + " --ifalias=NAME alias name (SNMP IfAlias)\n" ); exit(0); } @@ -84,6 +85,7 @@ int main(int argc, char *argv[]) ARG_MTU = 258, ARG_TXQLEN, ARG_WEIGHT, + ARG_IFALIAS, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, @@ -95,6 +97,7 @@ int main(int argc, char *argv[]) { "mtu", 1, 0, ARG_MTU }, { "txqlen", 1, 0, ARG_TXQLEN }, { "weight", 1, 0, ARG_WEIGHT }, + { "ifalias", 1, 0, ARG_IFALIAS }, { 0, 0, 0, 0 } }; @@ -109,9 +112,10 @@ int main(int argc, char *argv[]) case 'n': ok++; nl_cli_link_parse_name(link, optarg); break; case 'i': ok++; nl_cli_link_parse_ifindex(link, optarg); break; case ARG_RENAME: nl_cli_link_parse_name(change, optarg); break; - case ARG_MTU: nl_cli_link_parse_mtu(link, optarg); break; - case ARG_TXQLEN: nl_cli_link_parse_txqlen(link, optarg); break; - case ARG_WEIGHT: nl_cli_link_parse_weight(link, optarg); break; + case ARG_MTU: nl_cli_link_parse_mtu(change, optarg); break; + case ARG_TXQLEN: nl_cli_link_parse_txqlen(change, optarg); break; + case ARG_WEIGHT: nl_cli_link_parse_weight(change, optarg); break; + case ARG_IFALIAS: nl_cli_link_parse_ifalias(change, optarg); break; } }