11e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu/* 21e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * iproute_lwtunnel.c 31e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * 41e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * This program is free software; you can redistribute it and/or 51e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * modify it under the terms of the GNU General Public License 61e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * as published by the Free Software Foundation; either version 71e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * 2 of the License, or (at your option) any later version. 81e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * 91e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * Authors: Roopa Prabhu, <roopa@cumulusnetworks.com> 101e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * Thomas Graf <tgraf@suug.ch> 111e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu * 121e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu */ 131e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 141e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <stdio.h> 151e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <stdlib.h> 161e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <unistd.h> 171e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <fcntl.h> 181e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <string.h> 195866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert#include <linux/ila.h> 201e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <linux/lwtunnel.h> 211e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <linux/mpls_iptunnel.h> 221e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include <errno.h> 231e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 241e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include "rt_names.h" 251e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include "utils.h" 261e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu#include "iproute_lwtunnel.h" 271e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 281e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhustatic int read_encap_type(const char *name) 291e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 301e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (strcmp(name, "mpls") == 0) 311e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return LWTUNNEL_ENCAP_MPLS; 321e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu else if (strcmp(name, "ip") == 0) 331e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return LWTUNNEL_ENCAP_IP; 341e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu else if (strcmp(name, "ip6") == 0) 351e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return LWTUNNEL_ENCAP_IP6; 365866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert else if (strcmp(name, "ila") == 0) 375866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert return LWTUNNEL_ENCAP_ILA; 381e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu else 391e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return LWTUNNEL_ENCAP_NONE; 401e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 411e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 421e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhustatic const char *format_encap_type(int type) 431e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 441e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu switch (type) { 451e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu case LWTUNNEL_ENCAP_MPLS: 461e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return "mpls"; 471e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu case LWTUNNEL_ENCAP_IP: 481e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return "ip"; 491e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu case LWTUNNEL_ENCAP_IP6: 501e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return "ip6"; 515866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert case LWTUNNEL_ENCAP_ILA: 525866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert return "ila"; 531e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu default: 541e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return "unknown"; 551e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } 561e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 571e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 581e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhustatic void print_encap_mpls(FILE *fp, struct rtattr *encap) 591e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 601e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu struct rtattr *tb[MPLS_IPTUNNEL_MAX+1]; 611e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu char abuf[256]; 621e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 631e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu parse_rtattr_nested(tb, MPLS_IPTUNNEL_MAX, encap); 641e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 651e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (tb[MPLS_IPTUNNEL_DST]) 661e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(fp, " %s ", format_host(AF_MPLS, 671e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu RTA_PAYLOAD(tb[MPLS_IPTUNNEL_DST]), 681e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu RTA_DATA(tb[MPLS_IPTUNNEL_DST]), 691e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu abuf, sizeof(abuf))); 701e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 711e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 721e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhustatic void print_encap_ip(FILE *fp, struct rtattr *encap) 731e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 741e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu struct rtattr *tb[LWTUNNEL_IP_MAX+1]; 751e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu char abuf[256]; 761e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 771e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap); 781e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 791e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (tb[LWTUNNEL_IP_ID]) 801e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID]))); 811e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 821e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (tb[LWTUNNEL_IP_SRC]) 831e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(fp, "src %s ", 841e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rt_addr_n2a(AF_INET, 851e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu RTA_PAYLOAD(tb[LWTUNNEL_IP_SRC]), 861e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu RTA_DATA(tb[LWTUNNEL_IP_SRC]), 871e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu abuf, sizeof(abuf))); 881e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 891e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (tb[LWTUNNEL_IP_DST]) 901e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(fp, "dst %s ", 911e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rt_addr_n2a(AF_INET, 921e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu RTA_PAYLOAD(tb[LWTUNNEL_IP_DST]), 931e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu RTA_DATA(tb[LWTUNNEL_IP_DST]), 941e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu abuf, sizeof(abuf))); 951e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 961e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (tb[LWTUNNEL_IP_TTL]) 971e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(fp, "ttl %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL])); 981e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 991e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (tb[LWTUNNEL_IP_TOS]) 1001e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS])); 1011e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 1021e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1035866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbertstatic void print_encap_ila(FILE *fp, struct rtattr *encap) 1045866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert{ 1055866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert struct rtattr *tb[ILA_ATTR_MAX+1]; 1065866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 1075866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert parse_rtattr_nested(tb, ILA_ATTR_MAX, encap); 1085866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 1095866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert if (tb[ILA_ATTR_LOCATOR]) { 1105866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert char abuf[ADDR64_BUF_SIZE]; 1115866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 1125866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert addr64_n2a(*(__u64 *)RTA_DATA(tb[ILA_ATTR_LOCATOR]), 1135866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert abuf, sizeof(abuf)); 1145866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert fprintf(fp, " %s ", abuf); 1155866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert } 1165866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert} 1175866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 118d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abenistatic void print_encap_ip6(FILE *fp, struct rtattr *encap) 119d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni{ 120d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni struct rtattr *tb[LWTUNNEL_IP6_MAX+1]; 121d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni char abuf[256]; 122d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 123d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap); 124d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 125d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (tb[LWTUNNEL_IP6_ID]) 126d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID]))); 127d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 128d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (tb[LWTUNNEL_IP6_SRC]) 129d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni fprintf(fp, "src %s ", 130d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni rt_addr_n2a(AF_INET6, 131d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni RTA_PAYLOAD(tb[LWTUNNEL_IP6_SRC]), 132d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni RTA_DATA(tb[LWTUNNEL_IP6_SRC]), 133d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni abuf, sizeof(abuf))); 134d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 135d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (tb[LWTUNNEL_IP6_DST]) 136d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni fprintf(fp, "dst %s ", 137d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni rt_addr_n2a(AF_INET6, 138d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni RTA_PAYLOAD(tb[LWTUNNEL_IP6_DST]), 139d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni RTA_DATA(tb[LWTUNNEL_IP6_DST]), 140d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni abuf, sizeof(abuf))); 141d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 142d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (tb[LWTUNNEL_IP6_HOPLIMIT]) 143d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni fprintf(fp, "hoplimit %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT])); 144d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 145d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (tb[LWTUNNEL_IP6_TC]) 146d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni fprintf(fp, "tc %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC])); 147d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni} 148d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 1491e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhuvoid lwt_print_encap(FILE *fp, struct rtattr *encap_type, 1501e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu struct rtattr *encap) 1511e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 1521e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu int et; 1531e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1541e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (!encap_type) 1551e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return; 1561e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1571e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu et = rta_getattr_u16(encap_type); 1581e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 159d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni fprintf(fp, " encap %s ", format_encap_type(et)); 1601e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1611e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu switch (et) { 1621e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu case LWTUNNEL_ENCAP_MPLS: 1631e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu print_encap_mpls(fp, encap); 1641e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu break; 1651e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu case LWTUNNEL_ENCAP_IP: 1661e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu print_encap_ip(fp, encap); 1671e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu break; 1685866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert case LWTUNNEL_ENCAP_ILA: 1695866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert print_encap_ila(fp, encap); 1705866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert break; 171d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni case LWTUNNEL_ENCAP_IP6: 172d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni print_encap_ip6(fp, encap); 173d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni break; 1741e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } 1751e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 1761e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1771e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhustatic int parse_encap_mpls(struct rtattr *rta, size_t len, int *argcp, char ***argvp) 1781e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 1791e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu inet_prefix addr; 1801e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu int argc = *argcp; 1811e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu char **argv = *argvp; 1821e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1831e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (get_addr(&addr, *argv, AF_MPLS)) { 1841e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(stderr, "Error: an inet address is expected rather than \"%s\".\n", *argv); 1851e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu exit(1); 1861e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } 1871e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1881e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data, 1891e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu addr.bytelen); 1901e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1911e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu *argcp = argc; 1921e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu *argvp = argv; 1931e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1941e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return 0; 1951e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 1961e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 1971e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhustatic int parse_encap_ip(struct rtattr *rta, size_t len, int *argcp, char ***argvp) 1981e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 1991e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; 2001e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu char **argv = *argvp; 2011e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu int argc = *argcp; 2021e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 2031e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu while (argc > 0) { 2041e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (strcmp(*argv, "id") == 0) { 2051e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu __u64 id; 2061e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu NEXT_ARG(); 2071e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (id_ok++) 2081e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu duparg2("id", *argv); 2091e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (get_u64(&id, *argv, 0)) 2101e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu invarg("\"id\" value is invalid\n", *argv); 2111e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rta_addattr64(rta, len, LWTUNNEL_IP_ID, htonll(id)); 2121e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } else if (strcmp(*argv, "dst") == 0) { 2131e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu inet_prefix addr; 2141e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu NEXT_ARG(); 2151e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (dst_ok++) 2161e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu duparg2("dst", *argv); 2171e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu get_addr(&addr, *argv, AF_INET); 2181e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rta_addattr_l(rta, len, LWTUNNEL_IP_DST, &addr.data, addr.bytelen); 2191e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } else if (strcmp(*argv, "tos") == 0) { 2201e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu __u32 tos; 2211e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu NEXT_ARG(); 2221e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (tos_ok++) 2231e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu duparg2("tos", *argv); 2241e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (rtnl_dsfield_a2n(&tos, *argv)) 2251e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu invarg("\"tos\" value is invalid\n", *argv); 2261e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos); 2271e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } else if (strcmp(*argv, "ttl") == 0) { 2281e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu __u8 ttl; 2291e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu NEXT_ARG(); 2301e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (ttl_ok++) 2311e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu duparg2("ttl", *argv); 2321e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (get_u8(&ttl, *argv, 0)) 2331e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu invarg("\"ttl\" value is invalid\n", *argv); 2341e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); 2351e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } else { 2361e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu break; 2371e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } 238f0df40810f1c0bc86cf1fcb6f660b0fd9912b1d3Paolo Abeni argc--; argv++; 2391e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } 2401e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 241f0df40810f1c0bc86cf1fcb6f660b0fd9912b1d3Paolo Abeni /* argv is currently the first unparsed argument, 242f0df40810f1c0bc86cf1fcb6f660b0fd9912b1d3Paolo Abeni * but the lwt_parse_encap() caller will move to the next, 243f0df40810f1c0bc86cf1fcb6f660b0fd9912b1d3Paolo Abeni * so step back */ 244f0df40810f1c0bc86cf1fcb6f660b0fd9912b1d3Paolo Abeni *argcp = argc + 1; 245f0df40810f1c0bc86cf1fcb6f660b0fd9912b1d3Paolo Abeni *argvp = argv - 1; 2461e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 2471e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return 0; 2481e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 2491e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 2505866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbertstatic int parse_encap_ila(struct rtattr *rta, size_t len, 2515866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert int *argcp, char ***argvp) 2525866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert{ 2535866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert __u64 locator; 2545866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert int argc = *argcp; 2555866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert char **argv = *argvp; 2565866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 2575866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert if (get_addr64(&locator, *argv) < 0) { 2585866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert fprintf(stderr, "Bad locator: %s\n", *argv); 2595866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert exit(1); 2605866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert } 2615866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 2625866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator); 2635866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 2645866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert *argcp = argc; 2655866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert *argvp = argv; 2665866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert 2675866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert return 0; 2685866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert} 2691e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 270d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abenistatic int parse_encap_ip6(struct rtattr *rta, size_t len, int *argcp, char ***argvp) 271d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni{ 272d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; 273d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni char **argv = *argvp; 274d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni int argc = *argcp; 275d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 276d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni while (argc > 0) { 277d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (strcmp(*argv, "id") == 0) { 278d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni __u64 id; 279d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni NEXT_ARG(); 280d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (id_ok++) 281d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni duparg2("id", *argv); 282d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (get_u64(&id, *argv, 0)) 283d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni invarg("\"id\" value is invalid\n", *argv); 284d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni rta_addattr64(rta, len, LWTUNNEL_IP6_ID, htonll(id)); 285d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni } else if (strcmp(*argv, "dst") == 0) { 286d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni inet_prefix addr; 287d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni NEXT_ARG(); 288d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (dst_ok++) 289d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni duparg2("dst", *argv); 290d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni get_addr(&addr, *argv, AF_INET6); 291d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, &addr.data, addr.bytelen); 292d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni } else if (strcmp(*argv, "tc") == 0) { 293d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni __u32 tc; 294d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni NEXT_ARG(); 295d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (tos_ok++) 296d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni duparg2("tc", *argv); 297d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (rtnl_dsfield_a2n(&tc, *argv)) 298d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni invarg("\"tc\" value is invalid\n", *argv); 299d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc); 300d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni } else if (strcmp(*argv, "hoplimit") == 0) { 301d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni __u8 hoplimit; 302d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni NEXT_ARG(); 303d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (ttl_ok++) 304d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni duparg2("hoplimit", *argv); 305d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni if (get_u8(&hoplimit, *argv, 0)) 306d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni invarg("\"hoplimit\" value is invalid\n", *argv); 307d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit); 308d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni } else { 309d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni break; 310d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni } 311d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni argc--; argv++; 312d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni } 313d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 314d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni /* argv is currently the first unparsed argument, 315d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni * but the lwt_parse_encap() caller will move to the next, 316d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni * so step back */ 317d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni *argcp = argc + 1; 318d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni *argvp = argv - 1; 319d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 320d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni return 0; 321d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni} 322d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni 3231e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhuint lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) 3241e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu{ 3251e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu struct rtattr *nest; 3261e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu int argc = *argcp; 3271e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu char **argv = *argvp; 3281e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu __u16 type; 3291e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 3301e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu NEXT_ARG(); 3311e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu type = read_encap_type(*argv); 3321e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (!type) 3331e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu invarg("\"encap type\" value is invalid\n", *argv); 3341e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 3351e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu NEXT_ARG(); 3361e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu if (argc <= 1) { 3371e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(stderr, "Error: unexpected end of line after \"encap\"\n"); 3381e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu exit(-1); 3391e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } 3401e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 3411e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu nest = rta_nest(rta, 1024, RTA_ENCAP); 3421e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu switch (type) { 3431e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu case LWTUNNEL_ENCAP_MPLS: 3441e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu parse_encap_mpls(rta, len, &argc, &argv); 3451e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu break; 3461e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu case LWTUNNEL_ENCAP_IP: 3471e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu parse_encap_ip(rta, len, &argc, &argv); 3481e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu break; 3495866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert case LWTUNNEL_ENCAP_ILA: 3505866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert parse_encap_ila(rta, len, &argc, &argv); 3515866bddd9aa9eba57623d57f866afaee9a5e2597Tom Herbert break; 352d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni case LWTUNNEL_ENCAP_IP6: 353d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni parse_encap_ip6(rta, len, &argc, &argv); 354d95cdcf52b4c85c280e3a0aceff22238947d92c2Paolo Abeni break; 3551e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu default: 3561e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu fprintf(stderr, "Error: unsupported encap type\n"); 3571e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu break; 3581e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu } 3591e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rta_nest_end(rta, nest); 3601e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 3611e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); 3621e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 3631e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu *argcp = argc; 3641e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu *argvp = argv; 3651e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu 3661e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu return 0; 3671e5293056a02cb9f0dfb2c87e503e9f5acef16e2Roopa Prabhu} 368