1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Copyright (C)2006 USAGI/WIDE Project 3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This program is free software; you can redistribute it and/or modify 5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * it under the terms of the GNU General Public License as published by 6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * the Free Software Foundation; either version 2 of the License, or 7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * (at your option) any later version. 8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This program is distributed in the hope that it will be useful, 10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * but WITHOUT ANY WARRANTY; without even the implied warranty of 11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * GNU General Public License for more details. 13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * You should have received a copy of the GNU General Public License 15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * along with this program; if not, write to the Free Software 16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Author: 20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Masahide NAKAMURA @USAGI 21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h> 24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h> 25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h> 26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h> 27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/types.h> 28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h> 29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h> 30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/ioctl.h> 31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/ip.h> 32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/if.h> 33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/if_arp.h> 34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/if_tunnel.h> 35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/ip6_tunnel.h> 36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h" 38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tunnel.h" 39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define IP6_FLOWINFO_TCLASS htonl(0x0FF00000) 41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF) 42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define DEFAULT_TNL_HOP_LIMIT (64) 44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void usage(void) __attribute__((noreturn)); 46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void usage(void) 48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Usage: ip -f inet6 tunnel { add | change | del | show } [ NAME ]\n"); 50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " [ mode { ip6ip6 | ipip6 | any } ]\n"); 51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " [ remote ADDR local ADDR ] [ dev PHYS_DEV ]\n"); 52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " [ encaplimit ELIM ]\n"); 53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr ," [ hoplimit TTL ] [ tclass TCLASS ] [ flowlabel FLOWLABEL ]\n"); 54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " [ dscp inherit ]\n"); 55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "\n"); 56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Where: NAME := STRING\n"); 57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " ADDR := IPV6_ADDRESS\n"); 58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " ELIM := { none | 0..255 }(default=%d)\n", 59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat IPV6_DEFAULT_TNL_ENCAP_LIMIT); 60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " TTL := 0..255 (default=%d)\n", 61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat DEFAULT_TNL_HOP_LIMIT); 62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " TOS := { 0x0..0xff | inherit }\n"); 63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, " FLOWLABEL := { 0x0..0xfffff | inherit }\n"); 64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void print_tunnel(struct ip6_tnl_parm *p) 68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char remote[64]; 70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char local[64]; 71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat inet_ntop(AF_INET6, &p->raddr, remote, sizeof(remote)); 73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat inet_ntop(AF_INET6, &p->laddr, local, sizeof(local)); 74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf("%s: %s/ipv6 remote %s local %s", 76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->name, tnl_strproto(p->proto), remote, local); 77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->link) { 78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char *n = tnl_ioctl_get_ifname(p->link); 79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (n) 80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" dev %s", n); 81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->flags & IP6_TNL_F_IGN_ENCAP_LIMIT) 84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" encaplimit none"); 85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" encaplimit %u", p->encap_limit); 87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" hoplimit %u", p->hop_limit); 89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->flags & IP6_TNL_F_USE_ORIG_TCLASS) 91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" tclass inherit"); 92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else { 93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 val = ntohl(p->flowinfo & IP6_FLOWINFO_TCLASS); 94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" tclass 0x%02x", (__u8)(val >> 20)); 95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) 98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" flowlabel inherit"); 99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" flowlabel 0x%05x", ntohl(p->flowinfo & IP6_FLOWINFO_FLOWLABEL)); 101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" (flowinfo 0x%08x)", ntohl(p->flowinfo)); 103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->flags & IP6_TNL_F_RCV_DSCP_COPY) 105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" dscp inherit"); 106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int parse_args(int argc, char **argv, struct ip6_tnl_parm *p) 109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char medium[IFNAMSIZ]; 111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(medium, 0, sizeof(medium)); 113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (argc > 0) { 115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "mode") == 0) { 116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "ipv6/ipv6") == 0 || 118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "ip6ip6") == 0) 119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->proto = IPPROTO_IPV6; 120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (strcmp(*argv, "ip/ipv6") == 0 || 121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "ipv4/ipv6") == 0 || 122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "ipip6") == 0 || 123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "ip4ip6") == 0) 124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->proto = IPPROTO_IPIP; 125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (strcmp(*argv, "any/ipv6") == 0 || 126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "any") == 0) 127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->proto = 0; 128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else { 129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"Cannot guess tunnel mode.\n"); 130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "remote") == 0) { 133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat inet_prefix raddr; 134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat get_prefix(&raddr, *argv, preferred_family); 136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (raddr.family == AF_UNSPEC) 137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("\"remote\" address family is AF_UNSPEC", *argv); 138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(&p->raddr, &raddr.data, sizeof(p->raddr)); 139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "local") == 0) { 140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat inet_prefix laddr; 141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat get_prefix(&laddr, *argv, preferred_family); 143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (laddr.family == AF_UNSPEC) 144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("\"local\" address family is AF_UNSPEC", *argv); 145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(&p->laddr, &laddr.data, sizeof(p->laddr)); 146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "dev") == 0) { 147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strncpy(medium, *argv, IFNAMSIZ - 1); 149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "encaplimit") == 0) { 150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "none") == 0) { 152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT; 153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u8 uval; 155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u8(&uval, *argv, 0) < -1) 156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("invalid ELIM", *argv); 157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->encap_limit = uval; 158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "hoplimit") == 0 || 160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "ttl") == 0 || 161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "hlim") == 0) { 162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u8 uval; 163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u8(&uval, *argv, 0)) 165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("invalid TTL", *argv); 166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->hop_limit = uval; 167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "tclass") == 0 || 168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "tc") == 0 || 169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "tos") == 0 || 170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat matches(*argv, "dsfield") == 0) { 171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u8 uval; 172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "inherit") == 0) 174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flags |= IP6_TNL_F_USE_ORIG_TCLASS; 175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else { 176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u8(&uval, *argv, 16)) 177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("invalid TClass", *argv); 178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; 179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; 180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "flowlabel") == 0 || 182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcmp(*argv, "fl") == 0) { 183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 uval; 184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "inherit") == 0) 186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; 187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else { 188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&uval, *argv, 16)) 189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("invalid Flowlabel", *argv); 190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (uval > 0xFFFFF) 191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("invalid Flowlabel", *argv); 192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; 193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; 194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "dscp") == 0) { 196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "inherit") != 0) 198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat invarg("not inherit", *argv); 199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->flags |= IP6_TNL_F_RCV_DSCP_COPY; 200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "name") == 0) { 202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "help") == 0) 205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat usage(); 206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->name[0]) 207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat duparg2("name", *argv); 208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strncpy(p->name, *argv, IFNAMSIZ - 1); 209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc--; argv++; 211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (medium[0]) { 213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->link = tnl_ioctl_get_ifindex(medium); 214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->link == 0) 215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void ip6_tnl_parm_init(struct ip6_tnl_parm *p, int apply_default) 221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(p, 0, sizeof(*p)); 223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->proto = IPPROTO_IPV6; 224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (apply_default) { 225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->hop_limit = DEFAULT_TNL_HOP_LIMIT; 226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; 227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * @p1: user specified parameter 232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * @p2: database entry 233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int ip6_tnl_parm_match(const struct ip6_tnl_parm *p1, 235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat const struct ip6_tnl_parm *p2) 236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return ((!p1->link || p1->link == p2->link) && 238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (!p1->name[0] || strcmp(p1->name, p2->name) == 0) && 239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (memcmp(&p1->laddr, &in6addr_any, sizeof(p1->laddr)) == 0 || 240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcmp(&p1->laddr, &p2->laddr, sizeof(p1->laddr)) == 0) && 241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (memcmp(&p1->raddr, &in6addr_any, sizeof(p1->raddr)) == 0 || 242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcmp(&p1->raddr, &p2->raddr, sizeof(p1->raddr)) == 0) && 243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (!p1->proto || !p2->proto || p1->proto == p2->proto) && 244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (!p1->encap_limit || p1->encap_limit == p2->encap_limit) && 245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (!p1->hop_limit || p1->hop_limit == p2->hop_limit) && 246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (!(p1->flowinfo & IP6_FLOWINFO_TCLASS) || 247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat !((p1->flowinfo ^ p2->flowinfo) & IP6_FLOWINFO_TCLASS)) && 248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (!(p1->flowinfo & IP6_FLOWINFO_FLOWLABEL) || 249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat !((p1->flowinfo ^ p2->flowinfo) & IP6_FLOWINFO_FLOWLABEL)) && 250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (!p1->flags || (p1->flags & p2->flags))); 251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int do_tunnels_list(struct ip6_tnl_parm *p) 254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[512]; 256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int err = -1; 257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat FILE *fp = fopen("/proc/net/dev", "r"); 258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (fp == NULL) { 259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("fopen"); 260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto end; 261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /* skip two lines at the begenning of the file */ 264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fgets(buf, sizeof(buf), fp); 265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fgets(buf, sizeof(buf), fp); 266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (fgets(buf, sizeof(buf), fp) != NULL) { 268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char name[IFNAMSIZ]; 269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int type; 270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned long rx_bytes, rx_packets, rx_errs, rx_drops, 271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rx_fifo, rx_frame, 272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tx_bytes, tx_packets, tx_errs, tx_drops, 273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tx_fifo, tx_colls, tx_carrier, rx_multi; 274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct ip6_tnl_parm p1; 275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char *ptr; 276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat buf[sizeof(buf) - 1] = '\0'; 278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if ((ptr = strchr(buf, ':')) == NULL || 279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) { 280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Wrong format of /proc/net/dev. Sorry.\n"); 281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto end; 282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (sscanf(ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld", 284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat &rx_bytes, &rx_packets, &rx_errs, &rx_drops, 285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat &rx_fifo, &rx_frame, &rx_multi, 286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat &tx_bytes, &tx_packets, &tx_errs, &tx_drops, 287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat &tx_fifo, &tx_colls, &tx_carrier) != 14) 288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p->name[0] && strcmp(p->name, name)) 290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat type = tnl_ioctl_get_iftype(name); 292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (type == -1) { 293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Failed to get type of [%s]\n", name); 294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (type != ARPHRD_TUNNEL6) 297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&p1, 0, sizeof(p1)); 299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ip6_tnl_parm_init(&p1, 0); 300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcpy(p1.name, name); 301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p1.link = tnl_ioctl_get_ifindex(p1.name); 302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (p1.link == 0) 303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tnl_get_ioctl(p1.name, &p1)) 305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!ip6_tnl_parm_match(p, &p1)) 307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat print_tunnel(&p1); 309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (show_stats) { 310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf("%s", _SL_); 311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf("RX: Packets Bytes Errors CsumErrs OutOfSeq Mcasts%s", _SL_); 312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-8ld%s", 313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rx_packets, rx_bytes, rx_errs, rx_frame, rx_fifo, rx_multi, _SL_); 314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf("TX: Packets Bytes Errors DeadLoop NoRoute NoBufs%s", _SL_); 315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-6ld", 316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tx_packets, tx_bytes, tx_errs, tx_colls, tx_carrier, tx_drops); 317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf("\n"); 319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat err = 0; 321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat end: 323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (fp) 324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fclose(fp); 325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int do_show(int argc, char **argv) 329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct ip6_tnl_parm p; 331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ip6_tnl_parm_init(&p, 0); 333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p.proto = 0; /* default to any */ 334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_args(argc, argv, &p) < 0) 336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!p.name[0] || show_stats) 339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat do_tunnels_list(&p); 340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else { 341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tnl_get_ioctl(p.name, &p)) 342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat print_tunnel(&p); 344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf("\n"); 345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int do_add(int cmd, int argc, char **argv) 351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct ip6_tnl_parm p; 353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ip6_tnl_parm_init(&p, 1); 355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_args(argc, argv, &p) < 0) 357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return tnl_add_ioctl(cmd, 360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat cmd == SIOCCHGTUNNEL && p.name[0] ? 361dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat p.name : "ip6tnl0", p.name, &p); 362dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 363dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 364dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int do_del(int argc, char **argv) 365dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 366dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct ip6_tnl_parm p; 367dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 368dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ip6_tnl_parm_init(&p, 1); 369dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 370dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_args(argc, argv, &p) < 0) 371dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 372dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 373dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return tnl_del_ioctl(p.name[0] ? p.name : "ip6tnl0", p.name, &p); 374dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 375dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 376dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint do_ip6tunnel(int argc, char **argv) 377dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 378dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat switch (preferred_family) { 379dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case AF_UNSPEC: 380dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat preferred_family = AF_INET6; 381dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 382dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat case AF_INET6: 383dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 384dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat default: 385dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Unsupported family:%d\n", preferred_family); 386dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 387dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 388dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 389dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc > 0) { 390dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "add") == 0) 391dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return do_add(SIOCADDTUNNEL, argc - 1, argv + 1); 392dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "change") == 0) 393dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return do_add(SIOCCHGTUNNEL, argc - 1, argv + 1); 394dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "del") == 0) 395dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return do_del(argc - 1, argv + 1); 396dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "show") == 0 || 397dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat matches(*argv, "lst") == 0 || 398dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat matches(*argv, "list") == 0) 399dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return do_show(argc - 1, argv + 1); 400dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "help") == 0) 401dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat usage(); 402dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else 403dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return do_show(0, NULL); 404dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 405dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Command \"%s\" is unknown, try \"ip -f inet6 tunnel help\".\n", *argv); 406dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 407dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 408