diff -Nru iproute2-4.3.0/debian/changelog iproute2-4.3.0/debian/changelog --- iproute2-4.3.0/debian/changelog 2016-04-05 11:38:17.000000000 +0000 +++ iproute2-4.3.0/debian/changelog 2018-07-03 04:40:11.000000000 +0000 @@ -1,3 +1,10 @@ +iproute2 (4.3.0-1ubuntu4) UNRELEASED; urgency=medium + + * debian/patches/1004-Add-support-for-encapsulation-and- + rt_protos.patch: Fixes for lp #1771783 and lp #1771764 + + -- Khalid Elmously Tue, 03 Jul 2018 04:06:48 +0000 + iproute2 (4.3.0-1ubuntu3) xenial; urgency=medium * Add d/p/1003-fix-variable-in-libnetlink.patch (LP: #1522371), fix a variable name diff -Nru iproute2-4.3.0/debian/patches/1004-Add-support-for-encapsulation-and-rt_protos.patch iproute2-4.3.0/debian/patches/1004-Add-support-for-encapsulation-and-rt_protos.patch --- iproute2-4.3.0/debian/patches/1004-Add-support-for-encapsulation-and-rt_protos.patch 1970-01-01 00:00:00.000000000 +0000 +++ iproute2-4.3.0/debian/patches/1004-Add-support-for-encapsulation-and-rt_protos.patch 2018-07-03 04:39:35.000000000 +0000 @@ -0,0 +1,438 @@ +## Description: add some description +## Origin/Author: add some origin or author +## Bug: bug URL +Index: iproute2-4.3.0/etc/iproute2/rt_protos.d/README +=================================================================== +--- /dev/null ++++ iproute2-4.3.0/etc/iproute2/rt_protos.d/README +@@ -0,0 +1,2 @@ ++Each file in this directory is an rt_protos configuration file. iproute2 ++commands scan this directory processing all files that end in '.conf'. +Index: iproute2-4.3.0/include/utils.h +=================================================================== +--- iproute2-4.3.0.orig/include/utils.h ++++ iproute2-4.3.0/include/utils.h +@@ -191,6 +191,9 @@ void print_nlmsg_timestamp(FILE *fp, con + __attribute__ ((format (printf, (pos_str), (pos_args)))) + #endif + ++#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) ++#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) ++ + extern int cmdlineno; + ssize_t getcmdline(char **line, size_t *len, FILE *in); + int makeargs(char *line, char *argv[], int maxargs); +Index: iproute2-4.3.0/ip/Makefile +=================================================================== +--- iproute2-4.3.0.orig/ip/Makefile ++++ iproute2-4.3.0/ip/Makefile +@@ -7,7 +7,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o ipr + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ + link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ + iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ +- iplink_geneve.o iplink_vrf.o ++ iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o + + RTMONOBJ=rtmon.o + +Index: iproute2-4.3.0/ip/iproute.c +=================================================================== +--- iproute2-4.3.0.orig/ip/iproute.c ++++ iproute2-4.3.0/ip/iproute.c +@@ -29,6 +29,7 @@ + #include "rt_names.h" + #include "utils.h" + #include "ip_common.h" ++#include "iproute_lwtunnel.h" + + #ifndef RTAX_RTTVAR + #define RTAX_RTTVAR RTAX_HOPS +@@ -76,7 +77,8 @@ static void usage(void) + fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n"); + fprintf(stderr, " [ scope SCOPE ] [ metric METRIC ]\n"); + fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n"); +- fprintf(stderr, "NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"); ++ fprintf(stderr, "NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n"); ++ fprintf(stderr, " [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"); + fprintf(stderr, "FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]\n"); + fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n"); + fprintf(stderr, " [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n"); +@@ -95,6 +97,8 @@ static void usage(void) + fprintf(stderr, "TIME := NUMBER[s|ms]\n"); + fprintf(stderr, "BOOL := [1|0]\n"); + fprintf(stderr, "FEATURES := ecn\n"); ++ fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n"); ++ fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n"); + exit(-1); + } + +@@ -401,6 +405,10 @@ int print_route(const struct sockaddr_nl + abuf, sizeof(abuf)) + ); + } ++ ++ if (tb[RTA_ENCAP]) ++ lwt_print_encap(fp, tb[RTA_ENCAP_TYPE], tb[RTA_ENCAP]); ++ + if (r->rtm_tos && filter.tosmask != -1) { + SPRINT_BUF(b1); + fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); +@@ -633,6 +641,12 @@ int print_route(const struct sockaddr_nl + fprintf(fp, "%s\tnexthop", _SL_); + if (nh->rtnh_len > sizeof(*nh)) { + parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), nh->rtnh_len - sizeof(*nh)); ++ ++ if (tb[RTA_ENCAP]) ++ lwt_print_encap(fp, ++ tb[RTA_ENCAP_TYPE], ++ tb[RTA_ENCAP]); ++ + if (tb[RTA_GATEWAY]) { + fprintf(fp, " via %s ", + format_host(r->rtm_family, +@@ -704,9 +718,8 @@ int print_route(const struct sockaddr_nl + return 0; + } + +- +-static int parse_one_nh(struct rtmsg *r, struct rtattr *rta, +- struct rtnexthop *rtnh, ++static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, ++ struct rtattr *rta, struct rtnexthop *rtnh, + int *argcp, char ***argvp) + { + int argc = *argcp; +@@ -753,6 +766,11 @@ static int parse_one_nh(struct rtmsg *r, + invarg("\"realm\" value is invalid\n", *argv); + rta_addattr32(rta, 4096, RTA_FLOW, realm); + rtnh->rtnh_len += sizeof(struct rtattr) + 4; ++ } else if (strcmp(*argv, "encap") == 0) { ++ int len = rta->rta_len; ++ ++ lwt_parse_encap(rta, 4096, &argc, &argv); ++ rtnh->rtnh_len += rta->rta_len - len; + } else + break; + } +@@ -784,7 +802,7 @@ static int parse_nexthops(struct nlmsghd + memset(rtnh, 0, sizeof(*rtnh)); + rtnh->rtnh_len = sizeof(*rtnh); + rta->rta_len += rtnh->rtnh_len; +- parse_one_nh(r, rta, rtnh, &argc, &argv); ++ parse_one_nh(n, r, rta, rtnh, &argc, &argv); + rtnh = RTNH_NEXT(rtnh); + } + +@@ -1092,6 +1110,17 @@ static int iproute_modify(int cmd, unsig + else if (get_u8(&pref, *argv, 0)) + invarg("\"pref\" value is invalid\n", *argv); + addattr8(&req.n, sizeof(req), RTA_PREF, pref); ++ } else if (strcmp(*argv, "encap") == 0) { ++ char buf[1024]; ++ struct rtattr *rta = (void*)buf; ++ ++ rta->rta_type = RTA_ENCAP; ++ rta->rta_len = RTA_LENGTH(0); ++ ++ lwt_parse_encap(rta, sizeof(buf), &argc, &argv); ++ ++ if (rta->rta_len > RTA_LENGTH(0)) ++ addraw_l(&req.n, 1024, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } else { + int type; + inet_prefix dst; +Index: iproute2-4.3.0/ip/iproute_lwtunnel.c +=================================================================== +--- /dev/null ++++ iproute2-4.3.0/ip/iproute_lwtunnel.c +@@ -0,0 +1,228 @@ ++/* ++ * iproute_lwtunnel.c ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Authors: Roopa Prabhu, ++ * Thomas Graf ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rt_names.h" ++#include "utils.h" ++#include "iproute_lwtunnel.h" ++ ++static int read_encap_type(const char *name) ++{ ++ if (strcmp(name, "mpls") == 0) ++ return LWTUNNEL_ENCAP_MPLS; ++ else if (strcmp(name, "ip") == 0) ++ return LWTUNNEL_ENCAP_IP; ++ else if (strcmp(name, "ip6") == 0) ++ return LWTUNNEL_ENCAP_IP6; ++ else ++ return LWTUNNEL_ENCAP_NONE; ++} ++ ++static const char *format_encap_type(int type) ++{ ++ switch (type) { ++ case LWTUNNEL_ENCAP_MPLS: ++ return "mpls"; ++ case LWTUNNEL_ENCAP_IP: ++ return "ip"; ++ case LWTUNNEL_ENCAP_IP6: ++ return "ip6"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static void print_encap_mpls(FILE *fp, struct rtattr *encap) ++{ ++ struct rtattr *tb[MPLS_IPTUNNEL_MAX+1]; ++ char abuf[256]; ++ ++ parse_rtattr_nested(tb, MPLS_IPTUNNEL_MAX, encap); ++ ++ if (tb[MPLS_IPTUNNEL_DST]) ++ fprintf(fp, " %s ", format_host(AF_MPLS, ++ RTA_PAYLOAD(tb[MPLS_IPTUNNEL_DST]), ++ RTA_DATA(tb[MPLS_IPTUNNEL_DST]), ++ abuf, sizeof(abuf))); ++} ++ ++static void print_encap_ip(FILE *fp, struct rtattr *encap) ++{ ++ struct rtattr *tb[LWTUNNEL_IP_MAX+1]; ++ char abuf[256]; ++ ++ parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap); ++ ++ if (tb[LWTUNNEL_IP_ID]) ++ fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID]))); ++ ++ if (tb[LWTUNNEL_IP_SRC]) ++ fprintf(fp, "src %s ", ++ rt_addr_n2a(AF_INET, ++ RTA_PAYLOAD(tb[LWTUNNEL_IP_SRC]), ++ RTA_DATA(tb[LWTUNNEL_IP_SRC]), ++ abuf, sizeof(abuf))); ++ ++ if (tb[LWTUNNEL_IP_DST]) ++ fprintf(fp, "dst %s ", ++ rt_addr_n2a(AF_INET, ++ RTA_PAYLOAD(tb[LWTUNNEL_IP_DST]), ++ RTA_DATA(tb[LWTUNNEL_IP_DST]), ++ abuf, sizeof(abuf))); ++ ++ if (tb[LWTUNNEL_IP_TTL]) ++ fprintf(fp, "ttl %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL])); ++ ++ if (tb[LWTUNNEL_IP_TOS]) ++ fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS])); ++} ++ ++void lwt_print_encap(FILE *fp, struct rtattr *encap_type, ++ struct rtattr *encap) ++{ ++ int et; ++ ++ if (!encap_type) ++ return; ++ ++ et = rta_getattr_u16(encap_type); ++ ++ fprintf(fp, " encap %s", format_encap_type(et)); ++ ++ switch (et) { ++ case LWTUNNEL_ENCAP_MPLS: ++ print_encap_mpls(fp, encap); ++ break; ++ case LWTUNNEL_ENCAP_IP: ++ print_encap_ip(fp, encap); ++ break; ++ } ++} ++ ++static int parse_encap_mpls(struct rtattr *rta, size_t len, int *argcp, char ***argvp) ++{ ++ inet_prefix addr; ++ int argc = *argcp; ++ char **argv = *argvp; ++ ++ if (get_addr(&addr, *argv, AF_MPLS)) { ++ fprintf(stderr, "Error: an inet address is expected rather than \"%s\".\n", *argv); ++ exit(1); ++ } ++ ++ rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data, ++ addr.bytelen); ++ ++ *argcp = argc; ++ *argvp = argv; ++ ++ return 0; ++} ++ ++static int parse_encap_ip(struct rtattr *rta, size_t len, int *argcp, char ***argvp) ++{ ++ int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; ++ char **argv = *argvp; ++ int argc = *argcp; ++ ++ while (argc > 0) { ++ if (strcmp(*argv, "id") == 0) { ++ __u64 id; ++ NEXT_ARG(); ++ if (id_ok++) ++ duparg2("id", *argv); ++ if (get_u64(&id, *argv, 0)) ++ invarg("\"id\" value is invalid\n", *argv); ++ rta_addattr64(rta, len, LWTUNNEL_IP_ID, htonll(id)); ++ } else if (strcmp(*argv, "dst") == 0) { ++ inet_prefix addr; ++ NEXT_ARG(); ++ if (dst_ok++) ++ duparg2("dst", *argv); ++ get_addr(&addr, *argv, AF_INET); ++ rta_addattr_l(rta, len, LWTUNNEL_IP_DST, &addr.data, addr.bytelen); ++ } else if (strcmp(*argv, "tos") == 0) { ++ __u32 tos; ++ NEXT_ARG(); ++ if (tos_ok++) ++ duparg2("tos", *argv); ++ if (rtnl_dsfield_a2n(&tos, *argv)) ++ invarg("\"tos\" value is invalid\n", *argv); ++ rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos); ++ } else if (strcmp(*argv, "ttl") == 0) { ++ __u8 ttl; ++ NEXT_ARG(); ++ if (ttl_ok++) ++ duparg2("ttl", *argv); ++ if (get_u8(&ttl, *argv, 0)) ++ invarg("\"ttl\" value is invalid\n", *argv); ++ rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); ++ } else { ++ break; ++ } ++ } ++ ++ *argcp = argc; ++ *argvp = argv; ++ ++ return 0; ++} ++ ++ ++int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) ++{ ++ struct rtattr *nest; ++ int argc = *argcp; ++ char **argv = *argvp; ++ __u16 type; ++ ++ NEXT_ARG(); ++ type = read_encap_type(*argv); ++ if (!type) ++ invarg("\"encap type\" value is invalid\n", *argv); ++ ++ NEXT_ARG(); ++ if (argc <= 1) { ++ fprintf(stderr, "Error: unexpected end of line after \"encap\"\n"); ++ exit(-1); ++ } ++ ++ nest = rta_nest(rta, 1024, RTA_ENCAP); ++ switch (type) { ++ case LWTUNNEL_ENCAP_MPLS: ++ parse_encap_mpls(rta, len, &argc, &argv); ++ break; ++ case LWTUNNEL_ENCAP_IP: ++ parse_encap_ip(rta, len, &argc, &argv); ++ break; ++ default: ++ fprintf(stderr, "Error: unsupported encap type\n"); ++ break; ++ } ++ rta_nest_end(rta, nest); ++ ++ rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); ++ ++ *argcp = argc; ++ *argvp = argv; ++ ++ return 0; ++} +Index: iproute2-4.3.0/ip/iproute_lwtunnel.h +=================================================================== +--- /dev/null ++++ iproute2-4.3.0/ip/iproute_lwtunnel.h +@@ -0,0 +1,8 @@ ++#ifndef __LWTUNNEL_H__ ++#define __LETUNNEL_H__ 1 ++ ++int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp); ++void lwt_print_encap(FILE *fp, struct rtattr *encap_type, ++ struct rtattr *encap); ++ ++#endif +Index: iproute2-4.3.0/lib/rt_names.c +=================================================================== +--- iproute2-4.3.0.orig/lib/rt_names.c ++++ iproute2-4.3.0/lib/rt_names.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -143,9 +144,36 @@ static int rtnl_rtprot_init; + + static void rtnl_rtprot_initialize(void) + { ++ struct dirent *de; ++ DIR *d; ++ + rtnl_rtprot_init = 1; + rtnl_tab_initialize(CONFDIR "/rt_protos", + rtnl_rtprot_tab, 256); ++ ++ d = opendir(CONFDIR "/rt_protos.d"); ++ if (!d) ++ return; ++ ++ while ((de = readdir(d)) != NULL) { ++ char path[PATH_MAX]; ++ size_t len; ++ ++ if (*de->d_name == '.') ++ continue; ++ ++ /* only consider filenames ending in '.conf' */ ++ len = strlen(de->d_name); ++ if (len <= 5) ++ continue; ++ if (strcmp(de->d_name + len - 5, ".conf")) ++ continue; ++ ++ snprintf(path, sizeof(path), CONFDIR "/rt_protos.d/%s", ++ de->d_name); ++ rtnl_tab_initialize(path, rtnl_rtprot_tab, 256); ++ } ++ closedir(d); + } + + const char * rtnl_rtprot_n2a(int id, char *buf, int len) diff -Nru iproute2-4.3.0/debian/patches/series iproute2-4.3.0/debian/patches/series --- iproute2-4.3.0/debian/patches/series 2016-04-05 11:35:52.000000000 +0000 +++ iproute2-4.3.0/debian/patches/series 2018-07-03 04:39:27.000000000 +0000 @@ -4,3 +4,4 @@ 1001-ubuntu-poc-fan-driver-v3.patch 1002-ubuntu-poc-fan-driver-vxlan.patch 1003-fix-variable-in-libnetlink.patch +1004-Add-support-for-encapsulation-and-rt_protos.patch