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