⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipv6tunnel.c

📁 mobile ipv6协议Linux实现源代码
💻 C
字号:
/*  *	Authors: *	Ville Nuorvala		<vnuorval@tml.hut.fi>	 * * $Id: s.ipv6tunnel.c 1.9 03/09/16 14:56:16+03:00 vnuorval@dsl-hkigw1a8b.dial.inet.fi $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */ #include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <net/if.h>#include <netinet/in.h>#include <netdb.h>#include <unistd.h>#include <arpa/inet.h>#include <asm/types.h>#include <linux/sockios.h>#include <linux/ip.h>#include <linux/if_tunnel.h>#include "ipv6_tunnel.h"#define FLOWLABEL_MASK 0x000FFFFF#define TCLASS_MASK    0x0FF00000static void usage(void){	fprintf(stderr, "Usage: ipv6tunnel { add | change | del | show } [ NAME ]\n");	fprintf(stderr, "          [ --use-original-tclass ]\n");	fprintf(stderr, "          [ --use-original-flowlabel ]\n");	fprintf(stderr, "          [ remote ADDR local ADDR ]\n");	fprintf(stderr, "          [ dev PHYS_DEV ]\n");	fprintf(stderr, "          [ encaplimit TEL ]\n");	fprintf(stderr, "          [ hoplimit HOPLIMIT ]\n"); 	fprintf(stderr, "          [ tclass TCL ]\n");	fprintf(stderr, "          [ flowlabel FL ]\n");	fprintf(stderr, "Where: NAME := STRING\n");	fprintf(stderr, "       ADDR := IPV6_ADDRESS\n");	fprintf(stderr, "       PHYS_DEV := STRING\n");	fprintf(stderr, "       TEL := { none | 0..255 }\n");	fprintf(stderr, "       HOPLIMIT := 0..255\n");	fprintf(stderr, "       TCL := 0x0..0xff\n");	fprintf(stderr, "       FL := 0x0..0xfffff\n");	exit(-1);}static int do_ioctl_get_ifindex(char *dev){	struct ifreq ifr;	int fd;	int err;	strcpy(ifr.ifr_name, dev);	fd = socket(AF_INET6, SOCK_DGRAM, 0);	err = ioctl(fd, SIOCGIFINDEX, &ifr);	if (err) {		perror("ioctl");		return 0;	}	close(fd);	return ifr.ifr_ifindex;}static char *do_ioctl_get_ifname(int idx){	static struct ifreq ifr;	int fd;	int err;	ifr.ifr_ifindex = idx;	fd = socket(AF_INET6, SOCK_DGRAM, 0);	err = ioctl(fd, SIOCGIFNAME, &ifr);	if (err) {		perror("ioctl");		return NULL;	}	close(fd);	return ifr.ifr_name;}static int do_get_ioctl(char *basedev, struct ip6_tnl_parm *p){	struct ifreq ifr;	int fd;	int err;	strcpy(ifr.ifr_name, basedev);	ifr.ifr_ifru.ifru_data = (void *)p;	fd = socket(AF_INET6, SOCK_DGRAM, 0);	err = ioctl(fd, SIOCGETTUNNEL, &ifr);	if (err)		perror("ioctl");	close(fd);	return err;}static int do_add_ioctl(int cmd, char *basedev, struct ip6_tnl_parm *p){	struct ifreq ifr;	int fd;	int err;//	fprintf(stderr, "do_add_ioctl\n");	strcpy(ifr.ifr_name, basedev);	ifr.ifr_ifru.ifru_data = (void *)p;	fd = socket(AF_INET6, SOCK_DGRAM, 0);	err = ioctl(fd, cmd, &ifr);	if (err)		perror("ioctl");	close(fd);	return err;}static int do_del_ioctl(char *basedev, struct ip6_tnl_parm *p){	struct ifreq ifr;	int fd;	int err;//	fprintf(stderr, "do_del_ioctl\n");	strcpy(ifr.ifr_name, basedev);	ifr.ifr_ifru.ifru_data = (void *)p;	fd = socket(AF_INET6, SOCK_DGRAM, 0);	err = ioctl(fd, SIOCDELTUNNEL, &ifr);	if (err)		perror("ioctl");	close(fd);	return err;}void print_tunnel(struct ip6_tnl_parm *p){	char remote[64];	char local[64];		inet_ntop(AF_INET6, &p->raddr, remote, sizeof(remote));	inet_ntop(AF_INET6, &p->laddr, local, sizeof(local));	printf("%s: %s/IPv6 remote %s local %s",	       p->name,	       (p->proto == IPPROTO_IPV6 ? "IPv6" : "unknown"),	       remote, local);	if (p->link) {		char *n = do_ioctl_get_ifname(p->link);		if (n)			printf(" dev %s", n);	}	if (p->encap_limit)		printf(" encaplimit %d", p->encap_limit);	printf(" hoplimit %d", p->hop_limit);	if (p->flowinfo & TCLASS_MASK)		printf(" tclass 0x%x", p->flowinfo & TCLASS_MASK);	if (p->flowinfo & FLOWLABEL_MASK)		printf(" flowlabel 0x%x", p->flowinfo & FLOWLABEL_MASK);	if (p->flags) {		char flags[33];		char *fp = flags;		memset(flags, 0, 33);		if (p->flags & IP6_TNL_F_IGN_ENCAP_LIMIT) {			*fp = 'E';			fp++;		}		if (p->flags & IP6_TNL_F_USE_ORIG_TCLASS) {			*fp = 'T';			fp++;		}		if (p->flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) {			*fp = 'F';			fp++;		}		if (p->flags & IP6_TNL_F_MIP6_DEV) {			*fp = 'M';			fp++;		}		printf(" flags %s", flags);	}	printf("\n");}void resolve_name(char *name, struct in6_addr *ip6){ 	struct addrinfo ai, *res; 	int err; 	memset(&ai, 0, sizeof(struct addrinfo)); 	ai.ai_family = AF_INET6; 	ai.ai_protocol = IPPROTO_IPV6; 	ai.ai_flags = AI_NUMERICHOST;	err = getaddrinfo(name, NULL, &ai, &res);	if (err)		exit(-1);	*ip6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;	freeaddrinfo(res); } int get_u8(__u8 *val, char *arg){	unsigned long res = 0;	char *ptr;	if (!arg || !*arg)		return -1;	res = strtoul(arg, &ptr, 0);	if (!ptr || ptr == arg || *ptr || res > 0xFF)		return -1;	*val = (__u8) res;	return 0;}int get_u20(__u32 *val, char *arg){	unsigned long res = 0;	char *ptr;	if (!arg || !*arg)		return -1;	res = strtoul(arg, &ptr, 0);	if (!ptr || ptr == arg || *ptr || res > 0xFFFFF)		return -1;	*val = res;	return 0;}static int parse_args(int argc, char **argv, struct ip6_tnl_parm *p){	char medium[IFNAMSIZ];	memset(p, 0, sizeof(*p));	p->hop_limit = 64;	p->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;	p->proto = IPPROTO_IPV6;	memset(&medium, 0, sizeof(medium));	while (argc > 0) {		if (!strcmp(*argv, "--help") || !strcmp(*argv, "-h")) {			usage();		} else if (!strcmp(*argv, "--use-original-tclass")) {			p->flags |= IP6_TNL_F_USE_ORIG_TCLASS;		} else if (!strcmp(*argv, "--use-original-flowlabel")) {			p->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;		} else if (!strcmp(*argv, "remote")) {			argv++; 			if (--argc <= 0) 				usage();			resolve_name(*argv, &p->raddr);		} else if (!strcmp(*argv, "local")) {			argv++; 			if (--argc <= 0) 				usage();			resolve_name(*argv, &p->laddr);		} else if (!strcmp(*argv, "dev")) {			argv++; 			if (--argc <= 0) 				usage();			strncpy(medium, *argv, IFNAMSIZ - 1);		} else if (!strcmp(*argv, "encaplimit")) {			argv++; 			if (--argc <= 0) 				usage();			if (!strcmp(*argv, "none")) {				p->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;			} else {				__u8 uval;				if (get_u8(&uval, *argv) < -1)					usage();				p->encap_limit = uval;			}		} else if (!strcmp(*argv, "hoplimit")) {			__u8 uval;			argv++; 			if (--argc <= 0 || get_u8(&uval, *argv) < -1)				usage();			p->hop_limit = uval;		} else if (!strcmp(*argv, "tclass")) {			__u8 uval;			argv++; 			if (--argc <= 0 || get_u8(&uval, *argv) < -1)				usage();			p->flowinfo |= uval << 20;		} else if (!strcmp(*argv, "flowlabel")) {			__u32 uval;			argv++; 			if (--argc <= 0 || get_u20(&uval, *argv) < -1)				usage();			p->flowinfo |= uval;		} else {			if (p->name[0])				usage();			strncpy(p->name, *argv, IFNAMSIZ - 1);		}		argc--; argv++;	}	if (medium[0]) {		p->link = do_ioctl_get_ifindex(medium);		if (p->link == 0)			return -1;	}	return 0;}static int do_show(int argc, char **argv){        struct ip6_tnl_parm p;        if (parse_args(argc, argv, &p) < 0)                return -1;	if (do_get_ioctl(p.name[0] ? p.name : "ip6tnl0", &p))                return -1;        print_tunnel(&p);        return 0;}static int do_add(int cmd, int argc, char **argv){	struct ip6_tnl_parm p;	if (parse_args(argc, argv, &p) < 0)		return -1;		return do_add_ioctl(cmd, 			    cmd == SIOCCHGTUNNEL && p.name[0] ?			    p.name : "ip6tnl0", &p);}int do_del(int argc, char **argv){	struct ip6_tnl_parm p;	if (parse_args(argc, argv, &p) < 0)		return -1;	return do_del_ioctl(p.name[0] ? p.name : "ip6tnl0", &p);}int main(int argc, char **argv) { 	argc--;	argv++;	if (argc > 0) {		if (strcmp(*argv, "add") == 0)			return do_add(SIOCADDTUNNEL, argc - 1, argv + 1);		else if (strcmp(*argv, "change") == 0)			return do_add(SIOCCHGTUNNEL, argc - 1, argv + 1);		else if (strcmp(*argv, "del") == 0)			return do_del(argc - 1, argv + 1);		else if (strcmp(*argv, "show") == 0)			return do_show(argc - 1, argv + 1);		else			usage();	} else		return do_show(0, NULL);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -