14008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/* Shared library add-on to ip6tables to add Routing header support. */
24008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <stdio.h>
34008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <netdb.h>
44008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <string.h>
54008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <stdlib.h>
64008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <getopt.h>
74008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <errno.h>
84008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <ip6tables.h>
94008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/*#include <linux/in6.h>*/
104008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <linux/netfilter_ipv6/ip6t_rt.h>
114008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <sys/types.h>
124008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <sys/socket.h>
134008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#include <arpa/inet.h>
144008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
154008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/*#define DEBUG	1*/
164008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
174008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/* Function which prints out usage message. */
184008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void
194008138e2b5248940265b160fae001d8954fae21The Android Open Source Projecthelp(void)
204008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
214008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	printf(
224008138e2b5248940265b160fae001d8954fae21The Android Open Source Project"RT v%s options:\n"
234008138e2b5248940265b160fae001d8954fae21The Android Open Source Project" --rt-type [!] type            match the type\n"
244008138e2b5248940265b160fae001d8954fae21The Android Open Source Project" --rt-segsleft [!] num[:num]   match the Segments Left field (range)\n"
254008138e2b5248940265b160fae001d8954fae21The Android Open Source Project" --rt-len [!] length           total length of this header\n"
264008138e2b5248940265b160fae001d8954fae21The Android Open Source Project" --rt-0-res                    check the reserved filed, too (type 0)\n"
274008138e2b5248940265b160fae001d8954fae21The Android Open Source Project" --rt-0-addrs ADDR[,ADDR...]   Type=0 addresses (list, max: %d)\n"
284008138e2b5248940265b160fae001d8954fae21The Android Open Source Project" --rt-0-not-strict             List of Type=0 addresses not a strict list\n",
294008138e2b5248940265b160fae001d8954fae21The Android Open Source ProjectIPTABLES_VERSION, IP6T_RT_HOPS);
304008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
314008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
324008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic struct option opts[] = {
334008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	{ "rt-type", 1, 0, '1' },
344008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	{ "rt-segsleft", 1, 0, '2' },
354008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	{ "rt-len", 1, 0, '3' },
364008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	{ "rt-0-res", 0, 0, '4' },
374008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	{ "rt-0-addrs", 1, 0, '5' },
384008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	{ "rt-0-not-strict", 0, 0, '6' },
394008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	{0}
404008138e2b5248940265b160fae001d8954fae21The Android Open Source Project};
414008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
424008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic u_int32_t
434008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectparse_rt_num(const char *idstr, const char *typestr)
444008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
454008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	unsigned long int id;
464008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	char* ep;
474008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
484008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	id =  strtoul(idstr,&ep,0) ;
494008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
504008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if ( idstr == ep ) {
514008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		exit_error(PARAMETER_PROBLEM,
524008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			   "RT no valid digits in %s `%s'", typestr, idstr);
534008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
544008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if ( id == ULONG_MAX  && errno == ERANGE ) {
554008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		exit_error(PARAMETER_PROBLEM,
564008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			   "%s `%s' specified too big: would overflow",
574008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			   typestr, idstr);
584008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
594008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if ( *idstr != '\0'  && *ep != '\0' ) {
604008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		exit_error(PARAMETER_PROBLEM,
614008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			   "RT error parsing %s `%s'", typestr, idstr);
624008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
634008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	return (u_int32_t) id;
644008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
654008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
664008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void
674008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectparse_rt_segsleft(const char *idstring, u_int32_t *ids)
684008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
694008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	char *buffer;
704008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	char *cp;
714008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
724008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	buffer = strdup(idstring);
734008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if ((cp = strchr(buffer, ':')) == NULL)
744008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		ids[0] = ids[1] = parse_rt_num(buffer,"segsleft");
754008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	else {
764008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		*cp = '\0';
774008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		cp++;
784008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
794008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		ids[0] = buffer[0] ? parse_rt_num(buffer,"segsleft") : 0;
804008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		ids[1] = cp[0] ? parse_rt_num(cp,"segsleft") : 0xFFFFFFFF;
814008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
824008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	free(buffer);
834008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
844008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
854008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic char *
864008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectaddr_to_numeric(const struct in6_addr *addrp)
874008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
884008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	static char buf[50+1];
894008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	return (char *)inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
904008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
914008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
924008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic struct in6_addr *
934008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectnumeric_to_addr(const char *num)
944008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
954008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	static struct in6_addr ap;
964008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	int err;
974008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
984008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if ((err=inet_pton(AF_INET6, num, &ap)) == 1)
994008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		return &ap;
1004008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#ifdef DEBUG
1014008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1024008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#endif
1034008138e2b5248940265b160fae001d8954fae21The Android Open Source Project        exit_error(PARAMETER_PROBLEM, "bad address: %s", num);
1044008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1054008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	return (struct in6_addr *)NULL;
1064008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
1074008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1084008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1094008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic int
1104008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectparse_addresses(const char *addrstr, struct in6_addr *addrp)
1114008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
1124008138e2b5248940265b160fae001d8954fae21The Android Open Source Project        char *buffer, *cp, *next;
1134008138e2b5248940265b160fae001d8954fae21The Android Open Source Project        unsigned int i;
1144008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1154008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	buffer = strdup(addrstr);
1164008138e2b5248940265b160fae001d8954fae21The Android Open Source Project        if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
1174008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1184008138e2b5248940265b160fae001d8954fae21The Android Open Source Project        for (cp=buffer, i=0; cp && i<IP6T_RT_HOPS; cp=next,i++)
1194008138e2b5248940265b160fae001d8954fae21The Android Open Source Project        {
1204008138e2b5248940265b160fae001d8954fae21The Android Open Source Project                next=strchr(cp, ',');
1214008138e2b5248940265b160fae001d8954fae21The Android Open Source Project                if (next) *next++='\0';
1224008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		memcpy(&(addrp[i]), numeric_to_addr(cp), sizeof(struct in6_addr));
1234008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#if DEBUG
1244008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("addr str: %s\n", cp);
1254008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("addr ip6: %s\n", addr_to_numeric((numeric_to_addr(cp))));
1264008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("addr [%d]: %s\n", i, addr_to_numeric(&(addrp[i])));
1274008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#endif
1284008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
1294008138e2b5248940265b160fae001d8954fae21The Android Open Source Project        if (cp) exit_error(PARAMETER_PROBLEM, "too many addresses specified");
1304008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1314008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	free(buffer);
1324008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1334008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#if DEBUG
1344008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	printf("addr nr: %d\n", i);
1354008138e2b5248940265b160fae001d8954fae21The Android Open Source Project#endif
1364008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1374008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	return i;
1384008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
1394008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1404008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/* Initialize the match. */
1414008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void
1424008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectinit(struct ip6t_entry_match *m, unsigned int *nfcache)
1434008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
1444008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	struct ip6t_rt *rtinfo = (struct ip6t_rt *)m->data;
1454008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1464008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	rtinfo->rt_type = 0x0L;
1474008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	rtinfo->segsleft[0] = 0x0L;
1484008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	rtinfo->segsleft[1] = 0xFFFFFFFF;
1494008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	rtinfo->hdrlen = 0;
1504008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	rtinfo->flags = 0;
1514008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	rtinfo->invflags = 0;
1524008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	rtinfo->addrnr = 0;
1534008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
1544008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1554008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/* Function which parses command options; returns true if it
1564008138e2b5248940265b160fae001d8954fae21The Android Open Source Project   ate an option */
1574008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic int
1584008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectparse(int c, char **argv, int invert, unsigned int *flags,
1594008138e2b5248940265b160fae001d8954fae21The Android Open Source Project      const struct ip6t_entry *entry,
1604008138e2b5248940265b160fae001d8954fae21The Android Open Source Project      unsigned int *nfcache,
1614008138e2b5248940265b160fae001d8954fae21The Android Open Source Project      struct ip6t_entry_match **match)
1624008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
1634008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	struct ip6t_rt *rtinfo = (struct ip6t_rt *)(*match)->data;
1644008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
1654008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	switch (c) {
1664008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	case '1':
1674008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (*flags & IP6T_RT_TYP)
1684008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
1694008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "Only one `--rt-type' allowed");
1704008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		check_inverse(optarg, &invert, &optind, 0);
1714008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->rt_type = parse_rt_num(argv[optind-1], "type");
1724008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (invert)
1734008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			rtinfo->invflags |= IP6T_RT_INV_TYP;
1744008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->flags |= IP6T_RT_TYP;
1754008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		*flags |= IP6T_RT_TYP;
1764008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		break;
1774008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	case '2':
1784008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (*flags & IP6T_RT_SGS)
1794008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
1804008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "Only one `--rt-segsleft' allowed");
1814008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		check_inverse(optarg, &invert, &optind, 0);
1824008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		parse_rt_segsleft(argv[optind-1], rtinfo->segsleft);
1834008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (invert)
1844008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			rtinfo->invflags |= IP6T_RT_INV_SGS;
1854008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->flags |= IP6T_RT_SGS;
1864008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		*flags |= IP6T_RT_SGS;
1874008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		break;
1884008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	case '3':
1894008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (*flags & IP6T_RT_LEN)
1904008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
1914008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "Only one `--rt-len' allowed");
1924008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		check_inverse(optarg, &invert, &optind, 0);
1934008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->hdrlen = parse_rt_num(argv[optind-1], "length");
1944008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (invert)
1954008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			rtinfo->invflags |= IP6T_RT_INV_LEN;
1964008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->flags |= IP6T_RT_LEN;
1974008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		*flags |= IP6T_RT_LEN;
1984008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		break;
1994008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	case '4':
2004008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (*flags & IP6T_RT_RES)
2014008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
2024008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "Only one `--rt-0-res' allowed");
2034008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
2044008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
2054008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "`--rt-type 0' required before `--rt-0-res'");
2064008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->flags |= IP6T_RT_RES;
2074008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		*flags |= IP6T_RT_RES;
2084008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		break;
2094008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	case '5':
2104008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (*flags & IP6T_RT_FST)
2114008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
2124008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "Only one `--rt-0-addrs' allowed");
2134008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
2144008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
2154008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "`--rt-type 0' required before `--rt-0-addrs'");
2164008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		check_inverse(optarg, &invert, &optind, 0);
2174008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (invert)
2184008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
2194008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   " '!' not allowed with `--rt-0-addrs'");
2204008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->addrnr = parse_addresses(argv[optind-1], rtinfo->addrs);
2214008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->flags |= IP6T_RT_FST;
2224008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		*flags |= IP6T_RT_FST;
2234008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		break;
2244008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	case '6':
2254008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (*flags & IP6T_RT_FST_NSTRICT)
2264008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
2274008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "Only one `--rt-0-not-strict' allowed");
2284008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if ( !(*flags & IP6T_RT_FST) )
2294008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			exit_error(PARAMETER_PROBLEM,
2304008138e2b5248940265b160fae001d8954fae21The Android Open Source Project				   "`--rt-0-addr ...' required before `--rt-0-not-strict'");
2314008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		rtinfo->flags |= IP6T_RT_FST_NSTRICT;
2324008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		*flags |= IP6T_RT_FST_NSTRICT;
2334008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		break;
2344008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	default:
2354008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		return 0;
2364008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
2374008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2384008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	return 1;
2394008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
2404008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2414008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/* Final check; we don't care. */
2424008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void
2434008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectfinal_check(unsigned int flags)
2444008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
2454008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
2464008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2474008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void
2484008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectprint_nums(const char *name, u_int32_t min, u_int32_t max,
2494008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	    int invert)
2504008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
2514008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	const char *inv = invert ? "!" : "";
2524008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2534008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (min != 0 || max != 0xFFFFFFFF || invert) {
2544008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("%s", name);
2554008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (min == max) {
2564008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf(":%s", inv);
2574008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf("%u", min);
2584008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		} else {
2594008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf("s:%s", inv);
2604008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf("%u",min);
2614008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf(":");
2624008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf("%u",max);
2634008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		}
2644008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf(" ");
2654008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
2664008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
2674008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2684008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void
2694008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectprint_addresses(int addrnr, struct in6_addr *addrp)
2704008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
2714008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	unsigned int i;
2724008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2734008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	for(i=0; i<addrnr; i++){
2744008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("%s%c", addr_to_numeric(&(addrp[i])), (i!=addrnr-1)?',':' ');
2754008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
2764008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
2774008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2784008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/* Prints out the union ip6t_matchinfo. */
2794008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void
2804008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectprint(const struct ip6t_ip6 *ip,
2814008138e2b5248940265b160fae001d8954fae21The Android Open Source Project      const struct ip6t_entry_match *match, int numeric)
2824008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
2834008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	const struct ip6t_rt *rtinfo = (struct ip6t_rt *)match->data;
2844008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
2854008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	printf("rt ");
2864008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_TYP)
2874008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	    printf("type:%s%d ", rtinfo->invflags & IP6T_RT_INV_TYP ? "!" : "",
2884008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		    rtinfo->rt_type);
2894008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	print_nums("segsleft", rtinfo->segsleft[0], rtinfo->segsleft[1],
2904008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		    rtinfo->invflags & IP6T_RT_INV_SGS);
2914008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_LEN) {
2924008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("length");
2934008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf(":%s", rtinfo->invflags & IP6T_RT_INV_LEN ? "!" : "");
2944008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("%u", rtinfo->hdrlen);
2954008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf(" ");
2964008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
2974008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_RES) printf("reserved ");
2984008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_FST) printf("0-addrs ");
2994008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	print_addresses(rtinfo->addrnr, (struct in6_addr *)rtinfo->addrs);
3004008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_FST_NSTRICT) printf("0-not-strict ");
3014008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->invflags & ~IP6T_RT_INV_MASK)
3024008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("Unknown invflags: 0x%X ",
3034008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		       rtinfo->invflags & ~IP6T_RT_INV_MASK);
3044008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
3054008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3064008138e2b5248940265b160fae001d8954fae21The Android Open Source Project/* Saves the union ip6t_matchinfo in parsable form to stdout. */
3074008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
3084008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
3094008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	const struct ip6t_rt *rtinfo = (struct ip6t_rt *)match->data;
3104008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3114008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_TYP) {
3124008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("--rt-type %s%u ",
3134008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			(rtinfo->invflags & IP6T_RT_INV_TYP) ? "! " : "",
3144008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			rtinfo->rt_type);
3154008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
3164008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3174008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (!(rtinfo->segsleft[0] == 0
3184008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	    && rtinfo->segsleft[1] == 0xFFFFFFFF)) {
3194008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("--rt-segsleft %s",
3204008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			(rtinfo->invflags & IP6T_RT_INV_SGS) ? "! " : "");
3214008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		if (rtinfo->segsleft[0]
3224008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		    != rtinfo->segsleft[1])
3234008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf("%u:%u ",
3244008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			       rtinfo->segsleft[0],
3254008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			       rtinfo->segsleft[1]);
3264008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		else
3274008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			printf("%u ",
3284008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			       rtinfo->segsleft[0]);
3294008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
3304008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3314008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_LEN) {
3324008138e2b5248940265b160fae001d8954fae21The Android Open Source Project		printf("--rt-len %s%u ",
3334008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			(rtinfo->invflags & IP6T_RT_INV_LEN) ? "! " : "",
3344008138e2b5248940265b160fae001d8954fae21The Android Open Source Project			rtinfo->hdrlen);
3354008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	}
3364008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3374008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_RES) printf("--rt-0-res ");
3384008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_FST) printf("--rt-0-addrs ");
3394008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	print_addresses(rtinfo->addrnr, (struct in6_addr *)rtinfo->addrs);
3404008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	if (rtinfo->flags & IP6T_RT_FST_NSTRICT) printf("--rt-0-not-strict ");
3414008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3424008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
3434008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3444008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectstatic struct ip6tables_match rt = {
3454008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.name		= "rt",
3464008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.version	= IPTABLES_VERSION,
3474008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.size		= IP6T_ALIGN(sizeof(struct ip6t_rt)),
3484008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.userspacesize	= IP6T_ALIGN(sizeof(struct ip6t_rt)),
3494008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.help		= &help,
3504008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.init		= &init,
3514008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.parse		= &parse,
3524008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.final_check	= &final_check,
3534008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.print		= &print,
3544008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.save		= &save,
3554008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	.extra_opts	= opts,
3564008138e2b5248940265b160fae001d8954fae21The Android Open Source Project};
3574008138e2b5248940265b160fae001d8954fae21The Android Open Source Project
3584008138e2b5248940265b160fae001d8954fae21The Android Open Source Projectvoid
3594008138e2b5248940265b160fae001d8954fae21The Android Open Source Project_init(void)
3604008138e2b5248940265b160fae001d8954fae21The Android Open Source Project{
3614008138e2b5248940265b160fae001d8954fae21The Android Open Source Project	register_match6(&rt);
3624008138e2b5248940265b160fae001d8954fae21The Android Open Source Project}
363