├── src ├── .gitignore ├── Makefile ├── jhash.h ├── minivtun.h ├── list.h ├── library.h ├── minivtun.c ├── client.c ├── library.c └── server.c ├── README.md └── LICENSE /src/.gitignore: -------------------------------------------------------------------------------- 1 | /*.o 2 | /minivtun 3 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2015 Justin Liu 3 | # Author: Justin Liu 4 | # https://github.com/rssnsj/minivtun 5 | # 6 | 7 | ifeq ($(PREFIX),) 8 | PREFIX := $(shell [ -d /opt/local ] && echo /opt/local || echo /usr ) 9 | endif 10 | 11 | CC ?= gcc 12 | CFLAGS += -Wall 13 | HEADERS = minivtun.h library.h list.h jhash.h 14 | 15 | minivtun: minivtun.o library.o server.o client.o 16 | $(CC) $(LDFLAGS) -o $@ $^ -lcrypto 17 | 18 | %.o: %.c $(HEADERS) 19 | $(CC) $(CFLAGS) -c -o $@ $< 20 | 21 | install: minivtun 22 | cp -f minivtun $(PREFIX)/sbin/ 23 | 24 | clean: 25 | rm -f minivtun *.o 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # minivtun 2 | A fast secure and reliable VPN service in non-standard protocol for rapidly deploying VPN servers/clients or getting through firewalls 3 | 4 | ### Key features 5 | * Fast: direct UDP-encapsulated without complex authentication handshakes. 6 | * Secure: both header and tunnel data are encrypted, which is nearly impossible to be tracked by protocol characteristics and blocked, unless all UDP ports are blocked by your firewall; spoofed packets from unauthorized peer are dropped immediately. 7 | * Reliable: communication recovers immediately from next received packet from client after the previous session was dead, which makes the connection extremely reliable. 8 | * Rapid to deploy: a standalone program to run; all configuration are specified in command line with very few options. 9 | 10 | 11 | ### Installation for Linux 12 | 13 | Install required development components 14 | 15 | sudo apt-get install build-essential libssl-dev # for Ubuntu / Debian 16 | sudo yum install make gcc openssl-devel # for CentOS / Fedora / RedHat 17 | 18 | Compile and install 19 | 20 | git clone https://github.com/rssnsj/minivtun.git minivtun 21 | cd minivtun/src 22 | make 23 | sudo make install 24 | 25 | ### Installation for Mac OS X 26 | 27 | Install TUNTAP driver for Mac OS X: http://tuntaposx.sourceforge.net/ 28 | 29 | Compile and install 30 | 31 | git clone https://github.com/rssnsj/minivtun.git minivtun 32 | cd minivtun/src 33 | make 34 | sudo make install 35 | 36 | ### Installation for FreeBSD 37 | 38 | Compile and install 39 | 40 | git clone https://github.com/rssnsj/minivtun.git minivtun 41 | cd minivtun/src 42 | gmake 43 | sudo gmake install 44 | 45 | ### Usage 46 | 47 | Mini virtual tunneller in non-standard protocol. 48 | Usage: 49 | minivtun [options] 50 | Options: 51 | -l, --local IP:port for server to listen 52 | -r, --remote IP:port of server to connect 53 | -a, --ipv4-addr pointopoint IPv4 pair of the virtual interface 54 | IPv4 address/prefix length pair 55 | -A, --ipv6-addr IPv6 address/prefix length pair 56 | -m, --mtu set MTU size, default: 1300. 57 | -t, --keepalive interval of keep-alive packets, default: 13 58 | -n, --ifname virtual interface name 59 | -p, --pidfile PID file of the daemon 60 | -e, --key shared password for data encryption 61 | -v, --route 62 | route a network to a client address, can be multiple 63 | -w, --wait-dns wait for DNS resolve ready after service started. 64 | -d, --daemon run as daemon process 65 | -h, --help print this help 66 | 67 | ### Examples 68 | 69 | Server: Run a VPN server on port 1414, with local virtual address 10.7.0.1, client address space 10.7.0.0/24, encryption password 'Hello': 70 | 71 | /usr/sbin/minivtun -l 0.0.0.0:1414 -a 10.7.0.1/24 -e Hello -d 72 | 73 | Client: Connect VPN to the above server (assuming address vpn.abc.com), with local virtual address 10.7.0.33: 74 | 75 | /usr/sbin/minivtun -r vpn.abc.com:1414 -a 10.7.0.33/24 -e Hello -d 76 | 77 | Multiple clients on different devices can be connected to the same server: 78 | 79 | /usr/sbin/minivtun -r vpn.abc.com:1414 -a 10.7.0.34/24 -e Hello -d 80 | /usr/sbin/minivtun -r vpn.abc.com:1414 -a 10.7.0.35/24 -e Hello -d 81 | /usr/sbin/minivtun -r vpn.abc.com:1414 -a 10.7.0.36/24 -e Hello -d 82 | ... 83 | 84 | ### Diagnoses 85 | 86 | None. 87 | -------------------------------------------------------------------------------- /src/jhash.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINUX_JHASH_H 2 | #define _LINUX_JHASH_H 3 | 4 | #include 5 | 6 | /** 7 | * rol32 - rotate a 32-bit value left 8 | * @word: value to rotate 9 | * @shift: bits to roll 10 | */ 11 | static inline uint32_t rol32(uint32_t word, unsigned int shift) 12 | { 13 | return (word << shift) | (word >> (32 - shift)); 14 | } 15 | 16 | /* jhash.h: Jenkins hash support. 17 | * 18 | * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net) 19 | * 20 | * http://burtleburtle.net/bob/hash/ 21 | * 22 | * These are the credits from Bob's sources: 23 | * 24 | * lookup3.c, by Bob Jenkins, May 2006, Public Domain. 25 | * 26 | * These are functions for producing 32-bit hashes for hash table lookup. 27 | * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() 28 | * are externally useful functions. Routines to test the hash are included 29 | * if SELF_TEST is defined. You can use this free for any purpose. It's in 30 | * the public domain. It has no warranty. 31 | * 32 | * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu) 33 | * 34 | * I've modified Bob's hash to be useful in the Linux kernel, and 35 | * any bugs present are my fault. 36 | * Jozsef 37 | */ 38 | 39 | /* Best hash sizes are of power of two */ 40 | #define jhash_size(n) ((uint32_t)1<<(n)) 41 | /* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */ 42 | #define jhash_mask(n) (jhash_size(n)-1) 43 | 44 | /* __jhash_mix -- mix 3 32-bit values reversibly. */ 45 | #define __jhash_mix(a, b, c) \ 46 | { \ 47 | a -= c; a ^= rol32(c, 4); c += b; \ 48 | b -= a; b ^= rol32(a, 6); a += c; \ 49 | c -= b; c ^= rol32(b, 8); b += a; \ 50 | a -= c; a ^= rol32(c, 16); c += b; \ 51 | b -= a; b ^= rol32(a, 19); a += c; \ 52 | c -= b; c ^= rol32(b, 4); b += a; \ 53 | } 54 | 55 | /* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */ 56 | #define __jhash_final(a, b, c) \ 57 | { \ 58 | c ^= b; c -= rol32(b, 14); \ 59 | a ^= c; a -= rol32(c, 11); \ 60 | b ^= a; b -= rol32(a, 25); \ 61 | c ^= b; c -= rol32(b, 16); \ 62 | a ^= c; a -= rol32(c, 4); \ 63 | b ^= a; b -= rol32(a, 14); \ 64 | c ^= b; c -= rol32(b, 24); \ 65 | } 66 | 67 | /* An arbitrary initial parameter */ 68 | #define JHASH_INITVAL 0xdeadbeef 69 | 70 | /* jhash2 - hash an array of uint32_t's 71 | * @k: the key which must be an array of uint32_t's 72 | * @length: the number of uint32_t's in the key 73 | * @initval: the previous hash, or an arbitray value 74 | * 75 | * Returns the hash value of the key. 76 | */ 77 | static inline uint32_t jhash2(const uint32_t *k, uint32_t length, uint32_t initval) 78 | { 79 | uint32_t a, b, c; 80 | 81 | /* Set up the internal state */ 82 | a = b = c = JHASH_INITVAL + (length<<2) + initval; 83 | 84 | /* Handle most of the key */ 85 | while (length > 3) { 86 | a += k[0]; 87 | b += k[1]; 88 | c += k[2]; 89 | __jhash_mix(a, b, c); 90 | length -= 3; 91 | k += 3; 92 | } 93 | 94 | /* Handle the last 3 uint32_t's: all the case statements fall through */ 95 | switch (length) { 96 | case 3: c += k[2]; 97 | case 2: b += k[1]; 98 | case 1: a += k[0]; 99 | __jhash_final(a, b, c); 100 | case 0: /* Nothing left to add */ 101 | break; 102 | } 103 | 104 | return c; 105 | } 106 | 107 | 108 | /* jhash_3words - hash exactly 3, 2 or 1 word(s) */ 109 | static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval) 110 | { 111 | a += JHASH_INITVAL; 112 | b += JHASH_INITVAL; 113 | c += initval; 114 | 115 | __jhash_final(a, b, c); 116 | 117 | return c; 118 | } 119 | 120 | static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval) 121 | { 122 | return jhash_3words(a, b, 0, initval); 123 | } 124 | 125 | static inline uint32_t jhash_1word(uint32_t a, uint32_t initval) 126 | { 127 | return jhash_3words(a, 0, 0, initval); 128 | } 129 | 130 | #endif /* _LINUX_JHASH_H */ 131 | -------------------------------------------------------------------------------- /src/minivtun.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Justin Liu 3 | * Author: Justin Liu 4 | * https://github.com/rssnsj/minivtun 5 | */ 6 | 7 | #ifndef __MINIVTUN_H 8 | #define __MINIVTUN_H 9 | 10 | #include "library.h" 11 | 12 | extern struct minivtun_config config; 13 | extern struct state_variables state; 14 | 15 | /** 16 | * Pseudo route table for binding client side subnets 17 | * to corresponding connected virtual addresses. 18 | */ 19 | struct vt_route { 20 | struct vt_route *next; 21 | short af; 22 | union { 23 | struct in_addr in; 24 | struct in6_addr in6; 25 | } network, gateway; 26 | int prefix; 27 | }; 28 | 29 | struct minivtun_config { 30 | char ifname[40]; 31 | unsigned tun_mtu; 32 | unsigned tun_qlen; 33 | const char *crypto_passwd; 34 | const char *pid_file; 35 | bool in_background; 36 | bool tap_mode; 37 | 38 | char crypto_key[CRYPTO_MAX_KEY_SIZE]; 39 | const void *crypto_type; 40 | 41 | /* IPv4 address settings */ 42 | struct in_addr tun_in_local; 43 | struct in_addr tun_in_peer; 44 | int tun_in_prefix; 45 | 46 | /* IPv6 address settings */ 47 | struct in6_addr tun_in6_local; 48 | int tun_in6_prefix; 49 | 50 | /* Dynamic routes for client, or virtual routes for server */ 51 | struct vt_route *vt_routes; 52 | 53 | /* Client only configuration */ 54 | bool wait_dns; 55 | unsigned exit_after; 56 | bool dynamic_link; 57 | unsigned reconnect_timeo; 58 | unsigned max_droprate; 59 | unsigned max_rtt; 60 | unsigned keepalive_interval; 61 | unsigned health_assess_interval; 62 | unsigned nr_stats_buckets; 63 | const char *health_file; 64 | unsigned vt_metric; 65 | int metric_stepping; /* dynamic link route metric stepping factor */ 66 | char vt_table[32]; 67 | }; 68 | 69 | /* Statistics data for health assess */ 70 | struct stats_data { 71 | unsigned total_echo_sent; 72 | unsigned total_echo_rcvd; 73 | unsigned long total_rtt_ms; 74 | }; 75 | 76 | static inline void zero_stats_data(struct stats_data *st) 77 | { 78 | st->total_echo_sent = 0; 79 | st->total_echo_rcvd = 0; 80 | st->total_rtt_ms = 0; 81 | } 82 | 83 | /* Status variables during VPN running */ 84 | struct state_variables { 85 | int tunfd; 86 | int sockfd; 87 | 88 | /* *** Client specific *** */ 89 | struct sockaddr_inx peer_addr; 90 | __u16 xmit_seq; 91 | struct timeval last_recv; 92 | struct timeval last_echo_sent; 93 | struct timeval last_echo_recv; 94 | struct timeval last_health_assess; 95 | bool is_link_ok; 96 | bool health_based_link_up; 97 | unsigned rt_metric; /* current route metric */ 98 | 99 | /* Health assess data */ 100 | bool has_pending_echo; 101 | __be32 pending_echo_id; 102 | struct stats_data *stats_buckets; 103 | unsigned current_bucket; 104 | 105 | /* *** Server specific *** */ 106 | struct sockaddr_inx local_addr; 107 | struct timeval last_walk; 108 | }; 109 | 110 | enum { 111 | MINIVTUN_MSG_ECHO_REQ, 112 | MINIVTUN_MSG_IPDATA, 113 | MINIVTUN_MSG_DISCONNECT, 114 | MINIVTUN_MSG_ECHO_ACK, 115 | }; 116 | 117 | #define NM_PI_BUFFER_SIZE (1024 * 8) 118 | 119 | struct minivtun_msg { 120 | struct { 121 | __u8 opcode; 122 | __u8 rsv; 123 | __be16 seq; 124 | __u8 auth_key[16]; 125 | } __attribute__((packed)) hdr; /* 20 */ 126 | 127 | union { 128 | struct { 129 | __be16 proto; /* ETH_P_IP or ETH_P_IPV6 */ 130 | __be16 ip_dlen; /* Total length of IP/IPv6 data */ 131 | char data[NM_PI_BUFFER_SIZE]; 132 | } __attribute__((packed)) ipdata; /* 4+ */ 133 | struct { 134 | union { 135 | struct { 136 | struct in_addr loc_tun_in; 137 | struct in6_addr loc_tun_in6; 138 | }; 139 | struct mac_addr loc_tun_mac; 140 | }; 141 | __be32 id; 142 | } __attribute__((packed)) echo; /* 24 */ 143 | }; 144 | } __attribute__((packed)); 145 | 146 | #define MINIVTUN_MSG_BASIC_HLEN (sizeof(((struct minivtun_msg *)0)->hdr)) 147 | #define MINIVTUN_MSG_IPDATA_OFFSET (offsetof(struct minivtun_msg, ipdata.data)) 148 | 149 | #define enabled_encryption() (config.crypto_passwd[0]) 150 | 151 | static inline void local_to_netmsg(void *in, void **out, size_t *dlen) 152 | { 153 | if (enabled_encryption()) { 154 | datagram_encrypt(config.crypto_key, config.crypto_type, in, *out, dlen); 155 | } else { 156 | *out = in; 157 | } 158 | } 159 | static inline void netmsg_to_local(void *in, void **out, size_t *dlen) 160 | { 161 | if (enabled_encryption()) { 162 | datagram_decrypt(config.crypto_key, config.crypto_type, in, *out, dlen); 163 | } else { 164 | *out = in; 165 | } 166 | } 167 | 168 | int run_client(const char *peer_addr_pair); 169 | int run_server(const char *loc_addr_pair); 170 | 171 | #endif /* __MINIVTUN_H */ 172 | 173 | -------------------------------------------------------------------------------- /src/list.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIST_H 2 | #define __LIST_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * container_of - cast a member of a structure out to the containing structure 9 | * @ptr: the pointer to the member. 10 | * @type: the type of the container struct this is embedded in. 11 | * @member: the name of the member within the struct. 12 | * 13 | */ 14 | #define container_of(ptr, type, member) ({ \ 15 | const typeof(((type *)0)->member) * __mptr = (ptr); \ 16 | (type *)((char *)__mptr - offsetof(type, member)); }) 17 | 18 | /* 19 | * These are non-NULL pointers that will result in page faults 20 | * under normal circumstances, used to verify that nobody uses 21 | * non-initialized list entries. 22 | */ 23 | #define LIST_POISON1 ((void *) 0x00100100) 24 | #define LIST_POISON2 ((void *) 0x00200200) 25 | 26 | /* 27 | * Simple doubly linked list implementation. 28 | * 29 | * Some of the internal functions ("__xxx") are useful when 30 | * manipulating whole lists rather than single entries, as 31 | * sometimes we already know the next/prev entries and we can 32 | * generate better code by using them directly rather than 33 | * using the generic single-entry routines. 34 | */ 35 | 36 | struct list_head { 37 | struct list_head *next, *prev; 38 | }; 39 | 40 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 41 | 42 | #define __LIST_HEAD(name) \ 43 | struct list_head name = LIST_HEAD_INIT(name) 44 | 45 | static inline void INIT_LIST_HEAD(struct list_head *list) 46 | { 47 | list->next = list; 48 | list->prev = list; 49 | } 50 | 51 | /* 52 | * Insert a new entry between two known consecutive entries. 53 | * 54 | * This is only for internal list manipulation where we know 55 | * the prev/next entries already! 56 | */ 57 | static inline void __list_add(struct list_head *new, 58 | struct list_head *prev, 59 | struct list_head *next) 60 | { 61 | next->prev = new; 62 | new->next = next; 63 | new->prev = prev; 64 | prev->next = new; 65 | } 66 | 67 | /** 68 | * list_add - add a new entry 69 | * @new: new entry to be added 70 | * @head: list head to add it after 71 | * 72 | * Insert a new entry after the specified head. 73 | * This is good for implementing stacks. 74 | */ 75 | static inline void list_add(struct list_head *new, struct list_head *head) 76 | { 77 | __list_add(new, head, head->next); 78 | } 79 | 80 | /** 81 | * list_add_tail - add a new entry 82 | * @new: new entry to be added 83 | * @head: list head to add it before 84 | * 85 | * Insert a new entry before the specified head. 86 | * This is useful for implementing queues. 87 | */ 88 | static inline void list_add_tail(struct list_head *new, struct list_head *head) 89 | { 90 | __list_add(new, head->prev, head); 91 | } 92 | 93 | /* 94 | * Delete a list entry by making the prev/next entries 95 | * point to each other. 96 | * 97 | * This is only for internal list manipulation where we know 98 | * the prev/next entries already! 99 | */ 100 | static inline void __list_del(struct list_head * prev, struct list_head * next) 101 | { 102 | next->prev = prev; 103 | prev->next = next; 104 | } 105 | 106 | /** 107 | * list_del - deletes entry from list. 108 | * @entry: the element to delete from the list. 109 | * Note: list_empty() on entry does not return true after this, the entry is 110 | * in an undefined state. 111 | */ 112 | static inline void list_del(struct list_head *entry) 113 | { 114 | __list_del(entry->prev, entry->next); 115 | entry->next = LIST_POISON1; 116 | entry->prev = LIST_POISON2; 117 | } 118 | 119 | /** 120 | * list_empty - tests whether a list is empty 121 | * @head: the list to test. 122 | */ 123 | static inline int list_empty(const struct list_head *head) 124 | { 125 | return head->next == head; 126 | } 127 | 128 | /** 129 | * list_entry - get the struct for this entry 130 | * @ptr: the &struct list_head pointer. 131 | * @type: the type of the struct this is embedded in. 132 | * @member: the name of the list_struct within the struct. 133 | */ 134 | #define list_entry(ptr, type, member) \ 135 | container_of(ptr, type, member) 136 | 137 | /** 138 | * list_first_entry - get the first element from a list 139 | * @ptr: the list head to take the element from. 140 | * @type: the type of the struct this is embedded in. 141 | * @member: the name of the list_struct within the struct. 142 | * 143 | * Note, that list is expected to be not empty. 144 | */ 145 | #define list_first_entry(ptr, type, member) \ 146 | list_entry((ptr)->next, type, member) 147 | 148 | /** 149 | * list_next_entry - get the next element in list 150 | * @pos: the type * to cursor 151 | * @member: the name of the list_struct within the struct. 152 | */ 153 | #define list_next_entry(pos, member) \ 154 | list_entry((pos)->member.next, typeof(*(pos)), member) 155 | 156 | /** 157 | * list_for_each_entry - iterate over list of given type 158 | * @pos: the type * to use as a loop cursor. 159 | * @head: the head for your list. 160 | * @member: the name of the list_struct within the struct. 161 | */ 162 | #define list_for_each_entry(pos, head, member) \ 163 | for (pos = list_entry((head)->next, typeof(*pos), member); \ 164 | /*prefetch(pos->member.next),*/ &pos->member != (head); \ 165 | pos = list_entry(pos->member.next, typeof(*pos), member)) 166 | 167 | /** 168 | * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry 169 | * @pos: the type * to use as a loop cursor. 170 | * @n: another type * to use as temporary storage 171 | * @head: the head for your list. 172 | * @member: the name of the list_struct within the struct. 173 | */ 174 | #define list_for_each_entry_safe(pos, n, head, member) \ 175 | for (pos = list_first_entry(head, typeof(*pos), member), \ 176 | n = list_next_entry(pos, member); \ 177 | &pos->member != (head); \ 178 | pos = n, n = list_next_entry(n, member)) 179 | 180 | #endif /* __LIST_H */ 181 | -------------------------------------------------------------------------------- /src/library.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Justin Liu 3 | * Author: Justin Liu 4 | * https://github.com/rssnsj/minivtun 5 | */ 6 | 7 | #ifndef __LIBRARY_H 8 | #define __LIBRARY_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | typedef uint32_t __be32; 19 | typedef uint16_t __be16; 20 | typedef uint32_t __u32; 21 | typedef uint16_t __u16; 22 | typedef uint8_t __u8; 23 | 24 | typedef char bool; 25 | #define true 1 26 | #define false 0 27 | 28 | #define countof(arr) (sizeof(arr) / sizeof((arr)[0])) 29 | 30 | #define container_of(ptr, type, member) ({ \ 31 | const typeof(((type *)0)->member) * __mptr = (ptr); \ 32 | (type *)((char *)__mptr - offsetof(type, member)); }) 33 | 34 | #ifndef ETH_P_IP 35 | #define ETH_P_IP 0x0800 /* Internet Protocol packet */ 36 | #endif 37 | #ifndef ETH_P_IPV6 38 | #define ETH_P_IPV6 0x86dd /* IPv6 over bluebook */ 39 | #endif 40 | 41 | /* Dummy types for ethernet mode */ 42 | struct mac_addr { __u8 addr[6]; }; 43 | #define AF_MACADDR AF_PACKET 44 | 45 | /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ 46 | 47 | static inline bool is_in6_equal(const struct in6_addr *a1, const struct in6_addr *a2) 48 | { 49 | const __be32 *b1 = (__be32 *)a1, *b2 = (__be32 *)a2; 50 | if (b1[0] == b2[0] && b1[1] == b2[1] && 51 | b1[2] == b2[2] && b1[3] == b2[3]) { 52 | return true; 53 | } else { 54 | return false; 55 | } 56 | } 57 | 58 | static inline bool is_mac_equal(const struct mac_addr *a1, const struct mac_addr *a2) 59 | { 60 | const __be32 *b1 = (__be32 *)a1, *b2 = (__be32 *)a2; 61 | const __be16 *c1 = (__be16 *)(b1 + 1), *c2 = (__be16 *)(b2 + 1); 62 | if (*b1 == *b2 && *c1 == *c2) { 63 | return true; 64 | } else { 65 | return false; 66 | } 67 | } 68 | 69 | struct sockaddr_inx { 70 | union { 71 | struct sockaddr sa; 72 | struct sockaddr_in in; 73 | struct sockaddr_in6 in6; 74 | }; 75 | }; 76 | 77 | #define port_of_sockaddr(s) ((s)->sa.sa_family == AF_INET6 ? (s)->in6.sin6_port : (s)->in.sin_port) 78 | #define addr_of_sockaddr(s) ((s)->sa.sa_family == AF_INET6 ? (void *)&(s)->in6.sin6_addr : (void *)&(s)->in.sin_addr) 79 | #define sizeof_sockaddr(s) ((s)->sa.sa_family == AF_INET6 ? sizeof((s)->in6) : sizeof((s)->in)) 80 | 81 | static inline bool is_sockaddr_equal(const struct sockaddr_inx *a1, 82 | const struct sockaddr_inx *a2) 83 | { 84 | if (a1->sa.sa_family != a2->sa.sa_family) 85 | return false; 86 | 87 | if (a1->sa.sa_family == AF_INET6) { 88 | if (is_in6_equal(&a1->in6.sin6_addr, &a2->in6.sin6_addr) && 89 | a1->in6.sin6_port == a2->in6.sin6_port) { 90 | return true; 91 | } 92 | } else { 93 | if (a1->in.sin_addr.s_addr == a2->in.sin_addr.s_addr && 94 | a1->in.sin_port == a2->in.sin_port) { 95 | return true; 96 | } 97 | } 98 | 99 | return false; 100 | } 101 | 102 | int get_sockaddr_inx_pair(const char *pair, struct sockaddr_inx *sa, 103 | bool *is_random_port); 104 | int resolve_and_connect(const char *peer_addr_pair, struct sockaddr_inx *peer_addr); 105 | int tun_alloc(char *dev, bool tap_mode); 106 | 107 | void ip_addr_add_ipv4(const char *ifname, struct in_addr *local, 108 | struct in_addr *peer, int prefix); 109 | void ip_addr_add_ipv6(const char *ifname, struct in6_addr *local, int prefix); 110 | void ip_link_set_mtu(const char *ifname, unsigned mtu); 111 | void ip_link_set_txqueue_len(const char *ifname, unsigned qlen); 112 | void ip_link_set_updown(const char *ifname, bool up); 113 | void ip_route_add_ipvx(const char *ifname, int af, void *network, int prefix, 114 | int metric, const char *table); 115 | 116 | static inline bool is_valid_unicast_in(struct in_addr *in) 117 | { 118 | __u32 a = ntohl(in->s_addr); 119 | return ((a & 0xff000000) != 0x00000000) && 120 | ((a & 0xf0000000) != 0xe0000000); 121 | } 122 | 123 | static inline bool is_valid_unicast_in6(struct in6_addr *in6) 124 | { 125 | __u32 a0 = ntohl(((__be32 *)in6)[0]); 126 | return ((a0 & 0xff000000) != 0x00000000) && 127 | ((a0 & 0xff000000) != 0xff000000); 128 | } 129 | 130 | static inline bool is_valid_unicast_mac(struct mac_addr *mac) 131 | { 132 | if ((mac->addr[0] & 0x01)) { 133 | return false; 134 | } else { 135 | __be16 *a = (__be16 *)mac; 136 | if (a[0] == 0 && a[1] == 0 && a[2] == 0) { 137 | return false; 138 | } else { 139 | return true; 140 | } 141 | } 142 | } 143 | 144 | /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ 145 | 146 | #if defined(__APPLE__) || defined(__FreeBSD__) 147 | #include 148 | 149 | /* Protocol info prepended to the packets */ 150 | struct tun_pi { 151 | __u16 flags; 152 | __be16 proto; 153 | }; 154 | #define TUNSIFHEAD _IOW('t', 96, int) 155 | #define TUNGIFHEAD _IOR('t', 97, int) 156 | 157 | /* Conversion between address family & ethernet type. */ 158 | static inline void osx_af_to_ether(__be16 *proto) 159 | { 160 | switch (ntohs(*proto)) { 161 | case AF_INET: 162 | *proto = htons(ETH_P_IP); 163 | break; 164 | case AF_INET6: 165 | *proto = htons(ETH_P_IPV6); 166 | break; 167 | } 168 | } 169 | static inline void osx_ether_to_af(__be16 *proto) 170 | { 171 | switch (ntohs(*proto)) { 172 | case ETH_P_IP: 173 | *proto = htons(AF_INET); 174 | break; 175 | case ETH_P_IPV6: 176 | *proto = htons(AF_INET6); 177 | break; 178 | } 179 | } 180 | #else 181 | #include 182 | #include 183 | 184 | #define osx_af_to_ether(x) 185 | #define osx_ether_to_af(x) 186 | #endif 187 | 188 | /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ 189 | 190 | #define CRYPTO_DEFAULT_ALGORITHM "aes-128" 191 | #define CRYPTO_MAX_KEY_SIZE 32 192 | #define CRYPTO_MAX_BLOCK_SIZE 32 193 | 194 | struct name_cipher_pair { 195 | const char *name; 196 | const void *cipher; 197 | }; 198 | 199 | extern struct name_cipher_pair cipher_pairs[]; 200 | const void *get_crypto_type(const char *name); 201 | void datagram_encrypt(const void *key, const void *cptype, void *in, 202 | void *out, size_t *dlen); 203 | void datagram_decrypt(const void *key, const void *cptype, void *in, 204 | void *out, size_t *dlen); 205 | void fill_with_string_md5sum(const char *in, void *out, size_t outlen); 206 | 207 | /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ 208 | 209 | static inline long __sub_timeval_ms(const struct timeval *a, 210 | const struct timeval *b) 211 | { 212 | long secs = a->tv_sec - b->tv_sec; 213 | if (secs > 1000000) 214 | return 1000000000; 215 | if (secs < -1000000) 216 | return -1000000000; 217 | return secs * 1000 + (a->tv_usec - b->tv_usec) / 1000; 218 | } 219 | 220 | static inline int set_nonblock(int sockfd) 221 | { 222 | if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) 223 | return -1; 224 | return 0; 225 | } 226 | 227 | static inline void hexdump(void *d, size_t len) 228 | { 229 | unsigned char *s; 230 | for (s = d; len; len--, s++) 231 | printf("%02x ", (unsigned int)*s); 232 | printf("\n"); 233 | } 234 | 235 | void do_daemonize(void); 236 | 237 | #endif /* __LIBRARY_H */ 238 | 239 | -------------------------------------------------------------------------------- /src/minivtun.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Justin Liu 3 | * Author: Justin Liu 4 | * https://github.com/rssnsj/minivtun 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "minivtun.h" 20 | 21 | struct minivtun_config config = { 22 | .ifname = "", 23 | .tun_mtu = 1300, 24 | .tun_qlen = 1500, /* driver default: 500 */ 25 | .crypto_passwd = "", 26 | .crypto_type = NULL, 27 | .pid_file = NULL, 28 | .in_background = false, 29 | .tap_mode = false, 30 | .wait_dns = false, 31 | .exit_after = 0, 32 | .dynamic_link = false, 33 | .reconnect_timeo = 47, 34 | .max_droprate = 100, 35 | .max_rtt = 0, 36 | .keepalive_interval = 7, 37 | .health_assess_interval = 60, 38 | .nr_stats_buckets = 3, 39 | .health_file = NULL, 40 | .vt_metric = 0, 41 | .metric_stepping = 0, 42 | .vt_table = "", 43 | }; 44 | 45 | struct state_variables state = { 46 | .tunfd = -1, 47 | .sockfd = -1, 48 | }; 49 | 50 | static void vt_route_add(short af, void *n, int prefix, void *g) 51 | { 52 | union { 53 | struct in_addr in; 54 | struct in6_addr in6; 55 | } *network = n, *gateway = g; 56 | struct vt_route *rt; 57 | 58 | rt = malloc(sizeof(struct vt_route)); 59 | memset(rt, 0x0, sizeof(*rt)); 60 | 61 | rt->af = af; 62 | rt->prefix = prefix; 63 | if (af == AF_INET) { 64 | rt->network.in = network->in; 65 | rt->network.in.s_addr &= prefix ? htonl(~((1 << (32 - prefix)) - 1)) : 0; 66 | rt->gateway.in = gateway->in; 67 | } else if (af == AF_INET6) { 68 | int i; 69 | rt->network.in6 = network->in6; 70 | if (prefix < 128) { 71 | rt->network.in6.s6_addr[prefix / 8] &= ~((1 << (8 - prefix % 8)) - 1); 72 | for (i = prefix / 8 + 1; i < 16; i++) 73 | rt->network.in6.s6_addr[i] &= 0x00; 74 | } 75 | rt->gateway.in6 = gateway->in6; 76 | } else { 77 | assert(0); 78 | } 79 | 80 | /* Append to the list */ 81 | rt->next = config.vt_routes; 82 | config.vt_routes = rt; 83 | } 84 | 85 | static void parse_virtual_route(const char *arg) 86 | { 87 | char expr[80], *net, *pfx, *gw; 88 | short af = 0; 89 | int prefix = -1; 90 | union { 91 | struct in_addr in; 92 | struct in6_addr in6; 93 | } network, gateway; 94 | 95 | strncpy(expr, arg, sizeof(expr)); 96 | expr[sizeof(expr) - 1] = '\0'; 97 | 98 | /* Has gateway or not */ 99 | if ((gw = strchr(expr, '='))) 100 | *(gw++) = '\0'; 101 | 102 | /* Network or single IP/IPv6 address */ 103 | net = expr; 104 | if ((pfx = strchr(net, '/'))) { 105 | *(pfx++) = '\0'; 106 | prefix = strtol(pfx, NULL, 10); 107 | if (errno != ERANGE && prefix >= 0 && prefix <= 32 && 108 | inet_pton(AF_INET, net, &network)) { 109 | /* 192.168.0.0/16=10.7.7.1 */ 110 | af = AF_INET; 111 | } else if (errno != ERANGE && prefix >= 0 && prefix <= 128 && 112 | inet_pton(AF_INET6, net, &network)) { 113 | /* 2001:470:f9f2:ffff::/64=2001:470:f9f2::1 */ 114 | af = AF_INET6; 115 | } else { 116 | fprintf(stderr, "*** Not a valid route expression '%s'.\n", arg); 117 | exit(1); 118 | } 119 | } else { 120 | if (inet_pton(AF_INET, net, &network)) { 121 | /* 192.168.0.1=10.7.7.1 */ 122 | af = AF_INET; 123 | prefix = 32; 124 | } else if (inet_pton(AF_INET6, net, &network)) { 125 | /* 2001:470:f9f2:ffff::1=2001:470:f9f2::1 */ 126 | af = AF_INET6; 127 | prefix = 128; 128 | } else { 129 | fprintf(stderr, "*** Not a valid route expression '%s'.\n", arg); 130 | exit(1); 131 | } 132 | } 133 | 134 | /* Has gateway or not */ 135 | if (gw) { 136 | if (!inet_pton(af, gw, &gateway)) { 137 | fprintf(stderr, "*** Not a valid route expression '%s'.\n", arg); 138 | exit(1); 139 | } 140 | } else { 141 | memset(&gateway, 0x0, sizeof(gateway)); 142 | } 143 | 144 | vt_route_add(af, &network, prefix, &gateway); 145 | } 146 | 147 | static void print_help(int argc, char *argv[]) 148 | { 149 | int i; 150 | 151 | printf("Mini virtual tunneller in non-standard protocol.\n"); 152 | printf("Usage:\n"); 153 | printf(" %s [options]\n", argv[0]); 154 | printf("Options:\n"); 155 | printf(" -l, --local local IP:port for server to listen\n"); 156 | printf(" -r, --remote host:port of server to connect (brace with [] for bare IPv6)\n"); 157 | printf(" -n, --ifname virtual interface name\n"); 158 | printf(" -m, --mtu set MTU size, default: %u.\n", config.tun_mtu); 159 | printf(" -Q, --qlen set TX queue length, default: %u\n", config.tun_qlen); 160 | printf(" -a, --ipv4-addr pointopoint IPv4 pair of the virtual interface\n"); 161 | printf(" IPv4 address/prefix length pair\n"); 162 | printf(" -A, --ipv6-addr IPv6 address/prefix length pair\n"); 163 | printf(" -d, --daemon run as daemon process\n"); 164 | printf(" -p, --pidfile PID file of the daemon\n"); 165 | printf(" -E, --tap TAP mode\n"); 166 | printf(" -e, --key shared password for data encryption\n"); 167 | printf(" -t, --type encryption type\n"); 168 | printf(" -v, --route [=gw] attached IPv4/IPv6 route on this link, can be multiple\n"); 169 | printf(" -w, --wait-dns wait for DNS resolve ready after service started\n"); 170 | printf(" -D, --dynamic-link dynamic link mode, not bring up until data received\n"); 171 | printf(" -M, --metric [++stepping] metric of attached IPv4 routes\n"); 172 | printf(" -T, --table route table of the attached IPv4 routes\n"); 173 | printf(" -x, --exit-after force the client to exit after N seconds\n"); 174 | printf(" -H, --health-file file for writing real-time health data\n"); 175 | printf(" -R, --reconnect-timeo maximum inactive time (seconds) before reconnect, default: %u\n", config.reconnect_timeo); 176 | printf(" -K, --keepalive seconds between keep-alive tests, default: %u\n", config.keepalive_interval); 177 | printf(" -S, --health-assess seconds between health assess, default: %u\n", config.health_assess_interval); 178 | printf(" -B, --stats-buckets health data buckets, default: %u\n", config.nr_stats_buckets); 179 | printf(" -P, --max-droprate <1~100> maximum allowed packet drop percentage, default: %u%%\n", config.max_droprate); 180 | printf(" -X, --max-rtt maximum allowed echo delay (ms), default: unlimited\n"); 181 | printf(" -h, --help print this help\n"); 182 | printf("Supported encryption algorithms:\n"); 183 | printf(" "); 184 | for (i = 0; cipher_pairs[i].name; i++) 185 | printf("%s, ", cipher_pairs[i].name); 186 | printf("\n"); 187 | } 188 | 189 | int main(int argc, char *argv[]) 190 | { 191 | const char *tun_ip_config = NULL, *tun_ip6_config = NULL; 192 | const char *loc_addr_pair = NULL, *peer_addr_pair = NULL; 193 | const char *crypto_type = CRYPTO_DEFAULT_ALGORITHM; 194 | int override_mtu = 0, opt; 195 | struct timeval current; 196 | char *sp; 197 | 198 | static struct option long_opts[] = { 199 | { "local", required_argument, 0, 'l', }, 200 | { "remote", required_argument, 0, 'r', }, 201 | { "ipv4-addr", required_argument, 0, 'a', }, 202 | { "ipv6-addr", required_argument, 0, 'A', }, 203 | { "ifname", required_argument, 0, 'n', }, 204 | { "mtu", required_argument, 0, 'm', }, 205 | { "qlen", required_argument, 0, 'Q', }, 206 | { "pidfile", required_argument, 0, 'p', }, 207 | { "daemon", no_argument, 0, 'd', }, 208 | { "tap", no_argument, 0, 'E', }, 209 | { "key", required_argument, 0, 'e', }, 210 | { "type", required_argument, 0, 't', }, 211 | { "route", required_argument, 0, 'v', }, 212 | { "wait-dns", no_argument, 0, 'w', }, 213 | { "exit-after", required_argument, 0, 'x', }, 214 | { "dynamic-link", no_argument, 0, 'D', }, 215 | { "reconnect", required_argument, 0, 'R', }, 216 | { "keepalive", required_argument, 0, 'K', }, 217 | { "health-assess", required_argument, 0, 'S', }, 218 | { "stats-buckets", required_argument, 0, 'B', }, 219 | { "health-file", required_argument, 0, 'H', }, 220 | { "max-droprate", required_argument, 0, 'P', }, 221 | { "max-rtt", required_argument, 0, 'X', }, 222 | { "metric", required_argument, 0, 'M', }, 223 | { "table", required_argument, 0, 'T', }, 224 | { "help", no_argument, 0, 'h', }, 225 | { 0, 0, 0, 0, }, 226 | }; 227 | 228 | while ((opt = getopt_long(argc, argv, "r:l:a:A:m:Q:n:p:e:t:v:x:R:K:S:B:H:P:X:M:T:DEdwh", 229 | long_opts, NULL)) != -1) { 230 | switch (opt) { 231 | case 'l': 232 | loc_addr_pair = optarg; 233 | break; 234 | case 'r': 235 | peer_addr_pair = optarg; 236 | break; 237 | case 'a': 238 | tun_ip_config = optarg; 239 | break; 240 | case 'A': 241 | tun_ip6_config = optarg; 242 | break; 243 | case 'n': 244 | strncpy(config.ifname, optarg, sizeof(config.ifname) - 1); 245 | config.ifname[sizeof(config.ifname) - 1] = '\0'; 246 | break; 247 | case 'm': 248 | override_mtu = strtoul(optarg, NULL, 10); 249 | break; 250 | case 'Q': 251 | config.tun_qlen = strtoul(optarg, NULL, 10); 252 | break; 253 | case 'p': 254 | config.pid_file = optarg; 255 | break; 256 | case 'd': 257 | config.in_background = true; 258 | break; 259 | case 'E': 260 | config.tap_mode = true; 261 | break; 262 | case 'e': 263 | config.crypto_passwd = optarg; 264 | break; 265 | case 't': 266 | crypto_type = optarg; 267 | break; 268 | case 'v': 269 | parse_virtual_route(optarg); 270 | break; 271 | case 'w': 272 | config.wait_dns = true; 273 | break; 274 | case 'x': 275 | config.exit_after = strtoul(optarg, NULL, 10); 276 | break; 277 | case 'D': 278 | config.dynamic_link = true; 279 | break; 280 | case 'R': 281 | config.reconnect_timeo = strtoul(optarg, NULL, 10); 282 | break; 283 | case 'K': 284 | config.keepalive_interval = strtoul(optarg, NULL, 10); 285 | break; 286 | case 'S': 287 | config.health_assess_interval = strtoul(optarg, NULL, 10); 288 | break; 289 | case 'B': 290 | config.nr_stats_buckets = strtoul(optarg, NULL, 10); 291 | break; 292 | case 'H': 293 | config.health_file = optarg; 294 | break; 295 | case 'P': 296 | config.max_droprate = strtoul(optarg, NULL, 10); 297 | if (config.max_droprate < 1 || config.max_droprate > 100) { 298 | fprintf(stderr, "*** Acceptable '--max-droprate' values: 1~100.\n"); 299 | exit(1); 300 | } 301 | break; 302 | case 'X': 303 | config.max_rtt = strtoul(optarg, NULL, 10); 304 | break; 305 | case 'M': 306 | /* -M 200++5 */ 307 | if ((sp = strstr(optarg, "++"))) { 308 | char s[16]; 309 | memcpy(s, optarg, sp - optarg); 310 | s[sp - optarg] = '\0'; 311 | sp += 2; 312 | config.vt_metric = strtoul(s, NULL, 10); 313 | config.metric_stepping = strtol(sp, NULL, 10); 314 | } else { 315 | config.vt_metric = strtoul(optarg, NULL, 10); 316 | } 317 | break; 318 | case 'T': 319 | strncpy(config.vt_table, optarg, sizeof(config.vt_table)); 320 | config.vt_table[sizeof(config.vt_table) - 1] = '\0'; 321 | break; 322 | case 'h': 323 | print_help(argc, argv); 324 | exit(0); 325 | break; 326 | case '?': 327 | exit(1); 328 | } 329 | } 330 | 331 | if (override_mtu) { 332 | config.tun_mtu = override_mtu; 333 | } else { 334 | /* Default ethernet mode MTU: 1500 */ 335 | if (config.tap_mode) 336 | config.tun_mtu = 1500; 337 | } 338 | 339 | /* Random seed */ 340 | gettimeofday(¤t, NULL); 341 | srand(current.tv_sec ^ current.tv_usec ^ getpid()); 342 | 343 | if (config.ifname[0] == '\0') 344 | strcpy(config.ifname, "mv%d"); 345 | if ((state.tunfd = tun_alloc(config.ifname, config.tap_mode)) < 0) { 346 | fprintf(stderr, "*** open_tun() failed: %s.\n", strerror(errno)); 347 | exit(1); 348 | } 349 | 350 | openlog(config.ifname, LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_USER); 351 | 352 | /* Configure IPv4 address for the interface. */ 353 | if (tun_ip_config) { 354 | char s_lip[20], s_rip[20], *sp; 355 | struct in_addr vaddr; 356 | int pfxlen = 0; 357 | 358 | if (!(sp = strchr(tun_ip_config, '/'))) { 359 | fprintf(stderr, "*** Invalid IPv4 address pair: %s.\n", tun_ip_config); 360 | exit(1); 361 | } 362 | strncpy(s_lip, tun_ip_config, sp - tun_ip_config); 363 | s_lip[sp - tun_ip_config] = '\0'; 364 | sp++; 365 | strncpy(s_rip, sp, sizeof(s_rip)); 366 | s_rip[sizeof(s_rip) - 1] = '\0'; 367 | 368 | if (!inet_pton(AF_INET, s_lip, &vaddr)) { 369 | fprintf(stderr, "*** Invalid local IPv4 address: %s.\n", s_lip); 370 | exit(1); 371 | } 372 | config.tun_in_local = vaddr; 373 | if (inet_pton(AF_INET, s_rip, &vaddr)) { 374 | if (loc_addr_pair) { 375 | struct in_addr nz = { .s_addr = 0 }; 376 | vt_route_add(AF_INET, &nz, 0, &vaddr); 377 | } 378 | config.tun_in_peer = vaddr; 379 | } else if (sscanf(s_rip, "%d", &pfxlen) == 1 && pfxlen > 0 && pfxlen < 31 ) { 380 | config.tun_in_prefix = pfxlen; 381 | } else { 382 | fprintf(stderr, "*** Not a legal netmask or prefix length: %s.\n", s_rip); 383 | exit(1); 384 | } 385 | ip_addr_add_ipv4(config.ifname, &config.tun_in_local, 386 | &config.tun_in_peer, config.tun_in_prefix); 387 | } 388 | 389 | /* Configure IPv6 address if set. */ 390 | if (tun_ip6_config) { 391 | char s_lip[50], s_pfx[20], *sp; 392 | struct in6_addr vaddr; 393 | int pfxlen = 0; 394 | 395 | if (!(sp = strchr(tun_ip6_config, '/'))) { 396 | fprintf(stderr, "*** Invalid IPv6 address pair: %s.\n", tun_ip6_config); 397 | exit(1); 398 | } 399 | strncpy(s_lip, tun_ip6_config, sp - tun_ip6_config); 400 | s_lip[sp - tun_ip6_config] = '\0'; 401 | sp++; 402 | strncpy(s_pfx, sp, sizeof(s_pfx)); 403 | s_pfx[sizeof(s_pfx) - 1] = '\0'; 404 | 405 | if (!inet_pton(AF_INET6, s_lip, &vaddr)) { 406 | fprintf(stderr, "*** Invalid local IPv6 address: %s.\n", s_lip); 407 | exit(1); 408 | } 409 | config.tun_in6_local = vaddr; 410 | if (!(sscanf(s_pfx, "%d", &pfxlen) == 1 && pfxlen > 0 && pfxlen <= 128)) { 411 | fprintf(stderr, "*** Not a legal prefix length: %s.\n", s_pfx); 412 | exit(1); 413 | } 414 | config.tun_in6_prefix = pfxlen; 415 | 416 | ip_addr_add_ipv6(config.ifname, &config.tun_in6_local, config.tun_in6_prefix); 417 | } 418 | 419 | /* Set proper MTU size, and link up */ 420 | ip_link_set_mtu(config.ifname, config.tun_mtu); 421 | ip_link_set_txqueue_len(config.ifname, config.tun_qlen); 422 | ip_link_set_updown(config.ifname, true); 423 | 424 | if (enabled_encryption()) { 425 | fill_with_string_md5sum(config.crypto_passwd, config.crypto_key, CRYPTO_MAX_KEY_SIZE); 426 | if ((config.crypto_type = get_crypto_type(crypto_type)) == NULL) { 427 | fprintf(stderr, "*** No such encryption type defined: %s.\n", crypto_type); 428 | exit(1); 429 | } 430 | } else { 431 | memset(config.crypto_key, 0x0, CRYPTO_MAX_KEY_SIZE); 432 | fprintf(stderr, "*** WARNING: Transmission will not be encrypted.\n"); 433 | } 434 | 435 | if (loc_addr_pair) { 436 | run_server(loc_addr_pair); 437 | } else if (peer_addr_pair) { 438 | run_client(peer_addr_pair); 439 | } else { 440 | fprintf(stderr, "*** No valid local or peer address specified.\n"); 441 | exit(1); 442 | } 443 | 444 | /* Some cleanups before exit */ 445 | if (config.health_file) 446 | remove(config.health_file); 447 | closelog(); 448 | 449 | return 0; 450 | } 451 | 452 | -------------------------------------------------------------------------------- /src/client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Justin Liu 3 | * Author: Justin Liu 4 | * https://github.com/rssnsj/minivtun 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "minivtun.h" 20 | 21 | static bool rewind_dynamic_link_metric = false; 22 | 23 | static void handle_link_up(void) 24 | { 25 | struct vt_route *rt; 26 | 27 | ip_link_set_updown(config.ifname, true); 28 | 29 | if (config.metric_stepping) { 30 | syslog(LOG_INFO, "Link is up, metric: %u.", state.rt_metric); 31 | } else { 32 | syslog(LOG_INFO, "Link is up."); 33 | } 34 | 35 | /* Add IPv4 address if possible */ 36 | ip_addr_add_ipv4(config.ifname, &config.tun_in_local, 37 | &config.tun_in_peer, config.tun_in_prefix); 38 | 39 | /* Add IPv6 address if possible */ 40 | ip_addr_add_ipv6(config.ifname, &config.tun_in6_local, 41 | config.tun_in6_prefix); 42 | 43 | if (!config.tap_mode) { 44 | /* Attach the dynamic routes */ 45 | for (rt = config.vt_routes; rt; rt = rt->next) { 46 | ip_route_add_ipvx(config.ifname, rt->af, &rt->network, rt->prefix, 47 | state.rt_metric, config.vt_table[0] ? config.vt_table : NULL); 48 | } 49 | } 50 | } 51 | 52 | static void handle_link_down(void) 53 | { 54 | ip_link_set_updown(config.ifname, false); 55 | 56 | /* Lower route priority of the link by adding the stepping factor */ 57 | state.rt_metric += config.metric_stepping; 58 | 59 | syslog(LOG_INFO, "Link is down."); 60 | } 61 | 62 | static int network_receiving(void) 63 | { 64 | char read_buffer[NM_PI_BUFFER_SIZE], crypt_buffer[NM_PI_BUFFER_SIZE]; 65 | struct minivtun_msg *nmsg; 66 | struct tun_pi pi; 67 | void *out_data; 68 | size_t ip_dlen, out_dlen; 69 | struct sockaddr_inx real_peer; 70 | socklen_t real_peer_alen; 71 | struct iovec iov[2]; 72 | struct timeval __current; 73 | int rc; 74 | 75 | gettimeofday(&__current, NULL); 76 | 77 | real_peer_alen = sizeof(real_peer); 78 | rc = recvfrom(state.sockfd, &read_buffer, NM_PI_BUFFER_SIZE, 0, 79 | (struct sockaddr *)&real_peer, &real_peer_alen); 80 | if (rc <= 0) 81 | return -1; 82 | 83 | out_data = crypt_buffer; 84 | out_dlen = (size_t)rc; 85 | netmsg_to_local(read_buffer, &out_data, &out_dlen); 86 | nmsg = out_data; 87 | 88 | if (out_dlen < MINIVTUN_MSG_BASIC_HLEN) 89 | return 0; 90 | 91 | /* Verify password. */ 92 | if (memcmp(nmsg->hdr.auth_key, config.crypto_key, 93 | sizeof(nmsg->hdr.auth_key)) != 0) 94 | return 0; 95 | 96 | state.last_recv = __current; 97 | 98 | if (!state.health_based_link_up) { 99 | /* Call link-up scripts */ 100 | if (!state.is_link_ok) { 101 | if (config.dynamic_link) 102 | handle_link_up(); 103 | state.is_link_ok = true; 104 | } 105 | } 106 | 107 | switch (nmsg->hdr.opcode) { 108 | case MINIVTUN_MSG_IPDATA: 109 | if (config.tap_mode) { 110 | /* No ethernet packet is shorter than 14 bytes. */ 111 | if (out_dlen < MINIVTUN_MSG_IPDATA_OFFSET + 14) 112 | return 0; 113 | ip_dlen = out_dlen - MINIVTUN_MSG_IPDATA_OFFSET; 114 | nmsg->ipdata.proto = 0; 115 | } else { 116 | if (nmsg->ipdata.proto == htons(ETH_P_IP)) { 117 | /* No valid IP packet is shorter than 20 bytes. */ 118 | if (out_dlen < MINIVTUN_MSG_IPDATA_OFFSET + 20) 119 | return 0; 120 | } else if (nmsg->ipdata.proto == htons(ETH_P_IPV6)) { 121 | if (out_dlen < MINIVTUN_MSG_IPDATA_OFFSET + 40) 122 | return 0; 123 | } else { 124 | syslog(LOG_WARNING, "*** Invalid protocol: 0x%x.", ntohs(nmsg->ipdata.proto)); 125 | return 0; 126 | } 127 | 128 | ip_dlen = ntohs(nmsg->ipdata.ip_dlen); 129 | /* Drop incomplete IP packets. */ 130 | if (out_dlen - MINIVTUN_MSG_IPDATA_OFFSET < ip_dlen) 131 | return 0; 132 | } 133 | 134 | pi.flags = 0; 135 | pi.proto = nmsg->ipdata.proto; 136 | osx_ether_to_af(&pi.proto); 137 | iov[0].iov_base = π 138 | iov[0].iov_len = sizeof(pi); 139 | iov[1].iov_base = (char *)nmsg + MINIVTUN_MSG_IPDATA_OFFSET; 140 | iov[1].iov_len = ip_dlen; 141 | rc = writev(state.tunfd, iov, 2); 142 | break; 143 | case MINIVTUN_MSG_ECHO_ACK: 144 | if (state.has_pending_echo && nmsg->echo.id == state.pending_echo_id) { 145 | struct stats_data *st = &state.stats_buckets[state.current_bucket]; 146 | st->total_echo_rcvd++; 147 | st->total_rtt_ms += __sub_timeval_ms(&__current, &state.last_echo_sent); 148 | state.last_echo_recv = __current; 149 | state.has_pending_echo = false; 150 | } 151 | break; 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | static int tunnel_receiving(void) 158 | { 159 | char read_buffer[NM_PI_BUFFER_SIZE], crypt_buffer[NM_PI_BUFFER_SIZE]; 160 | struct tun_pi *pi = (void *)read_buffer; 161 | struct minivtun_msg nmsg; 162 | void *out_data; 163 | size_t ip_dlen, out_dlen; 164 | int rc; 165 | 166 | rc = read(state.tunfd, pi, NM_PI_BUFFER_SIZE); 167 | if (rc < sizeof(struct tun_pi)) 168 | return -1; 169 | 170 | osx_af_to_ether(&pi->proto); 171 | 172 | ip_dlen = (size_t)rc - sizeof(struct tun_pi); 173 | 174 | if (config.tap_mode) { 175 | if (ip_dlen < 14) 176 | return 0; 177 | } else { 178 | /* We only accept IPv4 or IPv6 frames. */ 179 | if (pi->proto == htons(ETH_P_IP)) { 180 | if (ip_dlen < 20) 181 | return 0; 182 | } else if (pi->proto == htons(ETH_P_IPV6)) { 183 | if (ip_dlen < 40) 184 | return 0; 185 | } else { 186 | syslog(LOG_WARNING, "*** Invalid protocol: 0x%x.", ntohs(pi->proto)); 187 | return 0; 188 | } 189 | } 190 | 191 | memset(&nmsg.hdr, 0x0, sizeof(nmsg.hdr)); 192 | nmsg.hdr.opcode = MINIVTUN_MSG_IPDATA; 193 | nmsg.hdr.seq = htons(state.xmit_seq++); 194 | memcpy(nmsg.hdr.auth_key, config.crypto_key, sizeof(nmsg.hdr.auth_key)); 195 | nmsg.ipdata.proto = pi->proto; 196 | nmsg.ipdata.ip_dlen = htons(ip_dlen); 197 | memcpy(nmsg.ipdata.data, pi + 1, ip_dlen); 198 | 199 | /* Do encryption. */ 200 | out_data = crypt_buffer; 201 | out_dlen = MINIVTUN_MSG_IPDATA_OFFSET + ip_dlen; 202 | local_to_netmsg(&nmsg, &out_data, &out_dlen); 203 | 204 | (void)send(state.sockfd, out_data, out_dlen, 0); 205 | 206 | return 0; 207 | } 208 | 209 | static void do_an_echo_request(void) 210 | { 211 | char in_data[64], crypt_buffer[64]; 212 | struct minivtun_msg *nmsg = (struct minivtun_msg *)in_data; 213 | void *out_msg; 214 | size_t out_len; 215 | __be32 r = rand(); 216 | 217 | memset(nmsg, 0x0, sizeof(nmsg->hdr) + sizeof(nmsg->echo)); 218 | nmsg->hdr.opcode = MINIVTUN_MSG_ECHO_REQ; 219 | nmsg->hdr.seq = htons(state.xmit_seq++); 220 | memcpy(nmsg->hdr.auth_key, config.crypto_key, sizeof(nmsg->hdr.auth_key)); 221 | if (!config.tap_mode) { 222 | nmsg->echo.loc_tun_in = config.tun_in_local; 223 | nmsg->echo.loc_tun_in6 = config.tun_in6_local; 224 | } 225 | nmsg->echo.id = r; 226 | 227 | out_msg = crypt_buffer; 228 | out_len = MINIVTUN_MSG_BASIC_HLEN + sizeof(nmsg->echo); 229 | local_to_netmsg(nmsg, &out_msg, &out_len); 230 | 231 | (void)send(state.sockfd, out_msg, out_len, 0); 232 | 233 | state.has_pending_echo = true; 234 | state.pending_echo_id = r; /* must be checked on ECHO_ACK */ 235 | state.stats_buckets[state.current_bucket].total_echo_sent++; 236 | } 237 | 238 | static void reset_state_on_reconnect(void) 239 | { 240 | struct timeval __current; 241 | int i; 242 | 243 | gettimeofday(&__current, NULL); 244 | state.xmit_seq = (__u16)rand(); 245 | state.last_recv = __current; 246 | state.last_echo_recv = __current; 247 | state.last_echo_sent = (struct timeval) { 0, 0 }; /* trigger the first echo */ 248 | state.last_health_assess = __current; 249 | 250 | /* Reset health assess variables */ 251 | state.has_pending_echo = false; 252 | state.pending_echo_id = 0; 253 | 254 | for (i = 0; i < config.nr_stats_buckets; i++) 255 | zero_stats_data(&state.stats_buckets[i]); 256 | state.current_bucket = 0; 257 | } 258 | 259 | static bool do_link_health_assess(void) 260 | { 261 | unsigned sent = 0, rcvd = 0, rtt = 0; 262 | unsigned drop_percent, rtt_average, i; 263 | bool health_ok = true; 264 | 265 | for (i = 0; i < config.nr_stats_buckets; i++) { 266 | struct stats_data *st = &state.stats_buckets[i]; 267 | sent += st->total_echo_sent; 268 | rcvd += st->total_echo_rcvd; 269 | rtt += st->total_rtt_ms; 270 | } 271 | /* Avoid generating negative values */ 272 | if (rcvd > sent) 273 | rcvd = sent; 274 | drop_percent = sent ? ((sent - rcvd) * 100 / sent) : 0; 275 | rtt_average = rcvd ? (rtt / rcvd) : 0; 276 | 277 | if (drop_percent > config.max_droprate) { 278 | health_ok = false; 279 | } else if (config.max_rtt && rtt_average > config.max_rtt) { 280 | health_ok = false; 281 | } 282 | 283 | /* Write into file */ 284 | if (config.health_file) { 285 | FILE *fp; 286 | remove(config.health_file); 287 | if ((fp = fopen(config.health_file, "w"))) { 288 | fprintf(fp, "%u,%u,%u,%u\n", sent, rcvd, drop_percent, rtt_average); 289 | fclose(fp); 290 | } 291 | } else { 292 | printf("Sent: %u, received: %u, drop: %u%%, RTT: %u\n", 293 | sent, rcvd, drop_percent, rtt_average); 294 | } 295 | 296 | /* Move to the next bucket and clear it */ 297 | state.current_bucket = (state.current_bucket + 1) % config.nr_stats_buckets; 298 | zero_stats_data(&state.stats_buckets[state.current_bucket]); 299 | 300 | if (!health_ok) { 301 | syslog(LOG_INFO, "Unhealthy state - sent: %u, received: %u, drop: %u%%, RTT: %u", 302 | sent, rcvd, drop_percent, rtt_average); 303 | } 304 | 305 | return health_ok; 306 | } 307 | 308 | static void usr1_signal_handler(int signum) 309 | { 310 | rewind_dynamic_link_metric = true; 311 | } 312 | 313 | int run_client(const char *peer_addr_pair) 314 | { 315 | char s_peer_addr[50]; 316 | struct timeval startup_time; 317 | 318 | /* Allocate statistics data buckets */ 319 | state.stats_buckets = malloc(sizeof(struct stats_data) * config.nr_stats_buckets); 320 | assert(state.stats_buckets); 321 | 322 | /* Remember the startup time for checking with 'config.exit_after' */ 323 | gettimeofday(&startup_time, NULL); 324 | 325 | /* Dynamic link mode */ 326 | state.is_link_ok = false; 327 | if (config.dynamic_link) 328 | ip_link_set_updown(config.ifname, false); 329 | 330 | /* Initial route metric */ 331 | state.rt_metric = config.vt_metric; 332 | 333 | if (config.wait_dns) { 334 | /* Connect later (state.sockfd < 0) */ 335 | state.sockfd = -1; 336 | gettimeofday(&state.last_health_assess, NULL); 337 | printf("Mini virtual tunneling client to '%s', interface: %s. \n", 338 | peer_addr_pair, config.ifname); 339 | } else if ((state.sockfd = resolve_and_connect(peer_addr_pair, &state.peer_addr)) >= 0) { 340 | /* DNS resolve OK, start service normally */ 341 | reset_state_on_reconnect(); 342 | inet_ntop(state.peer_addr.sa.sa_family, addr_of_sockaddr(&state.peer_addr), 343 | s_peer_addr, sizeof(s_peer_addr)); 344 | printf("Mini virtual tunneling client to %s:%u, interface: %s.\n", 345 | s_peer_addr, ntohs(port_of_sockaddr(&state.peer_addr)), config.ifname); 346 | } else if (state.sockfd == -EINVAL) { 347 | fprintf(stderr, "*** Invalid address pair '%s'.\n", peer_addr_pair); 348 | return -1; 349 | } else { 350 | fprintf(stderr, "*** Unable to connect to '%s'.\n", peer_addr_pair); 351 | return -1; 352 | } 353 | 354 | if (config.exit_after) 355 | printf("NOTICE: This client will exit autonomously in %u seconds.\n", config.exit_after); 356 | 357 | /* Run in background */ 358 | if (config.in_background) 359 | do_daemonize(); 360 | 361 | if (config.pid_file) { 362 | FILE *fp; 363 | if ((fp = fopen(config.pid_file, "w"))) { 364 | fprintf(fp, "%d\n", (int)getpid()); 365 | fclose(fp); 366 | } 367 | } 368 | 369 | signal(SIGUSR1, usr1_signal_handler); 370 | 371 | for (;;) { 372 | fd_set rset; 373 | struct timeval __current, timeo; 374 | int rc; 375 | bool need_reconnect = false; 376 | 377 | FD_ZERO(&rset); 378 | FD_SET(state.tunfd, &rset); 379 | if (state.sockfd >= 0) 380 | FD_SET(state.sockfd, &rset); 381 | 382 | timeo = (struct timeval) { 0, 500000 }; 383 | rc = select((state.tunfd > state.sockfd ? state.tunfd : state.sockfd) + 1, 384 | &rset, NULL, NULL, &timeo); 385 | if (rc < 0) { 386 | if (errno == EINTR || errno == ERESTART) { 387 | /* Fall through */ 388 | } else { 389 | fprintf(stderr, "*** select(): %s.\n", strerror(errno)); 390 | return -1; 391 | } 392 | } 393 | 394 | gettimeofday(&__current, NULL); 395 | 396 | /* Date corruption check */ 397 | if (timercmp(&state.last_recv, &__current, >)) 398 | state.last_recv = __current; 399 | if (timercmp(&state.last_echo_sent, &__current, >)) 400 | state.last_echo_sent = __current; 401 | if (timercmp(&state.last_echo_recv, &__current, >)) 402 | state.last_echo_recv = __current; 403 | 404 | /* Command line requires an "exit after N seconds" */ 405 | if (config.exit_after && __sub_timeval_ms(&__current, &startup_time) 406 | >= config.exit_after * 1000) { 407 | syslog(LOG_INFO, "User sets a force-to-exit after %u seconds. Exited.", 408 | config.exit_after); 409 | exit(0); 410 | } 411 | 412 | /* Check connection status or reconnect */ 413 | if (state.sockfd < 0 || 414 | (unsigned)__sub_timeval_ms(&__current, &state.last_echo_recv) 415 | >= config.reconnect_timeo * 1000) { 416 | need_reconnect = true; 417 | } else { 418 | /* Calculate packet loss and RTT for a link health assess */ 419 | if ((unsigned)__sub_timeval_ms(&__current, &state.last_health_assess) 420 | >= config.health_assess_interval * 1000) { 421 | state.last_health_assess = __current; 422 | if (do_link_health_assess()) { 423 | /* Call link-up scripts */ 424 | if (!state.is_link_ok) { 425 | if (config.dynamic_link) 426 | handle_link_up(); 427 | state.is_link_ok = true; 428 | } 429 | state.health_based_link_up = false; 430 | } else { 431 | need_reconnect = true; 432 | /* Keep link down until next health assess passes */ 433 | state.health_based_link_up = true; 434 | } 435 | } 436 | } 437 | 438 | /* Rewind to initial route metric and trigger a reconnect */ 439 | if (rewind_dynamic_link_metric) { 440 | rewind_dynamic_link_metric = false; 441 | if (state.is_link_ok) { 442 | if (config.dynamic_link) 443 | handle_link_down(); 444 | state.is_link_ok = false; 445 | } 446 | state.rt_metric = config.vt_metric; 447 | syslog(LOG_INFO, "Reset dynamic link route metric."); 448 | need_reconnect = true; 449 | } 450 | 451 | if (need_reconnect) { 452 | reconnect: 453 | /* Call link-down scripts */ 454 | if (state.is_link_ok) { 455 | if (config.dynamic_link) 456 | handle_link_down(); 457 | state.is_link_ok = false; 458 | } 459 | /* Reopen socket for a different local port */ 460 | if (state.sockfd >= 0) 461 | close(state.sockfd); 462 | if ((state.sockfd = resolve_and_connect(peer_addr_pair, &state.peer_addr)) < 0) { 463 | fprintf(stderr, "Unable to connect to '%s', retrying.\n", peer_addr_pair); 464 | sleep(5); 465 | goto reconnect; 466 | } 467 | reset_state_on_reconnect(); 468 | inet_ntop(state.peer_addr.sa.sa_family, addr_of_sockaddr(&state.peer_addr), 469 | s_peer_addr, sizeof(s_peer_addr)); 470 | syslog(LOG_INFO, "Reconnected to %s:%u.", s_peer_addr, 471 | ntohs(port_of_sockaddr(&state.peer_addr))); 472 | continue; 473 | } 474 | 475 | if (state.sockfd >= 0 && FD_ISSET(state.sockfd, &rset)) { 476 | rc = network_receiving(); 477 | } 478 | 479 | if (FD_ISSET(state.tunfd, &rset)) { 480 | rc = tunnel_receiving(); 481 | assert(rc == 0); 482 | } 483 | 484 | /* Trigger an echo test */ 485 | if (state.sockfd >= 0 && 486 | (unsigned)__sub_timeval_ms(&__current, &state.last_echo_sent) 487 | >= config.keepalive_interval * 1000) { 488 | do_an_echo_request(); 489 | state.last_echo_sent = __current; 490 | } 491 | } 492 | 493 | return 0; 494 | } 495 | -------------------------------------------------------------------------------- /src/library.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Justin Liu 3 | * Author: Justin Liu 4 | * https://github.com/rssnsj/minivtun 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "library.h" 21 | 22 | struct name_cipher_pair cipher_pairs[] = { 23 | { "aes-128", EVP_aes_128_cbc, }, 24 | { "aes-256", EVP_aes_256_cbc, }, 25 | { "des", EVP_des_cbc, }, 26 | { "desx", EVP_desx_cbc, }, 27 | { "rc4", EVP_rc4, }, 28 | { NULL, NULL, }, 29 | }; 30 | 31 | const void *get_crypto_type(const char *name) 32 | { 33 | const EVP_CIPHER *cipher = NULL; 34 | int i; 35 | 36 | for (i = 0; cipher_pairs[i].name; i++) { 37 | if (strcasecmp(cipher_pairs[i].name, name) == 0) { 38 | cipher = ((const EVP_CIPHER *(*)(void))cipher_pairs[i].cipher)(); 39 | break; 40 | } 41 | } 42 | 43 | if (cipher) { 44 | assert(EVP_CIPHER_key_length(cipher) <= CRYPTO_MAX_KEY_SIZE); 45 | assert(EVP_CIPHER_iv_length(cipher) <= CRYPTO_MAX_BLOCK_SIZE); 46 | return cipher; 47 | } else { 48 | return NULL; 49 | } 50 | } 51 | 52 | static const char crypto_ivec_initdata[CRYPTO_MAX_BLOCK_SIZE] = { 53 | 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 54 | 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 55 | 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 56 | 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 57 | }; 58 | 59 | #define CRYPTO_DATA_PADDING(data, dlen, bs) \ 60 | do { \ 61 | size_t last_len = *(dlen) % (bs); \ 62 | if (last_len) { \ 63 | size_t padding_len = bs - last_len; \ 64 | memset((char *)data + *(dlen), 0x0, padding_len); \ 65 | *(dlen) += padding_len; \ 66 | } \ 67 | } while(0) 68 | 69 | void datagram_encrypt(const void *key, const void *cptype, void *in, 70 | void *out, size_t *dlen) 71 | { 72 | size_t iv_len = EVP_CIPHER_iv_length((const EVP_CIPHER *)cptype); 73 | EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); 74 | unsigned char iv[CRYPTO_MAX_KEY_SIZE]; 75 | int outl = 0, outl2 = 0; 76 | 77 | if (iv_len == 0) 78 | iv_len = 16; 79 | 80 | memcpy(iv, crypto_ivec_initdata, iv_len); 81 | CRYPTO_DATA_PADDING(in, dlen, iv_len); 82 | EVP_CIPHER_CTX_init(ctx); 83 | assert(EVP_EncryptInit_ex(ctx, cptype, NULL, key, iv)); 84 | EVP_CIPHER_CTX_set_padding(ctx, 0); 85 | assert(EVP_EncryptUpdate(ctx, out, &outl, in, *dlen)); 86 | assert(EVP_EncryptFinal_ex(ctx, (unsigned char *)out + outl, &outl2)); 87 | EVP_CIPHER_CTX_cleanup(ctx); 88 | EVP_CIPHER_CTX_free(ctx); 89 | 90 | *dlen = (size_t)(outl + outl2); 91 | } 92 | 93 | void datagram_decrypt(const void *key, const void *cptype, void *in, 94 | void *out, size_t *dlen) 95 | { 96 | size_t iv_len = EVP_CIPHER_iv_length((const EVP_CIPHER *)cptype); 97 | EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); 98 | unsigned char iv[CRYPTO_MAX_KEY_SIZE]; 99 | int outl = 0, outl2 = 0; 100 | 101 | if (iv_len == 0) 102 | iv_len = 16; 103 | 104 | memcpy(iv, crypto_ivec_initdata, iv_len); 105 | CRYPTO_DATA_PADDING(in, dlen, iv_len); 106 | EVP_CIPHER_CTX_init(ctx); 107 | assert(EVP_DecryptInit_ex(ctx, cptype, NULL, key, iv)); 108 | EVP_CIPHER_CTX_set_padding(ctx, 0); 109 | assert(EVP_DecryptUpdate(ctx, out, &outl, in, *dlen)); 110 | assert(EVP_DecryptFinal_ex(ctx, (unsigned char *)out + outl, &outl2)); 111 | EVP_CIPHER_CTX_cleanup(ctx); 112 | EVP_CIPHER_CTX_free(ctx); 113 | 114 | *dlen = (size_t)(outl + outl2); 115 | } 116 | 117 | void fill_with_string_md5sum(const char *in, void *out, size_t outlen) 118 | { 119 | char *outp = out, *oute = outp + outlen; 120 | MD5_CTX ctx; 121 | 122 | MD5_Init(&ctx); 123 | MD5_Update(&ctx, in, strlen(in)); 124 | MD5_Final(out, &ctx); 125 | 126 | /* Fill in remaining buffer with repeated data. */ 127 | for (outp += 16; outp < oute; outp += 16) { 128 | size_t bs = (oute - outp >= 16) ? 16 : (oute - outp); 129 | memcpy(outp, out, bs); 130 | } 131 | } 132 | 133 | /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ 134 | 135 | int get_sockaddr_inx_pair(const char *pair, struct sockaddr_inx *sa, 136 | bool *is_random_port) 137 | { 138 | struct addrinfo hints, *result; 139 | char host[51] = "", s_port[21] = ""; 140 | unsigned port = 0; 141 | int rc; 142 | 143 | *is_random_port = false; 144 | 145 | /* Only getting an INADDR_ANY address. */ 146 | if (pair == NULL) { 147 | struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; 148 | sa4->sin_family = AF_INET; 149 | sa4->sin_addr.s_addr = 0; 150 | sa4->sin_port = 0; 151 | return 0; 152 | } 153 | 154 | if (sscanf(pair, "[%50[^]]]:%20s", host, s_port) == 2 || 155 | sscanf(pair, "%50[^:]:%20s", host, s_port) == 2) { 156 | unsigned end_port = 0; 157 | if (sscanf(s_port, "%u-%u", &port, &end_port) == 2) { 158 | /* Port range */ 159 | if (!(port > 0 && end_port >= port && end_port <= 65535)) 160 | return -EINVAL; 161 | port += rand() % (end_port - port + 1); 162 | *is_random_port = true; 163 | } else { 164 | /* Single port */ 165 | port = strtoul(s_port, NULL, 10); 166 | if (port > 65535) 167 | return -EINVAL; 168 | } 169 | } else { 170 | /** 171 | * Address with a single port number, usually for 172 | * local IPv4 listen address. 173 | * e.g., "10000" is considered as "0.0.0.0:10000" 174 | */ 175 | strcpy(host, "0.0.0.0"); 176 | port = strtoul(pair, NULL, 10); 177 | if (port > 65535) 178 | return -EINVAL; 179 | } 180 | 181 | sprintf(s_port, "%u", port); 182 | 183 | memset(&hints, 0, sizeof(struct addrinfo)); 184 | hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 185 | hints.ai_socktype = SOCK_STREAM; 186 | hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ 187 | hints.ai_protocol = 0; /* Any protocol */ 188 | hints.ai_canonname = NULL; 189 | hints.ai_addr = NULL; 190 | hints.ai_next = NULL; 191 | 192 | if ((rc = getaddrinfo(host, s_port, &hints, &result))) 193 | return -EAGAIN; 194 | 195 | /* Get the first resolution. */ 196 | memcpy(sa, result->ai_addr, result->ai_addrlen); 197 | 198 | freeaddrinfo(result); 199 | return 0; 200 | } 201 | 202 | int resolve_and_connect(const char *peer_addr_pair, struct sockaddr_inx *peer_addr) 203 | { 204 | int sockfd, rc; 205 | bool is_random_port = false; 206 | 207 | if ((rc = get_sockaddr_inx_pair(peer_addr_pair, peer_addr, &is_random_port)) < 0) 208 | return rc; 209 | 210 | if ((sockfd = socket(peer_addr->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 211 | fprintf(stderr, "*** socket() failed: %s.\n", strerror(errno)); 212 | return -1; 213 | } 214 | if (connect(sockfd, (struct sockaddr *)peer_addr, sizeof_sockaddr(peer_addr)) < 0) { 215 | close(sockfd); 216 | return -EAGAIN; 217 | } 218 | set_nonblock(sockfd); 219 | 220 | return sockfd; 221 | } 222 | 223 | int tun_alloc(char *dev, bool tap_mode) 224 | { 225 | int fd = -1, err; 226 | #if defined(__APPLE__) || defined(__FreeBSD__) 227 | int b_enable = 1, i; 228 | 229 | for (i = 0; i < 8; i++) { 230 | char dev_path[20]; 231 | sprintf(dev_path, "/dev/tun%d", i); 232 | if ((fd = open(dev_path, O_RDWR)) >= 0) { 233 | sprintf(dev, "tun%d", i); 234 | break; 235 | } 236 | } 237 | if (fd < 0) 238 | return -EINVAL; 239 | if ((err = ioctl(fd, TUNSIFHEAD, &b_enable)) < 0) { 240 | close(fd); 241 | return err; 242 | } 243 | #else 244 | struct ifreq ifr; 245 | 246 | if ((fd = open("/dev/net/tun", O_RDWR)) >= 0) { 247 | } else if ((fd = open("/dev/tun", O_RDWR)) >= 0) { 248 | } else { 249 | return -EINVAL; 250 | } 251 | 252 | memset(&ifr, 0, sizeof(ifr)); 253 | if (tap_mode) { 254 | ifr.ifr_flags = IFF_TAP; 255 | } else { 256 | ifr.ifr_flags = IFF_TUN; 257 | } 258 | if (dev[0]) 259 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); 260 | if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { 261 | close(fd); 262 | return err; 263 | } 264 | strcpy(dev, ifr.ifr_name); 265 | #endif 266 | 267 | return fd; 268 | } 269 | 270 | /* Like strncpy but make sure the resulting string is always 0 terminated. */ 271 | static char *safe_strncpy(char *dst, const char *src, size_t size) 272 | { 273 | dst[size - 1] = '\0'; 274 | return strncpy(dst, src, size - 1); 275 | } 276 | 277 | /* Set a certain interface flag. */ 278 | static int __set_flag(int sockfd, const char *ifname, short flag) 279 | { 280 | struct ifreq ifr; 281 | 282 | safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 283 | if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { 284 | fprintf(stderr, "*** SIOCGIFFLAGS: %s.\n", strerror(errno)); 285 | return -1; 286 | } 287 | safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 288 | ifr.ifr_flags |= flag; 289 | if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { 290 | fprintf(stderr, "*** SIOCSIFFLAGS: %s.\n", strerror(errno)); 291 | return -1; 292 | } 293 | return 0; 294 | } 295 | /* Clear a certain interface flag. */ 296 | static int __clr_flag(int sockfd, const char *ifname, short flag) 297 | { 298 | struct ifreq ifr; 299 | 300 | safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 301 | if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { 302 | fprintf(stderr, "*** SIOCGIFFLAGS: %s.\n", strerror(errno)); 303 | return -1; 304 | } 305 | safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 306 | ifr.ifr_flags &= ~flag; 307 | if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { 308 | fprintf(stderr, "*** SIOCSIFFLAGS: %s.\n", strerror(errno)); 309 | return -1; 310 | } 311 | return 0; 312 | } 313 | 314 | static int __set_ip_using(int sockfd, const char *name, int c, 315 | const struct in_addr *addr) 316 | { 317 | struct sockaddr_in sin; 318 | struct ifreq ifr; 319 | 320 | safe_strncpy(ifr.ifr_name, name, IFNAMSIZ); 321 | memset(&sin, 0, sizeof(struct sockaddr)); 322 | sin.sin_family = AF_INET; 323 | sin.sin_addr = *addr; 324 | memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); 325 | if (ioctl(sockfd, c, &ifr) < 0) 326 | return -1; 327 | return 0; 328 | } 329 | 330 | static int __get_ifindex(const char *ifname) 331 | { 332 | struct ifreq ifr; 333 | int sockfd; 334 | 335 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 336 | return -1; 337 | memset(&ifr, 0x0, sizeof(ifr)); 338 | safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 339 | if (ioctl(sockfd, SIOGIFINDEX, &ifr) < 0) { 340 | close(sockfd); 341 | return -1; 342 | } 343 | close(sockfd); 344 | return ifr.ifr_ifindex; 345 | } 346 | 347 | void ip_addr_add_ipv4(const char *ifname, struct in_addr *local, 348 | struct in_addr *peer, int prefix) 349 | { 350 | int sockfd; 351 | 352 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 353 | return; 354 | if (is_valid_unicast_in(local) && is_valid_unicast_in(peer)) { 355 | __set_ip_using(sockfd, ifname, SIOCSIFADDR, local); 356 | __set_ip_using(sockfd, ifname, SIOCSIFDSTADDR, peer); 357 | __set_flag(sockfd, ifname, IFF_POINTOPOINT | IFF_UP | IFF_RUNNING); /* same as ifconfig */ 358 | } else if (is_valid_unicast_in(local) && prefix > 0) { 359 | struct in_addr mask; 360 | mask.s_addr = htonl(~((1 << (32 - prefix)) - 1)); 361 | __set_ip_using(sockfd, ifname, SIOCSIFADDR, local); 362 | __set_ip_using(sockfd, ifname, SIOCSIFNETMASK, &mask); 363 | __set_flag(sockfd, ifname, IFF_UP | IFF_RUNNING); /* same as ifconfig */ 364 | } 365 | close(sockfd); 366 | } 367 | 368 | void ip_addr_add_ipv6(const char *ifname, struct in6_addr *local, int prefix) 369 | { 370 | #ifndef _LINUX_IN6_H 371 | /* This is in linux/include/net/ipv6.h */ 372 | struct in6_ifreq { 373 | struct in6_addr ifr6_addr; 374 | __u32 ifr6_prefixlen; 375 | unsigned int ifr6_ifindex; 376 | }; 377 | #endif 378 | struct in6_ifreq ifr6; 379 | int sockfd, ifindex; 380 | 381 | if ((ifindex = __get_ifindex(ifname)) < 0) { 382 | fprintf(stderr, "*** SIOGIFINDEX: %s.\n", strerror(errno)); 383 | return; 384 | } 385 | if ((sockfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 386 | return; 387 | if (is_valid_unicast_in6(local) && prefix > 0) { 388 | memcpy(&ifr6.ifr6_addr, local, sizeof(*local)); 389 | ifr6.ifr6_ifindex = ifindex; 390 | ifr6.ifr6_prefixlen = prefix; 391 | if (ioctl(sockfd, SIOCSIFADDR, &ifr6) < 0) 392 | fprintf(stderr, "*** SIOCSIFADDR: %s.\n", strerror(errno)); 393 | } 394 | close(sockfd); 395 | } 396 | 397 | void ip_link_set_mtu(const char *ifname, unsigned mtu) 398 | { 399 | struct ifreq ifr; 400 | int sockfd; 401 | 402 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 403 | return; 404 | safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 405 | ifr.ifr_mtu = mtu; 406 | if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) 407 | fprintf(stderr, "*** SIOCSIFMTU, %u: %s.\n", mtu, strerror(errno)); 408 | close(sockfd); 409 | } 410 | 411 | void ip_link_set_txqueue_len(const char *ifname, unsigned qlen) 412 | { 413 | struct ifreq ifr; 414 | int sockfd; 415 | 416 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 417 | return; 418 | safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 419 | ifr.ifr_qlen = qlen; 420 | if (ioctl(sockfd, SIOCSIFTXQLEN, &ifr) < 0) 421 | fprintf(stderr, "*** SIOCSIFTXQLEN: %s\n", strerror(errno)); 422 | close(sockfd); 423 | } 424 | 425 | void ip_link_set_updown(const char *ifname, bool up) 426 | { 427 | int sockfd; 428 | 429 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 430 | return; 431 | if (up) { 432 | __set_flag(sockfd, ifname, IFF_UP | IFF_RUNNING); 433 | } else { 434 | __clr_flag(sockfd, ifname, IFF_UP); 435 | } 436 | close(sockfd); 437 | } 438 | 439 | #if defined(__APPLE__) || defined(__FreeBSD__) 440 | void ip_route_add_ipvx(const char *ifname, int af, void *network, 441 | int prefix, int metric, const char *table) 442 | { 443 | char cmd[256], __net[64] = ""; 444 | inet_ntop(af, network, __net, sizeof(__net)); 445 | sprintf(cmd, "route %s add -net %s/%d %s metric %d", 446 | af == AF_INET6 ? "-A inet6" : "", __net, prefix, ifname, metric); 447 | (void)system(cmd); 448 | } 449 | #else 450 | void ip_route_add_ipvx(const char *ifname, int af, void *network, 451 | int prefix, int metric, const char *table) 452 | { 453 | /* Fallback to 'ip route ...' if adding to another table */ 454 | if (table) { 455 | char cmd[256], __net[64] = ""; 456 | inet_ntop(af, network, __net, sizeof(__net)); 457 | sprintf(cmd, "ip %s route add %s/%d dev %s metric %d table %s", 458 | af == AF_INET6 ? "-6" : "", __net, prefix, ifname, metric, table); 459 | (void)system(cmd); 460 | } else if (af == AF_INET) { 461 | /* IPv4 */ 462 | struct rtentry rt; 463 | int sockfd; 464 | 465 | memset(&rt, 0x0, sizeof(rt)); 466 | rt.rt_flags = RTF_UP; 467 | if (prefix == 32) 468 | rt.rt_flags |= RTF_HOST; 469 | ((struct sockaddr_in *)&rt.rt_dst)->sin_family = AF_INET; 470 | ((struct sockaddr_in *)&rt.rt_dst)->sin_addr = *(struct in_addr *)network; 471 | ((struct sockaddr_in *)&rt.rt_genmask)->sin_family = AF_INET; 472 | ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = 473 | prefix ? htonl(~((1 << (32 - prefix)) - 1)) : 0; 474 | rt.rt_metric = metric + 1; /* +1 for binary compatibility! */ 475 | rt.rt_dev = (char *)ifname; 476 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 477 | fprintf(stderr, "*** socket(): %s\n", strerror(errno)); 478 | return; 479 | } 480 | ioctl(sockfd, SIOCADDRT, &rt); 481 | close(sockfd); 482 | } else if (af == AF_INET6) { 483 | /* IPv6 */ 484 | struct in6_rtmsg rt6; 485 | int sockfd, ifindex; 486 | 487 | if ((ifindex = __get_ifindex(ifname)) < 0) { 488 | fprintf(stderr, "*** SIOGIFINDEX: %s.\n", strerror(errno)); 489 | return; 490 | } 491 | 492 | memset(&rt6, 0x0, sizeof(rt6)); 493 | memcpy(&rt6.rtmsg_dst, network, sizeof(struct in6_addr)); 494 | rt6.rtmsg_flags = RTF_UP; 495 | if (prefix == 128) 496 | rt6.rtmsg_flags |= RTF_HOST; 497 | rt6.rtmsg_metric = metric; 498 | rt6.rtmsg_dst_len = prefix; 499 | rt6.rtmsg_ifindex = ifindex; 500 | 501 | if ((sockfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 502 | fprintf(stderr, "*** socket(): %s\n", strerror(errno)); 503 | return; 504 | } 505 | ioctl(sockfd, SIOCADDRT, &rt6); 506 | close(sockfd); 507 | } 508 | } 509 | #endif 510 | 511 | void do_daemonize(void) 512 | { 513 | pid_t pid; 514 | int fd; 515 | 516 | /* Fork off the parent process */ 517 | if ((pid = fork()) < 0) { 518 | /* Error */ 519 | fprintf(stderr, "*** fork() error: %s.\n", strerror(errno)); 520 | exit(1); 521 | } else if (pid > 0) { 522 | /* Let the parent process terminate */ 523 | exit(0); 524 | } 525 | 526 | /* Do this before child process quits to prevent duplicate printf output */ 527 | if ((fd = open("/dev/null", O_RDWR)) >= 0) { 528 | dup2(fd, 0); 529 | dup2(fd, 1); 530 | dup2(fd, 2); 531 | if (fd > 2) 532 | close(fd); 533 | } 534 | 535 | /* Let the child process become session leader */ 536 | if (setsid() < 0) 537 | exit(1); 538 | 539 | if ((pid = fork()) < 0) { 540 | /* Error */ 541 | exit(1); 542 | } else if (pid > 0) { 543 | /* Let the parent process terminate */ 544 | exit(0); 545 | } 546 | 547 | /* OK, set up the grandchild process */ 548 | chdir("/tmp"); 549 | } 550 | 551 | -------------------------------------------------------------------------------- /src/server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Justin Liu 3 | * Author: Justin Liu 4 | * https://github.com/rssnsj/minivtun 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "list.h" 20 | #include "jhash.h" 21 | #include "minivtun.h" 22 | 23 | static __u32 hash_initval = 0; 24 | 25 | static void *vt_route_lookup(short af, const void *a) 26 | { 27 | const union { 28 | struct in_addr in; 29 | struct in6_addr in6; 30 | } *addr = a; 31 | struct vt_route *rt; 32 | 33 | for (rt = config.vt_routes; rt; rt = rt->next) { 34 | if (rt->af != af) 35 | continue; 36 | if (af == AF_INET) { 37 | if (rt->prefix == 0) { 38 | return &rt->gateway.in; 39 | } else { 40 | in_addr_t m = rt->prefix ? htonl(~((1 << (32 - rt->prefix)) - 1)) : 0; 41 | if ((addr->in.s_addr & m) == rt->network.in.s_addr) 42 | return &rt->gateway.in; 43 | } 44 | } else if (af == AF_INET6) { 45 | if (rt->prefix == 0) { 46 | return &rt->gateway.in6; 47 | } else if (rt->prefix < 128) { 48 | struct in6_addr n = addr->in6; 49 | int i; 50 | n.s6_addr[rt->prefix / 8] &= ~((1 << (8 - rt->prefix % 8)) - 1); 51 | for (i = rt->prefix / 8 + 1; i < 16; i++) 52 | n.s6_addr[i] &= 0x00; 53 | if (is_in6_equal(&n, &rt->network.in6)) 54 | return &rt->gateway.in6; 55 | } 56 | 57 | } 58 | } 59 | 60 | return NULL; 61 | } 62 | 63 | /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ 64 | 65 | struct ra_entry { 66 | struct list_head list; 67 | struct sockaddr_inx real_addr; 68 | struct timeval last_recv; 69 | __u16 xmit_seq; 70 | int refs; 71 | }; 72 | 73 | /* Hash table for dedicated clients (real addresses). */ 74 | #define RA_SET_HASH_SIZE (1 << 3) 75 | #define RA_SET_LIMIT_EACH_WALK (10) 76 | static struct list_head ra_set_hbase[RA_SET_HASH_SIZE]; 77 | static unsigned ra_set_len; 78 | 79 | static inline __u32 real_addr_hash(const struct sockaddr_inx *sa) 80 | { 81 | if (sa->sa.sa_family == AF_INET6) { 82 | return jhash_2words(sa->sa.sa_family, sa->in6.sin6_port, 83 | jhash2((__u32 *)&sa->in6.sin6_addr, 4, hash_initval)); 84 | } else { 85 | return jhash_3words(sa->sa.sa_family, sa->in.sin_port, 86 | sa->in.sin_addr.s_addr, hash_initval); 87 | } 88 | } 89 | 90 | static struct ra_entry *ra_get_or_create(const struct sockaddr_inx *sa) 91 | { 92 | struct list_head *chain = &ra_set_hbase[ 93 | real_addr_hash(sa) & (RA_SET_HASH_SIZE - 1)]; 94 | struct ra_entry *re; 95 | char s_real_addr[50]; 96 | 97 | list_for_each_entry (re, chain, list) { 98 | if (is_sockaddr_equal(&re->real_addr, sa)) { 99 | re->refs++; 100 | return re; 101 | } 102 | } 103 | 104 | if ((re = malloc(sizeof(*re))) == NULL) { 105 | syslog(LOG_ERR, "*** [%s] malloc(): %s.", __FUNCTION__, strerror(errno)); 106 | return NULL; 107 | } 108 | 109 | re->real_addr = *sa; 110 | re->xmit_seq = (__u16)rand(); 111 | re->refs = 1; 112 | list_add_tail(&re->list, chain); 113 | ra_set_len++; 114 | 115 | inet_ntop(re->real_addr.sa.sa_family, addr_of_sockaddr(&re->real_addr), 116 | s_real_addr, sizeof(s_real_addr)); 117 | syslog(LOG_INFO, "New client [%s:%u]", s_real_addr, 118 | port_of_sockaddr(&re->real_addr)); 119 | 120 | return re; 121 | } 122 | 123 | static inline void ra_put_no_free(struct ra_entry *re) 124 | { 125 | assert(re->refs > 0); 126 | re->refs--; 127 | } 128 | 129 | static inline void ra_entry_release(struct ra_entry *re) 130 | { 131 | char s_real_addr[50]; 132 | 133 | assert(re->refs == 0); 134 | list_del(&re->list); 135 | ra_set_len--; 136 | 137 | inet_ntop(re->real_addr.sa.sa_family, addr_of_sockaddr(&re->real_addr), 138 | s_real_addr, sizeof(s_real_addr)); 139 | syslog(LOG_INFO, "Recycled client [%s:%u]", s_real_addr, 140 | ntohs(port_of_sockaddr(&re->real_addr))); 141 | 142 | free(re); 143 | } 144 | 145 | struct tun_addr { 146 | unsigned short af; 147 | union { 148 | struct in_addr in; 149 | struct in6_addr in6; 150 | struct mac_addr mac; 151 | }; 152 | }; 153 | struct tun_client { 154 | struct list_head list; 155 | struct tun_addr virt_addr; 156 | struct ra_entry *ra; 157 | struct timeval last_recv; 158 | }; 159 | 160 | /* Hash table of virtual address in tunnel. */ 161 | #define VA_MAP_HASH_SIZE (1 << 4) 162 | #define VA_MAP_LIMIT_EACH_WALK (10) 163 | static struct list_head va_map_hbase[VA_MAP_HASH_SIZE]; 164 | static unsigned va_map_len; 165 | 166 | static inline void init_va_ra_maps(void) 167 | { 168 | int i; 169 | 170 | for (i = 0; i < VA_MAP_HASH_SIZE; i++) 171 | INIT_LIST_HEAD(&va_map_hbase[i]); 172 | va_map_len = 0; 173 | 174 | for (i = 0; i < RA_SET_HASH_SIZE; i++) 175 | INIT_LIST_HEAD(&ra_set_hbase[i]); 176 | ra_set_len = 0; 177 | } 178 | 179 | static inline __u32 tun_addr_hash(const struct tun_addr *addr) 180 | { 181 | if (addr->af == AF_INET) { 182 | return jhash_2words(addr->af, addr->in.s_addr, hash_initval); 183 | } else if (addr->af == AF_INET6) { 184 | const __be32 *a = (void *)&addr->in6; 185 | return jhash_2words(a[2], a[3], 186 | jhash_3words(addr->af, a[0], a[1], hash_initval)); 187 | } else if (addr->af == AF_MACADDR) { 188 | const __be32 *a = (void *)&addr->mac; 189 | const __be16 *b = (void *)(a + 1); 190 | return jhash_3words(addr->af, *a, *b, hash_initval); 191 | } else { 192 | abort(); 193 | return 0; 194 | } 195 | } 196 | 197 | static inline int tun_addr_comp( 198 | const struct tun_addr *a1, const struct tun_addr *a2) 199 | { 200 | if (a1->af != a2->af) 201 | return 1; 202 | 203 | if (a1->af == AF_INET) { 204 | if (a1->in.s_addr == a2->in.s_addr) { 205 | return 0; 206 | } else { 207 | return 1; 208 | } 209 | } else if (a1->af == AF_INET6) { 210 | if (is_in6_equal(&a1->in6, &a2->in6)) { 211 | return 0; 212 | } else { 213 | return 1; 214 | } 215 | } else if (a1->af == AF_MACADDR) { 216 | if (is_mac_equal(&a1->mac, &a2->mac)) { 217 | return 0; 218 | } else { 219 | return 1; 220 | } 221 | } else { 222 | abort(); 223 | return 0; 224 | } 225 | } 226 | 227 | static void tun_addr_ntop(const struct tun_addr *a, char *buf, socklen_t bufsz) 228 | { 229 | const __u8 *b; 230 | 231 | switch (a->af) { 232 | case AF_INET: 233 | case AF_INET6: 234 | inet_ntop(a->af, &a->in, buf, bufsz); 235 | break; 236 | default: 237 | b = a->mac.addr; 238 | sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", 239 | b[0], b[1], b[2], b[3], b[4], b[5]); 240 | } 241 | } 242 | 243 | #ifdef DUMP_TUN_CLIENTS_ON_WALK 244 | static inline void tun_client_dump(struct tun_client *ce) 245 | { 246 | char s_virt_addr[50] = "", s_real_addr[50] = ""; 247 | 248 | tun_addr_ntop(&ce->virt_addr, s_virt_addr, sizeof(s_virt_addr)); 249 | inet_ntop(ce->ra->real_addr.sa.sa_family, addr_of_sockaddr(&ce->ra->real_addr), 250 | s_real_addr, sizeof(s_real_addr)); 251 | printf("[%s] (%s:%u), last_recv: %lu\n", s_virt_addr, 252 | s_real_addr, ntohs(port_of_sockaddr(&ce->ra->real_addr)), 253 | (unsigned long)ce->last_recv.tv_sec); 254 | } 255 | #endif 256 | 257 | static inline void tun_client_release(struct tun_client *ce) 258 | { 259 | char s_virt_addr[50], s_real_addr[50]; 260 | 261 | tun_addr_ntop(&ce->virt_addr, s_virt_addr, sizeof(s_virt_addr)); 262 | inet_ntop(ce->ra->real_addr.sa.sa_family, addr_of_sockaddr(&ce->ra->real_addr), 263 | s_real_addr, sizeof(s_real_addr)); 264 | syslog(LOG_INFO, "Recycled virtual address [%s] at [%s:%u].", s_virt_addr, 265 | s_real_addr, ntohs(port_of_sockaddr(&ce->ra->real_addr))); 266 | 267 | ra_put_no_free(ce->ra); 268 | 269 | list_del(&ce->list); 270 | va_map_len--; 271 | 272 | free(ce); 273 | } 274 | 275 | static struct tun_client *tun_client_try_get(const struct tun_addr *vaddr) 276 | { 277 | struct list_head *chain = &va_map_hbase[ 278 | tun_addr_hash(vaddr) & (VA_MAP_HASH_SIZE - 1)]; 279 | struct tun_client *ce; 280 | 281 | list_for_each_entry (ce, chain, list) { 282 | if (tun_addr_comp(&ce->virt_addr, vaddr) == 0) 283 | return ce; 284 | } 285 | return NULL; 286 | } 287 | 288 | static struct tun_client *tun_client_get_or_create( 289 | const struct tun_addr *vaddr, const struct sockaddr_inx *raddr) 290 | { 291 | struct list_head *chain = &va_map_hbase[ 292 | tun_addr_hash(vaddr) & (VA_MAP_HASH_SIZE - 1)]; 293 | struct tun_client *ce, *__ce; 294 | char s_virt_addr[50], s_real_addr[50]; 295 | 296 | list_for_each_entry_safe (ce, __ce, chain, list) { 297 | if (tun_addr_comp(&ce->virt_addr, vaddr) == 0) { 298 | if (!is_sockaddr_equal(&ce->ra->real_addr, raddr)) { 299 | /* Real address changed, reassign a new entry for it. */ 300 | ra_put_no_free(ce->ra); 301 | if ((ce->ra = ra_get_or_create(raddr)) == NULL) { 302 | tun_client_release(ce); 303 | return NULL; 304 | } 305 | } 306 | return ce; 307 | } 308 | } 309 | 310 | /* Not found, always create new entry. */ 311 | if ((ce = malloc(sizeof(*ce))) == NULL) { 312 | syslog(LOG_ERR, "*** [%s] malloc(): %s.", __FUNCTION__, strerror(errno)); 313 | return NULL; 314 | } 315 | 316 | ce->virt_addr = *vaddr; 317 | 318 | /* Get real_addr entry before adding to list. */ 319 | if ((ce->ra = ra_get_or_create(raddr)) == NULL) { 320 | free(ce); 321 | return NULL; 322 | } 323 | list_add_tail(&ce->list, chain); 324 | va_map_len++; 325 | 326 | tun_addr_ntop(&ce->virt_addr, s_virt_addr, sizeof(s_virt_addr)); 327 | inet_ntop(ce->ra->real_addr.sa.sa_family, addr_of_sockaddr(&ce->ra->real_addr), 328 | s_real_addr, sizeof(s_real_addr)); 329 | syslog(LOG_INFO, "New virtual address [%s] at [%s:%u].", s_virt_addr, 330 | s_real_addr, ntohs(port_of_sockaddr(&ce->ra->real_addr))); 331 | 332 | return ce; 333 | } 334 | 335 | /* Send echo reply back to a client */ 336 | static void reply_an_echo_ack(struct minivtun_msg *req, struct ra_entry *re) 337 | { 338 | char in_data[64], crypt_buffer[64]; 339 | struct minivtun_msg *nmsg = (struct minivtun_msg *)in_data; 340 | void *out_msg; 341 | size_t out_len; 342 | 343 | memset(&nmsg->hdr, 0x0, sizeof(nmsg->hdr)); 344 | nmsg->hdr.opcode = MINIVTUN_MSG_ECHO_ACK; 345 | nmsg->hdr.seq = htons(re->xmit_seq++); 346 | memcpy(nmsg->hdr.auth_key, config.crypto_key, sizeof(nmsg->hdr.auth_key)); 347 | nmsg->echo = req->echo; 348 | 349 | out_msg = crypt_buffer; 350 | out_len = MINIVTUN_MSG_BASIC_HLEN + sizeof(nmsg->echo); 351 | local_to_netmsg(nmsg, &out_msg, &out_len); 352 | 353 | (void)sendto(state.sockfd, out_msg, out_len, 0, 354 | (const struct sockaddr *)&re->real_addr, 355 | sizeof_sockaddr(&re->real_addr)); 356 | } 357 | 358 | static void va_ra_walk_continue(void) 359 | { 360 | static unsigned va_index = 0, ra_index = 0; 361 | struct timeval __current; 362 | unsigned va_walk_max = VA_MAP_LIMIT_EACH_WALK, va_count = 0; 363 | unsigned ra_walk_max = RA_SET_LIMIT_EACH_WALK, ra_count = 0; 364 | unsigned __va_index = va_index, __ra_index = ra_index; 365 | struct tun_client *ce, *__ce; 366 | struct ra_entry *re, *__re; 367 | 368 | gettimeofday(&__current, NULL); 369 | 370 | if (va_walk_max > va_map_len) 371 | va_walk_max = va_map_len; 372 | if (ra_walk_max > ra_set_len) 373 | ra_walk_max = ra_set_len; 374 | 375 | /* Recycle timeout virtual address entries. */ 376 | if (va_walk_max > 0) { 377 | do { 378 | list_for_each_entry_safe (ce, __ce, &va_map_hbase[va_index], list) { 379 | #ifdef DUMP_TUN_CLIENTS_ON_WALK 380 | tun_client_dump(ce); 381 | #endif 382 | if (__sub_timeval_ms(&__current, &ce->last_recv) > 383 | config.reconnect_timeo * 1000) { 384 | tun_client_release(ce); 385 | } 386 | va_count++; 387 | } 388 | va_index = (va_index + 1) & (VA_MAP_HASH_SIZE - 1); 389 | } while (va_count < va_walk_max && va_index != __va_index); 390 | } 391 | 392 | /* Recycle or keep-alive real client addresses. */ 393 | if (ra_walk_max > 0) { 394 | do { 395 | list_for_each_entry_safe (re, __re, &ra_set_hbase[ra_index], list) { 396 | if (__sub_timeval_ms(&__current, &re->last_recv) > 397 | config.reconnect_timeo * 1000) { 398 | if (re->refs == 0) { 399 | ra_entry_release(re); 400 | } 401 | } 402 | ra_count++; 403 | } 404 | ra_index = (ra_index + 1) & (RA_SET_HASH_SIZE - 1); 405 | } while (ra_count < ra_walk_max && ra_index != __ra_index); 406 | } 407 | 408 | printf("Online clients: %u, addresses: %u\n", ra_set_len, va_map_len); 409 | } 410 | 411 | static inline void source_addr_of_ipdata( 412 | const void *data, unsigned char af, struct tun_addr *addr) 413 | { 414 | addr->af = af; 415 | switch (af) { 416 | case AF_INET: 417 | memcpy(&addr->in, (char *)data + 12, 4); 418 | break; 419 | case AF_INET6: 420 | memcpy(&addr->in6, (char *)data + 8, 16); 421 | break; 422 | case AF_MACADDR: 423 | memcpy(&addr->mac, (char *)data + 6, 6); 424 | break; 425 | default: 426 | abort(); 427 | } 428 | } 429 | 430 | static inline void dest_addr_of_ipdata( 431 | const void *data, unsigned char af, struct tun_addr *addr) 432 | { 433 | addr->af = af; 434 | switch (af) { 435 | case AF_INET: 436 | memcpy(&addr->in, (char *)data + 16, 4); 437 | break; 438 | case AF_INET6: 439 | memcpy(&addr->in6, (char *)data + 24, 16); 440 | break; 441 | case AF_MACADDR: 442 | memcpy(&addr->mac, (char *)data + 0, 6); 443 | break; 444 | default: 445 | abort(); 446 | } 447 | } 448 | 449 | 450 | static int network_receiving(void) 451 | { 452 | char read_buffer[NM_PI_BUFFER_SIZE], crypt_buffer[NM_PI_BUFFER_SIZE]; 453 | struct minivtun_msg *nmsg; 454 | struct tun_pi pi; 455 | void *out_data; 456 | size_t ip_dlen, out_dlen; 457 | unsigned short af = 0; 458 | struct tun_addr virt_addr; 459 | struct tun_client *ce; 460 | struct ra_entry *re; 461 | struct sockaddr_inx real_peer; 462 | socklen_t real_peer_alen; 463 | struct iovec iov[2]; 464 | struct timeval __current; 465 | int rc; 466 | 467 | gettimeofday(&__current, NULL); 468 | 469 | real_peer_alen = sizeof(real_peer); 470 | rc = recvfrom(state.sockfd, &read_buffer, NM_PI_BUFFER_SIZE, 0, 471 | (struct sockaddr *)&real_peer, &real_peer_alen); 472 | if (rc <= 0) 473 | return -1; 474 | 475 | out_data = crypt_buffer; 476 | out_dlen = (size_t)rc; 477 | netmsg_to_local(read_buffer, &out_data, &out_dlen); 478 | nmsg = out_data; 479 | 480 | if (out_dlen < MINIVTUN_MSG_BASIC_HLEN) 481 | return 0; 482 | 483 | /* Verify password. */ 484 | if (memcmp(nmsg->hdr.auth_key, config.crypto_key, 485 | sizeof(nmsg->hdr.auth_key)) != 0) 486 | return 0; 487 | 488 | switch (nmsg->hdr.opcode) { 489 | case MINIVTUN_MSG_ECHO_REQ: 490 | /* Keep the real address alive */ 491 | if ((re = ra_get_or_create(&real_peer))) { 492 | re->last_recv = __current; 493 | /* Send echo reply */ 494 | reply_an_echo_ack(nmsg, re); 495 | ra_put_no_free(re); 496 | } 497 | if (out_dlen < MINIVTUN_MSG_BASIC_HLEN + sizeof(nmsg->echo)) 498 | return 0; 499 | /* Keep virtual addresses alive */ 500 | if (config.tap_mode) { 501 | /* TAP mode, handle as MAC address */ 502 | if (is_valid_unicast_mac(&nmsg->echo.loc_tun_mac)) { 503 | virt_addr.af = AF_MACADDR; 504 | virt_addr.mac = nmsg->echo.loc_tun_mac; 505 | if ((ce = tun_client_get_or_create(&virt_addr, &real_peer))) 506 | ce->last_recv = __current; 507 | } 508 | } else { 509 | /* TUN mode, handle as IP/IPv6 addresses */ 510 | if (is_valid_unicast_in(&nmsg->echo.loc_tun_in)) { 511 | virt_addr.af = AF_INET; 512 | virt_addr.in = nmsg->echo.loc_tun_in; 513 | if ((ce = tun_client_get_or_create(&virt_addr, &real_peer))) 514 | ce->last_recv = __current; 515 | } 516 | if (is_valid_unicast_in6(&nmsg->echo.loc_tun_in6)) { 517 | virt_addr.af = AF_INET6; 518 | virt_addr.in6 = nmsg->echo.loc_tun_in6; 519 | if ((ce = tun_client_get_or_create(&virt_addr, &real_peer))) 520 | ce->last_recv = __current; 521 | } 522 | } 523 | break; 524 | case MINIVTUN_MSG_IPDATA: 525 | if (config.tap_mode) { 526 | af = AF_MACADDR; 527 | /* No ethernet packet is shorter than 14 bytes. */ 528 | if (out_dlen < MINIVTUN_MSG_IPDATA_OFFSET + 14) 529 | return 0; 530 | nmsg->ipdata.proto = 0; 531 | ip_dlen = out_dlen - MINIVTUN_MSG_IPDATA_OFFSET; 532 | } else { 533 | if (nmsg->ipdata.proto == htons(ETH_P_IP)) { 534 | af = AF_INET; 535 | /* No valid IP packet is shorter than 20 bytes. */ 536 | if (out_dlen < MINIVTUN_MSG_IPDATA_OFFSET + 20) 537 | return 0; 538 | } else if (nmsg->ipdata.proto == htons(ETH_P_IPV6)) { 539 | af = AF_INET6; 540 | if (out_dlen < MINIVTUN_MSG_IPDATA_OFFSET + 40) 541 | return 0; 542 | } else { 543 | syslog(LOG_WARNING, "*** Invalid protocol: 0x%x.", ntohs(nmsg->ipdata.proto)); 544 | return 0; 545 | } 546 | ip_dlen = ntohs(nmsg->ipdata.ip_dlen); 547 | /* Drop incomplete IP packets. */ 548 | if (out_dlen - MINIVTUN_MSG_IPDATA_OFFSET < ip_dlen) 549 | return 0; 550 | } 551 | 552 | source_addr_of_ipdata(nmsg->ipdata.data, af, &virt_addr); 553 | if ((ce = tun_client_get_or_create(&virt_addr, &real_peer)) == NULL) 554 | return 0; 555 | 556 | ce->last_recv = __current; 557 | ce->ra->last_recv = __current; 558 | 559 | pi.flags = 0; 560 | pi.proto = nmsg->ipdata.proto; 561 | osx_ether_to_af(&pi.proto); 562 | iov[0].iov_base = π 563 | iov[0].iov_len = sizeof(pi); 564 | iov[1].iov_base = (char *)nmsg + MINIVTUN_MSG_IPDATA_OFFSET; 565 | iov[1].iov_len = ip_dlen; 566 | rc = writev(state.tunfd, iov, 2); 567 | break; 568 | } 569 | 570 | return 0; 571 | } 572 | 573 | static int tunnel_receiving(void) 574 | { 575 | char read_buffer[NM_PI_BUFFER_SIZE], crypt_buffer[NM_PI_BUFFER_SIZE]; 576 | struct tun_pi *pi = (void *)read_buffer; 577 | struct minivtun_msg nmsg; 578 | void *out_data; 579 | size_t ip_dlen, out_dlen; 580 | unsigned short af = 0; 581 | struct tun_addr virt_addr; 582 | struct tun_client *ce; 583 | int rc; 584 | 585 | rc = read(state.tunfd, pi, NM_PI_BUFFER_SIZE); 586 | if (rc < sizeof(struct tun_pi)) 587 | return -1; 588 | 589 | osx_af_to_ether(&pi->proto); 590 | 591 | ip_dlen = (size_t)rc - sizeof(struct tun_pi); 592 | 593 | if (config.tap_mode) { 594 | /* Ethernet frame */ 595 | af = AF_MACADDR; 596 | if (ip_dlen < 14) 597 | return 0; 598 | } else { 599 | /* We only accept IPv4 or IPv6 frames. */ 600 | if (pi->proto == htons(ETH_P_IP)) { 601 | af = AF_INET; 602 | if (ip_dlen < 20) 603 | return 0; 604 | } else if (pi->proto == htons(ETH_P_IPV6)) { 605 | af = AF_INET6; 606 | if (ip_dlen < 40) 607 | return 0; 608 | } else { 609 | syslog(LOG_WARNING, "*** Invalid protocol: 0x%x.", ntohs(pi->proto)); 610 | return 0; 611 | } 612 | } 613 | 614 | dest_addr_of_ipdata(pi + 1, af, &virt_addr); 615 | 616 | if ((ce = tun_client_try_get(&virt_addr)) == NULL) { 617 | /** 618 | * Not an existing client address, lookup the pseudo 619 | * route table for a destination to send. 620 | */ 621 | void *gw; 622 | 623 | /* Lookup the gateway address first */ 624 | if ((gw = vt_route_lookup(virt_addr.af, &virt_addr.in))) { 625 | /* Then find the gateway client entry */ 626 | struct tun_addr __va; 627 | memset(&__va, 0x0, sizeof(__va)); 628 | __va.af = virt_addr.af; 629 | if (virt_addr.af == AF_INET) { 630 | __va.in = *(struct in_addr *)gw; 631 | } else if (virt_addr.af == AF_INET6) { 632 | __va.in6 = *(struct in6_addr *)gw; 633 | } else { 634 | __va.mac = *(struct mac_addr *)gw; 635 | } 636 | if ((ce = tun_client_try_get(&__va)) == NULL) 637 | return 0; 638 | 639 | /* Finally, create a client entry with this address */ 640 | if ((ce = tun_client_get_or_create(&virt_addr, 641 | &ce->ra->real_addr)) == NULL) 642 | return 0; 643 | } else if (config.tap_mode) { 644 | /* In TAP mode, fall through to broadcast to all clients */ 645 | } else { 646 | return 0; 647 | } 648 | } 649 | 650 | memset(&nmsg.hdr, 0x0, sizeof(nmsg.hdr)); 651 | nmsg.hdr.opcode = MINIVTUN_MSG_IPDATA; 652 | memcpy(nmsg.hdr.auth_key, config.crypto_key, sizeof(nmsg.hdr.auth_key)); 653 | nmsg.ipdata.proto = pi->proto; 654 | nmsg.ipdata.ip_dlen = htons(ip_dlen); 655 | memcpy(nmsg.ipdata.data, pi + 1, ip_dlen); 656 | 657 | /* Do encryption. */ 658 | out_data = crypt_buffer; 659 | out_dlen = MINIVTUN_MSG_IPDATA_OFFSET + ip_dlen; 660 | local_to_netmsg(&nmsg, &out_data, &out_dlen); 661 | 662 | if (ce) { 663 | nmsg.hdr.seq = htons(ce->ra->xmit_seq++); 664 | (void)sendto(state.sockfd, out_data, out_dlen, 0, 665 | (struct sockaddr *)&ce->ra->real_addr, 666 | sizeof_sockaddr(&ce->ra->real_addr)); 667 | } else { 668 | /* Traverse all online clients and send */ 669 | unsigned i; 670 | for (i = 0; i < RA_SET_HASH_SIZE; i++) { 671 | struct ra_entry *re; 672 | list_for_each_entry (re, &ra_set_hbase[i], list) { 673 | nmsg.hdr.seq = htons(re->xmit_seq++); 674 | (void)sendto(state.sockfd, out_data, out_dlen, 0, 675 | (struct sockaddr *)&re->real_addr, 676 | sizeof_sockaddr(&re->real_addr)); 677 | } 678 | } 679 | } 680 | 681 | return 0; 682 | } 683 | 684 | static void usr1_signal_handler(int signum) 685 | { 686 | } 687 | 688 | int run_server(const char *loc_addr_pair) 689 | { 690 | char s_loc_addr[50]; 691 | bool is_random_port = false; 692 | 693 | if (get_sockaddr_inx_pair(loc_addr_pair, &state.local_addr, &is_random_port) < 0) { 694 | fprintf(stderr, "*** Cannot resolve address pair '%s'.\n", loc_addr_pair); 695 | return -1; 696 | } 697 | if (is_random_port) { 698 | fprintf(stderr, "*** Port range is not allowed for server.\n"); 699 | return -1; 700 | } 701 | 702 | inet_ntop(state.local_addr.sa.sa_family, addr_of_sockaddr(&state.local_addr), 703 | s_loc_addr, sizeof(s_loc_addr)); 704 | printf("Mini virtual tunneling server on %s:%u, interface: %s.\n", 705 | s_loc_addr, ntohs(port_of_sockaddr(&state.local_addr)), config.ifname); 706 | 707 | /* Initialize address map hash table. */ 708 | init_va_ra_maps(); 709 | hash_initval = rand(); 710 | 711 | if ((state.sockfd = socket(state.local_addr.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 712 | fprintf(stderr, "*** socket() failed: %s.\n", strerror(errno)); 713 | exit(1); 714 | } 715 | if (bind(state.sockfd, (struct sockaddr *)&state.local_addr, 716 | sizeof_sockaddr(&state.local_addr)) < 0) { 717 | fprintf(stderr, "*** bind() failed: %s.\n", strerror(errno)); 718 | exit(1); 719 | } 720 | set_nonblock(state.sockfd); 721 | 722 | /* Run in background. */ 723 | if (config.in_background) 724 | do_daemonize(); 725 | 726 | if (config.pid_file) { 727 | FILE *fp; 728 | if ((fp = fopen(config.pid_file, "w"))) { 729 | fprintf(fp, "%d\n", (int)getpid()); 730 | fclose(fp); 731 | } 732 | } 733 | 734 | gettimeofday(&state.last_walk, NULL); 735 | 736 | signal(SIGUSR1, usr1_signal_handler); 737 | 738 | for (;;) { 739 | fd_set rset; 740 | struct timeval __current, timeo; 741 | int rc; 742 | 743 | FD_ZERO(&rset); 744 | FD_SET(state.tunfd, &rset); 745 | FD_SET(state.sockfd, &rset); 746 | 747 | timeo = (struct timeval) { 2, 0 }; 748 | rc = select((state.tunfd > state.sockfd ? state.tunfd : state.sockfd) + 1, 749 | &rset, NULL, NULL, &timeo); 750 | if (rc < 0) { 751 | if (errno == EINTR || errno == ERESTART) { 752 | /* Fall through */ 753 | } else { 754 | fprintf(stderr, "*** select(): %s.\n", strerror(errno)); 755 | return -1; 756 | } 757 | } 758 | 759 | if (FD_ISSET(state.sockfd, &rset)) { 760 | rc = network_receiving(); 761 | } 762 | 763 | if (FD_ISSET(state.tunfd, &rset)) { 764 | rc = tunnel_receiving(); 765 | } 766 | 767 | /* Check connection state at each chance. */ 768 | gettimeofday(&__current, NULL); 769 | if (__sub_timeval_ms(&__current, &state.last_walk) >= 3 * 1000) { 770 | va_ra_walk_continue(); 771 | state.last_walk = __current; 772 | } 773 | } 774 | 775 | return 0; 776 | } 777 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------