From 8a485b0a363935309f976866b8a30988362fadc0 Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Mon, 29 Jun 2020 17:57:26 +0200 Subject: [PATCH] ip address: Add support for "valid_lft" and "preferred_lft" options Signed-off-by: Christian Eggers Signed-off-by: Denys Vlasenko --- networking/libiproute/ip_common.h | 4 ++ networking/libiproute/ipaddress.c | 65 +++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/networking/libiproute/ip_common.h b/networking/libiproute/ip_common.h index 40171bed9..894e380f8 100644 --- a/networking/libiproute/ip_common.h +++ b/networking/libiproute/ip_common.h @@ -33,4 +33,8 @@ int FAST_FUNC do_iplink(char **argv); POP_SAVED_FUNCTION_VISIBILITY +#ifndef INFINITY_LIFE_TIME +#define INFINITY_LIFE_TIME 0xFFFFFFFFU +#endif + #endif diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 6cfd3c398..71e8fb6a7 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c @@ -592,6 +592,14 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) return 0; } +static void set_lifetime(unsigned int *lifetime, char *argv, const char *errmsg) +{ + if (strcmp(argv, "forever") == 0) + *lifetime = INFINITY_LIFE_TIME; + else + *lifetime = get_u32(argv, errmsg); +} + static int default_scope(inet_prefix *lcl) { if (lcl->family == AF_INET) { @@ -607,10 +615,13 @@ static int ipaddr_modify(int cmd, int flags, char **argv) /* If you add stuff here, update ipaddr_full_usage */ static const char option[] ALIGN1 = "peer\0""remote\0""broadcast\0""brd\0" - "anycast\0""scope\0""dev\0""label\0""noprefixroute\0""local\0"; + "anycast\0""valid_lft\0""preferred_lft\0" + "scope\0""dev\0""label\0""noprefixroute\0""local\0"; #define option_peer option #define option_broadcast (option + sizeof("peer") + sizeof("remote")) #define option_anycast (option_broadcast + sizeof("broadcast") + sizeof("brd")) +#define option_valid_lft (option_anycast + sizeof("anycast")) +#define option_pref_lft (option_valid_lft + sizeof("valid_lft")) struct rtnl_handle rth; struct { struct nlmsghdr n; @@ -619,6 +630,8 @@ static int ipaddr_modify(int cmd, int flags, char **argv) } req; char *d = NULL; char *l = NULL; + char *valid_lftp = NULL; + char *preferred_lftp = NULL; inet_prefix lcl; inet_prefix peer; int local_len = 0; @@ -626,6 +639,8 @@ static int ipaddr_modify(int cmd, int flags, char **argv) int brd_len = 0; int any_len = 0; bool scoped = 0; + __u32 valid_lft = INFINITY_LIFE_TIME; + __u32 preferred_lft = INFINITY_LIFE_TIME; unsigned int ifa_flags = 0; memset(&req, 0, sizeof(req)); @@ -638,10 +653,9 @@ static int ipaddr_modify(int cmd, int flags, char **argv) while (*argv) { unsigned arg = index_in_strings(option, *argv); /* if search fails, "local" is assumed */ - if ((int)arg >= 0 && arg != 8) - NEXT_ARG(); if (arg <= 1) { /* peer, remote */ + NEXT_ARG(); if (peer_len) { duparg(option_peer, *argv); } @@ -654,6 +668,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv) req.ifa.ifa_prefixlen = peer.bitlen; } else if (arg <= 3) { /* broadcast, brd */ inet_prefix addr; + NEXT_ARG(); if (brd_len) { duparg(option_broadcast, *argv); } @@ -670,6 +685,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv) } } else if (arg == 4) { /* anycast */ inet_prefix addr; + NEXT_ARG(); if (any_len) { duparg(option_anycast, *argv); } @@ -679,22 +695,39 @@ static int ipaddr_modify(int cmd, int flags, char **argv) } addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); any_len = addr.bytelen; - } else if (arg == 5) { /* scope */ + } else if (arg == 5) { /* valid_lft */ + if (valid_lftp) + duparg(option_valid_lft, *argv); + NEXT_ARG(); + valid_lftp = *argv; + set_lifetime(&valid_lft, *argv, option_valid_lft); + } else if (arg == 6) { /* preferred_lft */ + if (preferred_lftp) + duparg(option_pref_lft, *argv); + NEXT_ARG(); + preferred_lftp = *argv; + set_lifetime(&preferred_lft, *argv, option_pref_lft); + } else if (arg == 7) { /* scope */ uint32_t scope = 0; + NEXT_ARG(); if (rtnl_rtscope_a2n(&scope, *argv)) { invarg_1_to_2(*argv, "scope"); } req.ifa.ifa_scope = scope; scoped = 1; - } else if (arg == 6) { /* dev */ + } else if (arg == 8) { /* dev */ + NEXT_ARG(); d = *argv; - } else if (arg == 7) { /* label */ + } else if (arg == 9) { /* label */ + NEXT_ARG(); l = *argv; addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1); - } else if (arg == 8) { /* noprefixroute */ + } else if (arg == 10) { /* noprefixroute */ ifa_flags |= IFA_F_NOPREFIXROUTE; } else { /* local (specified or assumed) */ + if ((int)arg >= 0) + NEXT_ARG(); if (local_len) { duparg2("local", *argv); } @@ -755,6 +788,24 @@ static int ipaddr_modify(int cmd, int flags, char **argv) req.ifa.ifa_index = xll_name_to_index(d); + if (valid_lftp || preferred_lftp) { + struct ifa_cacheinfo cinfo = {}; + + if (!valid_lft) { + fprintf(stderr, "valid_lft is zero\n"); + return 1; + } + if (valid_lft < preferred_lft) { + fprintf(stderr, "preferred_lft is greater than valid_lft\n"); + return 1; + } + + cinfo.ifa_prefered = preferred_lft; + cinfo.ifa_valid = valid_lft; + addattr_l(&req.n, sizeof(req), IFA_CACHEINFO, &cinfo, + sizeof(cinfo)); + } + if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2;