├── sample ├── sample.png ├── n10plus.jpg ├── sample.pptx └── README.md ├── sample2 ├── vcnet.png ├── n10plus.jpg ├── vcnet.pptx └── README.md ├── VERSION ├── Makefile ├── README.md └── EthUDP.c /sample/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bg6cq/ethudp/HEAD/sample/sample.png -------------------------------------------------------------------------------- /sample2/vcnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bg6cq/ethudp/HEAD/sample2/vcnet.png -------------------------------------------------------------------------------- /sample/n10plus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bg6cq/ethudp/HEAD/sample/n10plus.jpg -------------------------------------------------------------------------------- /sample/sample.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bg6cq/ethudp/HEAD/sample/sample.pptx -------------------------------------------------------------------------------- /sample2/n10plus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bg6cq/ethudp/HEAD/sample2/n10plus.jpg -------------------------------------------------------------------------------- /sample2/vcnet.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bg6cq/ethudp/HEAD/sample2/vcnet.pptx -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v20230202 2 | 3 | 802.1Q tag bug fix 4 | 5 | v20210111 6 | 7 | run_seconds support 8 | 9 | v20201118 10 | 11 | 9234 Jumbo Frame support 12 | 13 | v20200402 14 | 15 | tcpdump as input for capture 16 | 17 | v20200401 18 | 19 | IP_MTU_DISCOVER 20 | status format 21 | default enc_algorithm & enc_key 22 | 23 | v20200325 24 | 25 | status bad when starting 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GIT_VERSION ?= $(shell git describe --abbrev=4 --dirty --always --tags) 2 | CC ?= gcc 3 | 4 | EthUDP:EthUDP.c 5 | $(CC) -g -Wall -DVERSION=\"$(GIT_VERSION)\" -o EthUDP EthUDP.c -lpthread -lssl -llz4 -lcrypto -lpcap -D_GNU_SOURCE 6 | 7 | run: 8 | $(CC) -Wall -DVERSION=\"$(GIT_VERSION)-O3\" -Wunused-result -fno-strict-aliasing -O2 -o EthUDP EthUDP.c -lpthread -lssl -llz4 -lcrypto -lpcap -D_GNU_SOURCE 9 | 10 | indent: EthUDP.c 11 | indent EthUDP.c -nbad -bap -nbc -bbo -hnl -br -brs -c33 -cd33 -ncdb -ce -ci4 \ 12 | -cli0 -d0 -di1 -nfc1 -i8 -ip0 -l160 -lp -npcs -nprs -npsl -sai \ 13 | -saf -saw -ncs -nsc -sob -nfca -cp33 -ss -ts8 -il1 14 | -------------------------------------------------------------------------------- /sample/README.md: -------------------------------------------------------------------------------- 1 | # EthUDP sample 2 | 3 | Ethernet over UDP sample 4 | 5 | [N10Plus多网口千兆迷你小主机](https://detail.tmall.com/item.htm?id=542409856806) 6 | 7 | N10Plus有4个千兆接口,无风扇运行,外形如下: 8 | 9 | ![N10Plus多网口千兆迷你小主机](n10plus.jpg) 10 | 11 | 12 | ![sample network](sample.png) 13 | 14 | 15 | On server A /etc/rc.local 16 | ```` 17 | ip add add 222.195.81.240/24 dev eth0 18 | ip link set eth0 up 19 | ip route add 0/0 via 222.195.81.1 20 | 21 | ip link set eth1 mtu 1508 22 | ip link set eth1 up 23 | 24 | /usr/src/ethudp/EthUDP -e 222.195.81.240 6000 202.38.64.144 6000 eth1 \ 25 | 222.195.81.240 7000 202.38.64.144 7000 26 | ```` 27 | 28 | On server B /etc/rc.local 29 | ```` 30 | ip add add 202.38.64.144/24 dev eth0 31 | ip link set eth0 up 32 | ip route add 0/0 via 202.38.64.1 33 | 34 | ip link set eth1 mtu 1508 35 | ip link set eth1 up 36 | 37 | /usr/src/ethudp/EthUDP -e 202.38.64.144 6000 222.195.81.240 6000 eth1 \ 38 | 202.38.64.144 7000 222.195.81.240 7000 39 | ```` 40 | 41 | Note: UDP port 6000 is master connection, and 7000 is slave connection. 42 | -------------------------------------------------------------------------------- /sample2/README.md: -------------------------------------------------------------------------------- 1 | # Cross Internet, connect your ethernets 2 | # 通过互联网桥接2个以太网段 3 | 4 | 使用EthUDP可以把两个以太网通过互联网桥接,下面是我们的一个案例: 5 | 6 | 开通视频会议时,如果某一方的视频会议终端在内网,对外经过了NAT或防火墙设备连接互联网, 7 | 另一方终端在互联网上,这种情况经常会出现某个方向的音频或视频无法传送的问题。 8 | 9 | 解决问题的最简单方法是把两方的内部以太网通过互联网直接桥接,让两边的视频终端直通即可。 10 | 11 | 12 | ## 网络结构 13 | 14 | 站点A有公网IP,IP地址是202.110.92.27/29,网关是202.110.92.25。 15 | 16 | 站点B经过NAT连接互联网,IP地址是192.168.10.2/24(内网),网关是192.168.10.1。 17 | 18 | 站点A和站点B各有一台视频会议终端,站点A的视频会议终端IP是 10.10.10.1/24, 19 | 站点B的视频会议终端IP是10.10.10.2/24。 20 | 21 | 为了将站点A和站点B的以太网互联,在站点A和站点B各增加一台Linux机器提供隧道连接,拓扑图如下: 22 | 23 | ![网络拓扑图](vcnet.png) 24 | 25 | ## 使用设备 26 | 27 | Linux机器,我们采购的是 28 | [N10Plus多网口千兆迷你小主机](https://detail.tmall.com/item.htm?id=542409856806) 29 | 30 | N10Plus有4个千兆接口,无风扇运行,外形如下: 31 | 32 | ![N10Plus多网口千兆迷你小主机](n10plus.jpg) 33 | 34 | ## 系统安装 35 | 36 | 两台Linux机器为CentOS 6 最小安装(eth0网卡分别设置各自IP地址和网关),执行以下命令安装EthUDP软件: 37 | ``` 38 | yum install epel-release 39 | yum install gcc git lz4-devel openssl-devel tcpdump ntpdate telnet traceroute 40 | cd /usr/src 41 | git clone https://github.com/bg6cq/ethudp.git 42 | cd ethudp 43 | make 44 | ``` 45 | 46 | ## 站点A Linux机器的设置: 47 | 48 | 1. 允许udp 6000、6001端口的通信 49 | 50 | ``` 51 | iptables -I INPUT -j ACCEPT -p udp --dport 6000 52 | iptables -I INPUT -j ACCEPT -p udp --dport 6001 53 | service iptables save 54 | ``` 55 | 2. 修改文件 `/etc/rc.d/rc.local` 56 | 57 | ``` 58 | ethtool -K eth1 gro off 59 | ip link set eth1 up 60 | 61 | OPT="-k 123456 -enc aes-128 -p password" 62 | /usr/src/ethudp/EthUDP -e $OPT 222.110.92.27 6000 0.0.0.0 0 eth1 63 | /usr/src/ethudp/EthUDP -i $OPT 222.110.92.27 6001 0.0.0.0 0 172.16.10.1 24 64 | ```` 65 | 66 | ## 站点B Linux机器的设置: 67 | 68 | 1. 修改文件 `/etc/rc.d/rc.local` 69 | 70 | ``` 71 | ethtool -K eth1 gro off 72 | ip link set eth1 up 73 | 74 | OPT="-k 123456 -enc aes-128 -p password" 75 | /usr/src/ethudp/EthUDP -e $OPT 192.168.10.2 6000 222.110.92.27 6000 eth1 76 | /usr/src/ethudp/EthUDP -i $OPT 192.168.10.2 6001 222.110.92.27 6001 172.16.10.2 24 77 | ```` 78 | 79 | ## 配置说明 80 | 81 | 以上设置的含义是: 82 | 83 | * 站点A和站点B间的Linux机器使用UDP 6000和6001端口通信 84 | * 站点B的Linux通过NAT连接站点A的Linux 85 | * 通信时使用AES-128加密 86 | * 站点A/站点B的视频会议终端能直接通信,就像两者直连一样 87 | * 站点A/站点B的Linux可以使用172.16.10.1/172.16.10.2互相通信 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EthUDP 2 | 3 | Ethernet over UDP, similar of VXLAN, transport Ethernet packet via UDP, support data encryption, udp connection failover 4 | 5 | ## Sample config 6 | 7 | [Cross Internet, connect your ethenets/通过互联网桥接2个以太网段](sample2/README.md) 8 | 9 | [Sample config](sample/README.md) 10 | 11 | ## package needs to compile 12 | 13 | CentOS: 14 | ```` 15 | openssl-devel lz4-devel libpcap-devel 16 | ```` 17 | Debian 18 | ```` 19 | libssl-dev liblz4-dev libpcap-dev 20 | ```` 21 | and Debian liblz4 miss LZ4_compress_fast, you need rebuild it as https://github.com/facebook/mcrouter/issues/149 22 | ```` 23 | apt-get install dpkg-dev debhelper 24 | echo "deb-src http://ftp.de.debian.org/debian/ stretch main" > /etc/apt/sources.list.d/stretch-source-packages.list 25 | apt-get update 26 | apt-get source lz4=0.0~r131-2 27 | cd lz4-0.0~r131 28 | dpkg-buildpackage -rfakeroot -uc -b 29 | cd .. 30 | dpkg -i liblz4-1_0.0~r131-2_amd64.deb liblz4-dev_0.0~r131-2_amd64.deb 31 | ```` 32 | 33 | ## Increasing Linux kernel network buffers 34 | 35 | For better performance, increase the UDP receive buffer size from 128K to 32MB 36 | ```` 37 | sysctl -w net.core.rmem_max=33554432 38 | ```` 39 | 40 | ## 1. mode e 41 | Bridge two ethernets using UDP 42 | 43 |
 44 |           |-------Internet---------|
 45 |           |                        |
 46 |           |                        |
 47 |           |IPA                  IPB|
 48 |           |eth0                eth0|
 49 | +---------+----+              +----+---------+
 50 | |   server A   |              |   server B   |
 51 | +------+-------+              +-------+------+
 52 |        | eth1                    eth1 |
 53 |        |                              |
 54 |        |                              |
 55 |        |                              |
 56 |   +----+---+                     +----+----+
 57 |   | HOST 1 |                     |  HOST 2 |
 58 |   +--------+                     +---------+
 59 | 
60 | 61 | Each server connects Internet via interface eth0, IP is IPA & IPB. 62 | 63 | On server A, run following command 64 | ```` 65 | ip link set eth1 up 66 | ethtool -K eth1 gro off 67 | ifconfig eth1 mtu 1508 68 | ./EthUDP -e IPA 6000 IPB 6000 eth1 69 | ```` 70 | 71 | On server B, run following command 72 | ```` 73 | ip link set eth1 up 74 | ethtool -K eth1 gro off 75 | ifconfig eth1 mtu 1508 76 | ./EthUDP -e IPB 6000 IPA 6000 eth1 77 | ```` 78 | 79 | bridge HOST 1 and HOST 2 via internet using UDP port 6000 80 | 81 | how it works: 82 | * open raw socket for eth1 83 | * open udp socket to remote host 84 | * read packet from raw socket, send to udp socket 85 | * read packet from udp socket, send to raw socket 86 | 87 | ## 2. mode i 88 | create a tap tunnel interface using UDP 89 |
 90 |        |------------Internet--------------|
 91 |        |                                  |
 92 |        |                                  |
 93 |        |IPA                            IPB|
 94 |        |eth0                          eth0|
 95 | +------+-------+                  +-------+------+
 96 | |   server A   +--IP1--------IP2--+   server B   |
 97 | +--------------+                  +--------------+
 98 | 
99 | 100 | Each server connects Internet via interface eth0, IP is IPA & IPB. 101 | 102 | On server A, run following command 103 | ```` 104 | ./EthUDP -i IPA 6000 IPB 6000 IP1 masklen 105 | ```` 106 | 107 | On server B, run following command 108 | ```` 109 | ./EthUDP -i IPB 6000 IPA 6000 IP2 masklen 110 | ```` 111 | 112 | create a tap tunnel interface and setup IP1/masklen IP2/masklen via internet using UDP port 6000 113 | 114 | how it works: 115 | * open tap raw socket, setip addr 116 | * open udp socket to remote host 117 | * read packet from raw socket, send to udp socket 118 | * read packet from udp socket, send to raw socket 119 | 120 | 121 | ## 3. mode b 122 | create a tap tunnel interface using UDP 123 |
124 |        |------------Internet--------------|
125 |        |                                  |
126 |        |                                  |
127 |        |IPA                            IPB|
128 |        |eth0                          eth0|
129 | +------+-------+                  +-------+------+
130 | |   server A   +--bridge----bridge|   server B   |
131 | +------+-------+                  +-------+------+
132 |        |eth1                          eth1|
133 |        |                                  |
134 |        |                                  |
135 |   +----+---+                         +----+----+
136 |   | HOST 1 |                         |  HOST 2 |
137 |   +--------+                         +---------+
138 | 
139 | 140 | Each server connects Internet via interface eth0, IP is IPA & IPB. 141 | 142 | On server A, run following command 143 | ```` 144 | brctl addbr br0 145 | ip link set eth1 up 146 | brctl addif br0 eth1 147 | ./EthUDP -b IPA 6000 IPB 6000 br0 148 | ```` 149 | 150 | On server B, run following command 151 | ```` 152 | brctl addbr br0 153 | ip link set eth1 up 154 | brctl addif br0 eth1 155 | ./EthUDP -b IPB 6000 IPA 6000 br0 156 | ```` 157 | 158 | create a tap tunnel interface and add to br0 internet using UDP port 6000, 159 | Host 1 and Host 2 can communicate with each other. 160 | 161 | how it works: 162 | * open tap raw socket, run shell `brctl add if ??? tap?` add to bridge 163 | * open udp socket to remote host 164 | * read packet from raw socket, send to udp socket 165 | * read packet from udp socket, send to raw socket 166 | 167 | 168 | ## 4. mode t 169 | 170 | using libpcap to capture packets and send full ethernet packet to remote site 171 | 172 | ## 5. mode u 173 | 174 | using libpcap to capture udp packets and send udp packet to remote site 175 | 176 | ## Note: 177 | 1. support 802.1Q VLAN frame transport 178 | 179 | NIC MTU should set to 1504 or 1508, for single 802.1Q or double 802.1Q tag. But some NICs do not allow change the default 1500. 180 | 181 | 2. support automatic tcp mss fix 182 | 183 | 3. if your NIC support GRO, you should disable it by 184 | ```` 185 | ethtool -K eth1 gro off 186 | ```` 187 | 188 | 4. support connection from NATed server 189 | 190 | If server A has public IP, while server B connect from NATed IP, please run (port is 0) 191 | ```` 192 | ./EthUDP -e -p password IPA 6000 0.0.0.0 0 eth1 in A 193 | ./EthUDP -e -p password IPB 6000 IPA 6000 eth1 in B 194 | ```` 195 | 5. support master slave switchover 196 | 197 | Using master udp connection, switch to slave if master down(send/recv ping/pong message 1/sec) 198 | ```` 199 | ./EthUDP ... IPA portA IPB portB ... SlaveIPA SlaveportA SlaveIPB SlaveportB 200 | ./EthUDP ... IPB portB IPA portA ... SlaveIPB SlaveportB SlaveIPA SlaveportA 201 | ```` 202 | 6. support AES-128/192/256 encrypt/decrypt UDP traffic 203 | ```` 204 | ./EthUDP ... -enc aes-128 -k aes_key ... 205 | ```` 206 | 7. support LZ4 compress 207 | ```` 208 | ./EthUDP ... -lz4 1 ... 209 | ```` 210 | 8. support VLAN maping 211 | ```` 212 | ./EthUDP ... -m vlanmap.txt ... 213 | 214 | vlanmap.txt 215 | #my_vlan remote_vlan 216 | 10 30 217 | 40 100 218 | ```` 219 | 9. support UDP packet fragment 220 | 221 | ``` 222 | ./EthUDP ... -mtu 1500 223 | ``` 224 | split UDP packet length exceed 1500 bytes to two UDP packets 225 | -------------------------------------------------------------------------------- /EthUDP.c: -------------------------------------------------------------------------------- 1 | /* EthUDP: used to create tunnel over ipv4/ipv6 network 2 | by james@ustc.edu.cn 2009.04.02 3 | */ 4 | 5 | // kernel use auxdata to send vlan tag, we use auxdata to reconstructe vlan header 6 | #define HAVE_PACKET_AUXDATA 1 7 | 8 | // enable OPENSSL encrypt/decrypt support 9 | #define ENABLE_OPENSSL 1 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #define MAXLEN 2048 44 | #define MAX_PACKET_SIZE 9234 // Jumbo Frame 45 | #define MAXFD 64 46 | 47 | #define STATUS_BAD 0 48 | #define STATUS_OK 1 49 | #define MASTER 0 50 | #define SLAVE 1 51 | 52 | #define MODEE 0 // raw ether bridge mode 53 | #define MODEI 1 // tap interface mode 54 | #define MODEB 2 // bridge mode 55 | #define MODET 3 // tcpdump full packet to remote 56 | #define MODEU 4 // tcpdump udp packet to remote 57 | 58 | //#define DEBUGPINGPONG 1 59 | //#define DEBUGSSL 1 60 | 61 | // ip & brctl command 62 | #define IPCMD "/sbin/ip" 63 | #define BRIDGECMD "/usr/sbin/brctl" 64 | 65 | #define XOR 1 66 | 67 | #ifdef ENABLE_OPENSSL 68 | #include 69 | #define AES_128 2 70 | #define AES_192 3 71 | #define AES_256 3 72 | #else 73 | #define EVP_MAX_BLOCK_LENGTH 0 74 | #endif 75 | 76 | #define max(a,b) ((a) > (b) ? (a) : (b)) 77 | 78 | #ifdef HAVE_PACKET_AUXDATA 79 | #define VLAN_TAG_LEN 4 80 | struct vlan_tag { 81 | u_int16_t vlan_tpid; /* ETH_P_8021Q */ 82 | u_int16_t vlan_tci; /* VLAN TCI */ 83 | }; 84 | #endif 85 | 86 | u_int16_t ETHP8021Q; // 0x8100 in network order 87 | 88 | struct _EtherHeader { 89 | uint16_t destMAC1; 90 | uint32_t destMAC2; 91 | uint16_t srcMAC1; 92 | uint32_t srcMAC2; 93 | uint32_t VLANTag; 94 | uint16_t type; 95 | int32_t payload; 96 | } __attribute__ ((packed)); 97 | 98 | typedef struct _EtherHeader EtherPacket; 99 | 100 | struct packet_buf { 101 | time_t rcvt; // recv time, 0 if not valid 102 | int len; // buf len 103 | unsigned char *buf; // packet header is 8 bytes: UDPFRG+seq 104 | }; 105 | 106 | #define MAXPKTS 65536 107 | 108 | struct packet_buf packet_bufs[MAXPKTS]; // buf[0] & buf[1] is pair, store the orignal big UDP packets 109 | 110 | int daemon_proc; /* set nonzero by daemon_init() */ 111 | volatile int debug = 0; 112 | 113 | int mode = -1; // 0 eth bridge, 1 interface, 2 bridge 114 | int mtu = 0; 115 | int udp_frg_seq = 0; 116 | int master_slave = 0; 117 | int read_only = 0, write_only = 0; 118 | int fixmss = 0; 119 | int nopromisc = 0; 120 | int loopback_check = 0; 121 | int packet_len = 1500; 122 | char name[MAXLEN]; 123 | char run_cmd[MAXLEN]; 124 | char dev_name[IFNAMSIZ]; 125 | int run_seconds = 0; 126 | 127 | int32_t ifindex; 128 | 129 | char mypassword[MAXLEN]; 130 | int enc_algorithm; 131 | unsigned char enc_key[MAXLEN]; 132 | #ifdef ENABLE_OPENSSL 133 | unsigned char enc_iv[EVP_MAX_IV_LENGTH]; 134 | #endif 135 | int enc_key_len = 0; 136 | 137 | int fdudp[2], fdraw; 138 | int nat[2]; 139 | pcap_t *pcap_handle; 140 | 141 | int lz4 = 0; 142 | volatile long long udp_total = 0; 143 | volatile long long compress_overhead = 0; 144 | volatile long long compress_save = 0; 145 | volatile long long encrypt_overhead = 0; 146 | #define LZ4_SPACE 128 147 | 148 | int vlan_map = 0; 149 | int my_vlan[4096]; 150 | int remote_vlan[4096]; 151 | 152 | volatile struct sockaddr_storage local_addr[2]; 153 | volatile struct sockaddr_storage cmd_remote_addr[2]; 154 | volatile struct sockaddr_storage remote_addr[2]; 155 | volatile unsigned long myticket, last_pong[2]; // myticket inc 1 every 1 second after start 156 | volatile unsigned long ping_send[2], ping_recv[2], pong_send[2], pong_recv[2]; 157 | volatile unsigned long raw_send_pkt, raw_send_byte, raw_recv_pkt, raw_recv_byte; 158 | volatile unsigned long udp_send_pkt[2], udp_send_byte[2], udp_recv_pkt[2], udp_recv_byte[2]; 159 | volatile unsigned long udp_send_err[2], raw_send_err; 160 | volatile int master_status = STATUS_BAD; 161 | volatile int slave_status = STATUS_BAD; 162 | volatile int current_remote = MASTER; 163 | volatile int got_signal = 1; 164 | 165 | void sig_handler_hup(int signo) 166 | { 167 | got_signal = 1; 168 | } 169 | 170 | void sig_handler_usr1(int signo) 171 | { 172 | udp_total = compress_overhead = compress_save = encrypt_overhead = 0; 173 | raw_send_pkt = raw_send_byte = raw_recv_pkt = raw_recv_byte = 0; 174 | udp_send_pkt[0] = udp_send_byte[0] = udp_recv_pkt[0] = udp_recv_byte[0] = 0; 175 | udp_send_pkt[1] = udp_send_byte[1] = udp_recv_pkt[1] = udp_recv_byte[1] = 0; 176 | } 177 | 178 | void err_doit(int errnoflag, int level, const char *fmt, va_list ap) 179 | { 180 | int errno_save, n; 181 | char buf[MAXLEN]; 182 | 183 | errno_save = errno; /* value caller might want printed */ 184 | vsnprintf(buf, sizeof(buf), fmt, ap); /* this is safe */ 185 | n = strlen(buf); 186 | if (errnoflag) 187 | snprintf(buf + n, sizeof(buf) - n, ": %s", strerror(errno_save)); 188 | strcat(buf, "\n"); 189 | 190 | if (daemon_proc) { 191 | if (name[0]) 192 | syslog(level, "%s: %s", name, buf); 193 | else 194 | syslog(level, "%s", buf); 195 | } else { 196 | fflush(stdout); /* in case stdout and stderr are the same */ 197 | if (name[0]) { 198 | fputs(name, stderr); 199 | fputs(": ", stderr); 200 | } 201 | fputs(buf, stderr); 202 | fflush(stderr); 203 | } 204 | return; 205 | } 206 | 207 | void err_msg(const char *fmt, ...) 208 | { 209 | va_list ap; 210 | va_start(ap, fmt); 211 | err_doit(0, LOG_INFO, fmt, ap); 212 | va_end(ap); 213 | return; 214 | } 215 | 216 | void Debug(const char *fmt, ...) 217 | { 218 | va_list ap; 219 | if (debug) { 220 | va_start(ap, fmt); 221 | err_doit(0, LOG_INFO, fmt, ap); 222 | va_end(ap); 223 | } 224 | return; 225 | } 226 | 227 | void err_quit(const char *fmt, ...) 228 | { 229 | va_list ap; 230 | va_start(ap, fmt); 231 | err_doit(0, LOG_ERR, fmt, ap); 232 | va_end(ap); 233 | exit(1); 234 | } 235 | 236 | void err_sys(const char *fmt, ...) 237 | { 238 | va_list ap; 239 | va_start(ap, fmt); 240 | err_doit(1, LOG_ERR, fmt, ap); 241 | va_end(ap); 242 | exit(1); 243 | } 244 | 245 | void daemon_init(const char *pname, int facility) 246 | { 247 | int i; 248 | pid_t pid; 249 | if ((pid = fork()) != 0) 250 | exit(0); /* parent terminates */ 251 | 252 | /* 41st child continues */ 253 | setsid(); /* become session leader */ 254 | 255 | signal(SIGHUP, SIG_IGN); 256 | if ((pid = fork()) != 0) 257 | exit(0); /* 1st child terminates */ 258 | 259 | /* 42nd child continues */ 260 | daemon_proc = 1; /* for our err_XXX() functions */ 261 | 262 | umask(0); /* clear our file mode creation mask */ 263 | 264 | for (i = 0; i < MAXFD; i++) 265 | close(i); 266 | 267 | openlog(pname, LOG_PID, facility); 268 | } 269 | 270 | int udp_server(const char *host, const char *serv, socklen_t * addrlenp, int index) 271 | { 272 | int sockfd, n; 273 | int on = 1; 274 | struct addrinfo hints, *res, *ressave; 275 | 276 | bzero(&hints, sizeof(struct addrinfo)); 277 | hints.ai_flags = AI_PASSIVE; 278 | hints.ai_family = AF_UNSPEC; 279 | hints.ai_socktype = SOCK_DGRAM; 280 | 281 | if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) 282 | err_quit("udp_server error for %s, %s", host, serv); 283 | ressave = res; 284 | 285 | do { 286 | sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 287 | if (sockfd < 0) 288 | continue; /* error, try next one */ 289 | memcpy((void *)&(local_addr[index]), res->ai_addr, res->ai_addrlen); 290 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, 1); 291 | if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0) 292 | break; /* success */ 293 | close(sockfd); /* bind error, close and try next one */ 294 | } 295 | while ((res = res->ai_next) != NULL); 296 | 297 | if (res == NULL) /* errno from final socket() or bind() */ 298 | err_sys("udp_server error for %s, %s", host, serv); 299 | 300 | if (addrlenp) 301 | *addrlenp = res->ai_addrlen; /* return size of protocol address */ 302 | 303 | freeaddrinfo(ressave); 304 | 305 | return (sockfd); 306 | } 307 | 308 | int udp_xconnect(char *lhost, char *lserv, char *rhost, char *rserv, int index) 309 | { 310 | int sockfd, n; 311 | struct addrinfo hints, *res, *ressave; 312 | 313 | sockfd = udp_server(lhost, lserv, NULL, index); 314 | 315 | n = 10 * 1024 * 1024; 316 | setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); 317 | if (debug) { 318 | socklen_t ln; 319 | if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, &ln) == 0) 320 | Debug("UDP socket RCVBUF setting to %d\n", n); 321 | } 322 | // set IP_MTU_DISCOVER, otherwise UDP has DFbit set 323 | n = 0; 324 | if (setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &n, sizeof(n)) != 0) 325 | err_msg("udp_xeonnect setsockopt returned error, errno %d\n", errno); 326 | 327 | bzero(&hints, sizeof(struct addrinfo)); 328 | hints.ai_family = AF_UNSPEC; 329 | hints.ai_socktype = SOCK_DGRAM; 330 | 331 | if ((n = getaddrinfo(rhost, rserv, &hints, &res)) != 0) 332 | err_quit("udp_xconnect error for %s, %s", rhost, rserv); 333 | ressave = res; 334 | 335 | do { 336 | void *raddr; 337 | if (res->ai_family == AF_INET) { // IPv4 338 | struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr; 339 | raddr = &(ipv4->sin_addr); 340 | if ((memcmp(raddr, "\0\0\0\0", 4) == 0) || (ipv4->sin_port == 0)) { 341 | Debug("nat = 1"); 342 | nat[index] = 1; 343 | memcpy((void *)&(cmd_remote_addr[index]), res->ai_addr, res->ai_addrlen); 344 | freeaddrinfo(ressave); 345 | return sockfd; 346 | } 347 | } else { // IPv6 348 | struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr; 349 | raddr = &(ipv6->sin6_addr); 350 | if ((memcmp(raddr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) || (ipv6->sin6_port == 0)) { 351 | Debug("nat = 1"); 352 | nat[index] = 1; 353 | memcpy((void *)&(cmd_remote_addr[index]), res->ai_addr, res->ai_addrlen); 354 | freeaddrinfo(ressave); 355 | return sockfd; 356 | } 357 | } 358 | 359 | if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0) { 360 | memcpy((void *)&(cmd_remote_addr[index]), res->ai_addr, res->ai_addrlen); 361 | memcpy((void *)&(remote_addr[index]), res->ai_addr, res->ai_addrlen); 362 | break; /* success */ 363 | } 364 | } 365 | while ((res = res->ai_next) != NULL); 366 | 367 | if (res == NULL) /* errno set from final connect() */ 368 | err_sys("udp_xconnect error for %s, %s", rhost, rserv); 369 | 370 | freeaddrinfo(ressave); 371 | 372 | return (sockfd); 373 | } 374 | 375 | /** 376 | * Open a rawsocket for the network interface 377 | */ 378 | int32_t open_rawsocket(char *ifname, int32_t * rifindex) 379 | { 380 | unsigned char buf[MAX_PACKET_SIZE]; 381 | int32_t ifindex; 382 | struct ifreq ifr; 383 | struct sockaddr_ll sll; 384 | int n; 385 | 386 | int32_t fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 387 | if (fd == -1) 388 | err_sys("socket %s - ", ifname); 389 | 390 | // get interface index 391 | memset(&ifr, 0, sizeof(ifr)); 392 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 393 | if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) 394 | err_sys("SIOCGIFINDEX %s - ", ifname); 395 | ifindex = ifr.ifr_ifindex; 396 | *rifindex = ifindex; 397 | 398 | if (!nopromisc) { // set promiscuous mode 399 | memset(&ifr, 0, sizeof(ifr)); 400 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 401 | ioctl(fd, SIOCGIFFLAGS, &ifr); 402 | ifr.ifr_flags |= IFF_PROMISC; 403 | ioctl(fd, SIOCSIFFLAGS, &ifr); 404 | } 405 | 406 | memset(&sll, 0xff, sizeof(sll)); 407 | sll.sll_family = AF_PACKET; 408 | sll.sll_protocol = htons(ETH_P_ALL); 409 | sll.sll_ifindex = ifindex; 410 | if (bind(fd, (struct sockaddr *)&sll, sizeof(sll)) == -1) 411 | err_sys("bind %s - ", ifname); 412 | 413 | /* flush all received packets. 414 | * 415 | * raw-socket receives packets from all interfaces 416 | * when the socket is not bound to an interface 417 | */ 418 | int32_t i, l = 0; 419 | do { 420 | fd_set fds; 421 | struct timeval t; 422 | FD_ZERO(&fds); 423 | FD_SET(fd, &fds); 424 | memset(&t, 0, sizeof(t)); 425 | i = select(FD_SETSIZE, &fds, NULL, NULL, &t); 426 | if (i > 0) { 427 | recv(fd, buf, i, 0); 428 | l++; 429 | }; 430 | Debug("interface %d flushed %d packets", ifindex, l); 431 | } 432 | while (i > 0); 433 | 434 | /* Enable auxillary data if supported and reserve room for 435 | * reconstructing VLAN headers. */ 436 | #ifdef HAVE_PACKET_AUXDATA 437 | int val = 1; 438 | if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, &val, sizeof(val)) == -1 && errno != ENOPROTOOPT) { 439 | err_sys("setsockopt(packet_auxdata): %s", strerror(errno)); 440 | } 441 | #endif /* HAVE_PACKET_AUXDATA */ 442 | 443 | Debug("%s opened (fd=%d interface=%d)", ifname, fd, ifindex); 444 | 445 | n = 10 * 1024 * 1024; 446 | setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); 447 | if (debug) { 448 | socklen_t ln; 449 | if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &n, &ln) == 0) { 450 | Debug("RAW socket RCVBUF setting to %d", n); 451 | } 452 | } 453 | 454 | return fd; 455 | } 456 | 457 | int xor_encrypt(u_int8_t * buf, int n, u_int8_t * nbuf) 458 | { 459 | int i; 460 | for (i = 0; i < n; i++) 461 | nbuf[i] = buf[i] ^ enc_key[i % enc_key_len]; 462 | return n; 463 | } 464 | 465 | #ifdef ENABLE_OPENSSL 466 | int openssl_encrypt(u_int8_t * buf, int len, u_int8_t * nbuf) 467 | { 468 | EVP_CIPHER_CTX *ctx; 469 | int outlen1, outlen2; 470 | #ifdef DEBUGSSL 471 | Debug("aes encrypt len=%d", len); 472 | #endif 473 | ctx = EVP_CIPHER_CTX_new(); 474 | if (enc_algorithm == AES_128) 475 | EVP_EncryptInit(ctx, EVP_aes_128_cbc(), enc_key, enc_iv); 476 | else if (enc_algorithm == AES_192) 477 | EVP_EncryptInit(ctx, EVP_aes_192_cbc(), enc_key, enc_iv); 478 | else if (enc_algorithm == AES_256) 479 | EVP_EncryptInit(ctx, EVP_aes_256_cbc(), enc_key, enc_iv); 480 | EVP_EncryptUpdate(ctx, nbuf, &outlen1, buf, len); 481 | EVP_EncryptFinal(ctx, nbuf + outlen1, &outlen2); 482 | len = outlen1 + outlen2; 483 | 484 | #ifdef DEBUGSSL 485 | Debug("after aes encrypt len=%d", len); 486 | #endif 487 | EVP_CIPHER_CTX_free(ctx); 488 | return len; 489 | } 490 | 491 | int openssl_decrypt(u_int8_t * buf, int len, u_int8_t * nbuf) 492 | { 493 | 494 | EVP_CIPHER_CTX *ctx; 495 | int outlen1, outlen2; 496 | #ifdef DEBUGSSL 497 | Debug("aes decrypt len=%d", len); 498 | #endif 499 | ctx = EVP_CIPHER_CTX_new(); 500 | if (enc_algorithm == AES_128) 501 | EVP_DecryptInit(ctx, EVP_aes_128_cbc(), enc_key, enc_iv); 502 | else if (enc_algorithm == AES_192) 503 | EVP_DecryptInit(ctx, EVP_aes_192_cbc(), enc_key, enc_iv); 504 | else if (enc_algorithm == AES_256) 505 | EVP_DecryptInit(ctx, EVP_aes_256_cbc(), enc_key, enc_iv); 506 | if (EVP_DecryptUpdate(ctx, nbuf, &outlen1, buf, len) != 1 || EVP_DecryptFinal(ctx, nbuf + outlen1, &outlen2) != 1) 507 | len = 0; 508 | else 509 | len = outlen1 + outlen2; 510 | #ifdef DEBUGSSL 511 | Debug("after aes decrypt len=%d", len); 512 | #endif 513 | EVP_CIPHER_CTX_free(ctx); 514 | return len; 515 | } 516 | #endif 517 | 518 | int do_encrypt(u_int8_t * buf, int len, u_int8_t * nbuf) 519 | { 520 | u_int8_t lzbuf[MAX_PACKET_SIZE + LZ4_SPACE]; 521 | int nlen; 522 | udp_total += len; 523 | if (lz4 > 0) { 524 | nlen = LZ4_compress_fast((char *)buf, (char *)lzbuf, len, len + LZ4_SPACE, lz4); 525 | if (nlen <= 0) { 526 | err_msg("lz4 compress error"); 527 | return 0; 528 | } 529 | if (debug) 530 | Debug("compress %d-->%d save %d byte", len, nlen, len - nlen); 531 | if (nlen < len) { // compressed 532 | lzbuf[nlen] = 0xff; // 0xff means compressed data 533 | nlen++; 534 | compress_save += len - nlen; 535 | len = nlen; 536 | buf = lzbuf; 537 | } else { 538 | buf[len] = 0xaa; // 0xaa means not compressed data 539 | compress_overhead++; 540 | len++; 541 | if (debug) 542 | Debug("not compressed %d", len); 543 | } 544 | } 545 | if (enc_key_len <= 0) { 546 | memcpy(nbuf, buf, len); 547 | return len; 548 | } 549 | if (enc_algorithm == XOR) 550 | nlen = xor_encrypt(buf, len, nbuf); 551 | #ifdef ENABLE_OPENSSL 552 | else if ((enc_algorithm == AES_128) 553 | || (enc_algorithm == AES_192) 554 | || (enc_algorithm == AES_256)) 555 | nlen = openssl_encrypt(buf, len, nbuf); 556 | #endif 557 | else 558 | return 0; 559 | if (debug) 560 | Debug("encrypt_overhead %d", nlen - len); 561 | encrypt_overhead += nlen - len; 562 | return nlen; 563 | } 564 | 565 | int do_decrypt(u_int8_t * buf, int len, u_int8_t * nbuf) 566 | { 567 | u_int8_t lzbuf[MAX_PACKET_SIZE + LZ4_SPACE]; 568 | if (enc_key_len > 0) { 569 | if (enc_algorithm == XOR) { 570 | len = xor_encrypt(buf, len, lzbuf); 571 | buf = lzbuf; 572 | } 573 | #ifdef ENABLE_OPENSSL 574 | else if ((enc_algorithm == AES_128) 575 | || (enc_algorithm == AES_192) 576 | || (enc_algorithm == AES_256)) { 577 | len = openssl_decrypt(buf, len, lzbuf); 578 | buf = lzbuf; 579 | } 580 | #endif 581 | } 582 | if ((lz4 > 0) && (len > 0)) { 583 | len--; 584 | if (buf[len] == 0xaa) { // not compressed data 585 | if (debug) 586 | Debug("decompress not compressed data %d", len); 587 | memcpy(nbuf, buf, len); 588 | } else if (buf[len] == 0xff) { // compressed data 589 | int nlen; 590 | nlen = LZ4_decompress_safe((char *)buf, (char *)nbuf, len, MAX_PACKET_SIZE + LZ4_SPACE); 591 | if (nlen < 0) { 592 | err_msg("lz4 decompress error"); 593 | return 0; 594 | } 595 | if (debug) 596 | Debug("decompress %d-->%d", len, nlen); 597 | len = nlen; 598 | } else { 599 | err_msg("len %d last byte error 0x%02X", len, buf[len]); 600 | return 0; 601 | } 602 | } else 603 | memcpy(nbuf, buf, len); 604 | return len; 605 | } 606 | 607 | char *stamp(void) 608 | { 609 | static char st_buf[200]; 610 | struct timeval tv; 611 | struct timezone tz; 612 | struct tm *tm; 613 | 614 | gettimeofday(&tv, &tz); 615 | tm = localtime(&tv.tv_sec); 616 | 617 | snprintf(st_buf, 200, "%02d%02d %02d:%02d:%02d.%06ld", tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec); 618 | return st_buf; 619 | } 620 | 621 | void printPacket(EtherPacket * packet, ssize_t packetSize, char *message) 622 | { 623 | printf("%s ", stamp()); 624 | 625 | if ((ntohl(packet->VLANTag) >> 16) == 0x8100) // VLAN tag 626 | printf("%s #%04x (VLAN %d) from %04x%08x to %04x%08x, len=%d\n", 627 | message, ntohs(packet->type), 628 | ntohl(packet->VLANTag) & 0xFFF, ntohs(packet->srcMAC1), 629 | ntohl(packet->srcMAC2), ntohs(packet->destMAC1), ntohl(packet->destMAC2), (int)packetSize); 630 | else 631 | printf("%s #%04x (no VLAN) from %04x%08x to %04x%08x, len=%d\n", 632 | message, ntohl(packet->VLANTag) >> 16, 633 | ntohs(packet->srcMAC1), ntohl(packet->srcMAC2), ntohs(packet->destMAC1), ntohl(packet->destMAC2), (int)packetSize); 634 | fflush(stdout); 635 | } 636 | 637 | // function from http://www.bloof.de/tcp_checksumming, thanks to crunsh 638 | u_int16_t tcp_sum_calc(u_int16_t len_tcp, u_int16_t src_addr[], u_int16_t dest_addr[], u_int16_t buff[]) 639 | { 640 | u_int16_t prot_tcp = 6; 641 | u_int32_t sum = 0; 642 | int nleft = len_tcp; 643 | u_int16_t *w = buff; 644 | 645 | /* calculate the checksum for the tcp header and payload */ 646 | while (nleft > 1) { 647 | sum += *w++; 648 | nleft -= 2; 649 | } 650 | 651 | /* if nleft is 1 there ist still on byte left. We add a padding byte (0xFF) to build a 16bit word */ 652 | if (nleft > 0) 653 | sum += *w & ntohs(0xFF00); /* Thanks to Dalton */ 654 | 655 | /* add the pseudo header */ 656 | sum += src_addr[0]; 657 | sum += src_addr[1]; 658 | sum += dest_addr[0]; 659 | sum += dest_addr[1]; 660 | sum += htons(len_tcp); 661 | sum += htons(prot_tcp); 662 | 663 | // keep only the last 16 bits of the 32 bit calculated sum and add the carries 664 | sum = (sum >> 16) + (sum & 0xFFFF); 665 | sum += (sum >> 16); 666 | 667 | // Take the one's complement of sum 668 | sum = ~sum; 669 | 670 | return ((u_int16_t) sum); 671 | } 672 | 673 | u_int16_t tcp_sum_calc_v6(u_int16_t len_tcp, u_int16_t src_addr[], u_int16_t dest_addr[], u_int16_t buff[]) 674 | { 675 | u_int16_t prot_tcp = 6; 676 | u_int32_t sum = 0; 677 | int nleft = len_tcp; 678 | u_int16_t *w = buff; 679 | 680 | /* calculate the checksum for the tcp header and payload */ 681 | while (nleft > 1) { 682 | sum += *w++; 683 | nleft -= 2; 684 | } 685 | 686 | /* if nleft is 1 there ist still on byte left. We add a padding byte (0xFF) to build a 16bit word */ 687 | if (nleft > 0) 688 | sum += *w & ntohs(0xFF00); /* Thanks to Dalton */ 689 | 690 | /* add the pseudo header */ 691 | int i; 692 | for (i = 0; i < 8; i++) 693 | sum = sum + src_addr[i] + dest_addr[i]; 694 | 695 | sum += htons(len_tcp); // why using 32bit len_tcp 696 | sum += htons(prot_tcp); 697 | 698 | // keep only the last 16 bits of the 32 bit calculated sum and add the carries 699 | sum = (sum >> 16) + (sum & 0xFFFF); 700 | sum += (sum >> 16); 701 | 702 | // Take the one's complement of sum 703 | sum = ~sum; 704 | 705 | return ((u_int16_t) sum); 706 | } 707 | 708 | static unsigned int optlen(const u_int8_t * opt, unsigned int offset) 709 | { 710 | /* Beware zero-length options: make finite progress */ 711 | if (opt[offset] <= TCPOPT_NOP || opt[offset + 1] == 0) 712 | return 1; 713 | else 714 | return opt[offset + 1]; 715 | } 716 | 717 | void fix_mss(u_int8_t * buf, int len, int index) 718 | { 719 | u_int8_t *packet; 720 | int i; 721 | 722 | if (len < 54) 723 | return; 724 | packet = buf + 12; // skip ethernet dst & src addr 725 | len -= 12; 726 | 727 | if ((packet[0] == 0x81) && (packet[1] == 0x00)) { // skip 802.1Q tag 0x8100 728 | packet += 4; 729 | len -= 4; 730 | } 731 | if ((packet[0] == 0x08) && (packet[1] == 0x00)) { // IPv4 packet 0x0800 732 | packet += 2; 733 | len -= 2; 734 | 735 | struct iphdr *ip = (struct iphdr *)packet; 736 | if (ip->version != 4) 737 | return; // check ipv4 738 | if (ntohs(ip->frag_off) & 0x1fff) 739 | return; // not the first fragment 740 | if (ip->protocol != IPPROTO_TCP) 741 | return; // not tcp packet 742 | if (ntohs(ip->tot_len) > len) 743 | return; // tot_len should < len 744 | 745 | struct tcphdr *tcph = (struct tcphdr *)(packet + ip->ihl * 4); 746 | if (!tcph->syn) 747 | return; 748 | 749 | if (debug) 750 | Debug("fixmss ipv4 tcp syn"); 751 | 752 | u_int8_t *opt = (u_int8_t *) tcph; 753 | for (i = sizeof(struct tcphdr); i < tcph->doff * 4; i += optlen(opt, i)) { 754 | if (opt[i] == 2 && tcph->doff * 4 - i >= 4 && // TCP_MSS 755 | opt[i + 1] == 4) { 756 | u_int16_t newmss = fixmss, oldmss; 757 | oldmss = (opt[i + 2] << 8) | opt[i + 3]; 758 | /* Never increase MSS, even when setting it, as 759 | * doing so results in problems for hosts that rely 760 | * on MSS being set correctly. 761 | */ 762 | if (oldmss <= newmss) 763 | return; 764 | if (debug) 765 | Debug("change inner v4 tcp mss from %d to %d", oldmss, newmss); 766 | opt[i + 2] = (newmss & 0xff00) >> 8; 767 | opt[i + 3] = newmss & 0x00ff; 768 | 769 | tcph->check = 0; /* Checksum field has to be set to 0 before checksumming */ 770 | tcph->check = (u_int16_t) 771 | tcp_sum_calc((u_int16_t) 772 | (ntohs(ip->tot_len) - ip->ihl * 4), (u_int16_t *) & ip->saddr, (u_int16_t *) & ip->daddr, (u_int16_t *) tcph); 773 | return; 774 | } 775 | } 776 | } else if ((packet[0] == 0x86) && (packet[1] == 0xdd)) { // IPv6 packet, 0x86dd 777 | packet += 2; 778 | len -= 2; 779 | 780 | struct ip6_hdr *ip6 = (struct ip6_hdr *)packet; 781 | if ((ip6->ip6_vfc & 0xf0) != 0x60) 782 | return; // check ipv6 783 | if (ip6->ip6_nxt != IPPROTO_TCP) 784 | return; // not tcp packet 785 | if (ntohs(ip6->ip6_plen) > len) 786 | return; // tot_len should < len 787 | 788 | struct tcphdr *tcph = (struct tcphdr *)(packet + 40); 789 | if (!tcph->syn) 790 | return; 791 | if (debug) 792 | Debug("fixmss ipv6 tcp syn"); 793 | u_int8_t *opt = (u_int8_t *) tcph; 794 | for (i = sizeof(struct tcphdr); i < tcph->doff * 4; i += optlen(opt, i)) { 795 | if (opt[i] == 2 && tcph->doff * 4 - i >= 4 && // TCP_MSS 796 | opt[i + 1] == 4) { 797 | u_int16_t newmss = fixmss, oldmss; 798 | oldmss = (opt[i + 2] << 8) | opt[i + 3]; 799 | /* Never increase MSS, even when setting it, as 800 | * doing so results in problems for hosts that rely 801 | * on MSS being set correctly. 802 | */ 803 | if (oldmss <= newmss) 804 | return; 805 | if (debug) 806 | Debug("change inner v6 tcp mss from %d to %d", oldmss, newmss); 807 | 808 | opt[i + 2] = (newmss & 0xff00) >> 8; 809 | opt[i + 3] = newmss & 0x00ff; 810 | 811 | tcph->check = 0; /* Checksum field has to be set to 0 before checksumming */ 812 | tcph->check = (u_int16_t) tcp_sum_calc_v6((u_int16_t) 813 | ntohs(ip6->ip6_plen), 814 | (u_int16_t *) & ip6->ip6_src, (u_int16_t *) & ip6->ip6_dst, (u_int16_t *) 815 | tcph); 816 | return; 817 | } 818 | } 819 | } 820 | } 821 | 822 | /* return 1 if packet will cause loopback, DSTIP or SRCIP == remote address && PROTO == UDP 823 | */ 824 | int do_loopback_check(u_int8_t * buf, int len) 825 | { 826 | u_int8_t *packet; 827 | 828 | if (len < 14) // MAC(12)+Proto(2)+IP(20) 829 | return 0; 830 | packet = buf + 12; // skip ethernet dst & src addr 831 | len -= 12; 832 | 833 | if ((packet[0] == 0x81) && (packet[1] == 0x00)) { // skip 802.1Q tag 0x8100 834 | packet += 4; 835 | len -= 4; 836 | } 837 | if ((packet[0] == 0x08) && (packet[1] == 0x00)) { // IPv4 packet 0x0800 838 | packet += 2; 839 | len -= 2; 840 | 841 | if (len < 20) // IP header len is 20 842 | return 0; 843 | 844 | struct iphdr *ip = (struct iphdr *)packet; 845 | if (ip->version != 4) 846 | return 0; // not ipv4 847 | if (ip->protocol != IPPROTO_UDP) 848 | return 0; // not udp packet 849 | 850 | struct sockaddr_in *r = (struct sockaddr_in *)(&remote_addr[MASTER]); 851 | if (ip->saddr == r->sin_addr.s_addr) { 852 | if (debug) 853 | Debug("master remote ipaddr == src addr, loopback"); 854 | return 1; 855 | } else if (ip->daddr == r->sin_addr.s_addr) { 856 | if (debug) 857 | Debug("master remote ipaddr == dst addr, loopback"); 858 | return 1; 859 | } 860 | if (master_slave) { 861 | r = (struct sockaddr_in *)(&remote_addr[SLAVE]); 862 | if (ip->saddr == r->sin_addr.s_addr) { 863 | if (debug) 864 | Debug("slave remote ipaddr == src addr, loopback"); 865 | return 1; 866 | } else if (ip->daddr == r->sin_addr.s_addr) { 867 | if (debug) 868 | Debug("slave remote ipaddr == dst addr, loopback"); 869 | return 1; 870 | } 871 | } 872 | } else if ((packet[0] == 0x86) && (packet[1] == 0xdd)) { // IPv6 packet, 0x86dd 873 | packet += 2; 874 | len -= 2; 875 | 876 | if (len < 40) // IPv6 header len is 40 877 | return 0; 878 | 879 | struct ip6_hdr *ip6 = (struct ip6_hdr *)packet; 880 | if ((ip6->ip6_vfc & 0xf0) != 0x60) 881 | return 0; // not ipv6 882 | if (ip6->ip6_nxt != IPPROTO_UDP) 883 | return 0; // not udp packet 884 | 885 | struct sockaddr_in6 *r = (struct sockaddr_in6 *)&remote_addr[MASTER]; 886 | if (memcmp(&ip6->ip6_src, &r->sin6_addr, 16) == 0) { 887 | if (debug) 888 | Debug("master remote ip6_addr == src ip6 addr, loopback"); 889 | return 1; 890 | } else if (memcmp(&ip6->ip6_dst, &r->sin6_addr, 16) == 0) { 891 | if (debug) 892 | Debug("master remote ip6_addr == dst ip6 addr, loopback"); 893 | return 1; 894 | } 895 | if (master_slave) { 896 | r = (struct sockaddr_in6 *)&remote_addr[SLAVE]; 897 | if (memcmp(&ip6->ip6_src, &r->sin6_addr, 16) == 0) { 898 | if (debug) 899 | Debug("slave remote ip6_addr == src ip6 addr, loopback"); 900 | return 1; 901 | } else if (memcmp(&ip6->ip6_dst, &r->sin6_addr, 16) == 0) { 902 | if (debug) 903 | Debug("slave remote ip6_addr == dst ip6 addr, loopback"); 904 | return 1; 905 | } 906 | } 907 | } 908 | return 0; 909 | } 910 | 911 | void send_udp_to_remote(u_int8_t * buf, int len, int index); 912 | 913 | void send_frag_udp(u_int8_t * buf, int len, int index) 914 | { 915 | unsigned char newbuf[MAX_PACKET_SIZE]; 916 | if (len >= 2000) // should not go here 917 | return; 918 | if (len <= 1000) // should not go here 919 | return; 920 | memcpy(newbuf, "UDPFRG", 6); 921 | newbuf[6] = (udp_frg_seq >> 8) & 0xff; 922 | newbuf[7] = udp_frg_seq & 0xff; 923 | memcpy(newbuf + 8, buf, 1000); 924 | if (debug) 925 | Debug("send frag %d, len=1000, total_len=%d", udp_frg_seq, len); 926 | send_udp_to_remote(newbuf, 1008, index); 927 | udp_frg_seq++; 928 | if (udp_frg_seq >= MAXPKTS) 929 | udp_frg_seq = 0; 930 | newbuf[6] = (udp_frg_seq >> 8) & 0xff; 931 | newbuf[7] = udp_frg_seq & 0xff; 932 | memcpy(newbuf + 8, buf + 1000, len - 1000); 933 | if (debug) 934 | Debug("send frag %d, len=%d, total_len=%d", udp_frg_seq, len - 1000, len); 935 | send_udp_to_remote(newbuf, 8 + len - 1000, index); 936 | udp_frg_seq++; 937 | if (udp_frg_seq >= MAXPKTS) 938 | udp_frg_seq = 0; 939 | } 940 | 941 | void send_udp_to_remote(u_int8_t * buf, int len, int index) // send udp packet to remote 942 | { 943 | if ((mtu > 0) && (len > mtu - 28)) 944 | return send_frag_udp(buf, len, index); 945 | if (nat[index]) { 946 | char rip[200]; 947 | if (remote_addr[index].ss_family == AF_INET) { 948 | struct sockaddr_in *r = (struct sockaddr_in *)(&remote_addr[index]); 949 | if (debug) 950 | Debug("nat mode: send len %d to %s:%d", len, inet_ntop(r->sin_family, (void *)&r->sin_addr, rip, 200), ntohs(r->sin_port)); 951 | if (r->sin_port) { 952 | sendto(fdudp[index], buf, len, 0, (struct sockaddr *)&remote_addr[index], sizeof(struct sockaddr_storage)); 953 | udp_send_pkt[index]++; 954 | udp_send_byte[index] += len; 955 | } 956 | } else if (remote_addr[index].ss_family == AF_INET6) { 957 | struct sockaddr_in6 *r = (struct sockaddr_in6 *)&remote_addr[index]; 958 | if (debug) 959 | Debug("nat mode: send len %d to [%s]:%d", len, inet_ntop(r->sin6_family, (void *)&r->sin6_addr, rip, 200), ntohs(r->sin6_port)); 960 | if (r->sin6_port) { 961 | sendto(fdudp[index], buf, len, 0, (struct sockaddr *)&remote_addr[index], sizeof(struct sockaddr_storage)); 962 | udp_send_pkt[index]++; 963 | udp_send_byte[index] += len; 964 | } 965 | } 966 | } else { 967 | if (write(fdudp[index], buf, len) != len) 968 | udp_send_err[index]++; 969 | else { 970 | udp_send_pkt[index]++; 971 | udp_send_byte[index] += len; 972 | } 973 | } 974 | } 975 | 976 | void print_addrinfo(int index) 977 | { 978 | char localip[200]; 979 | char cmd_remoteip[200]; 980 | char remoteip[200]; 981 | if (local_addr[index].ss_family == AF_INET) { 982 | struct sockaddr_in *r = (struct sockaddr_in *)(&local_addr[index]); 983 | int lp, c_rp, rp; 984 | lp = ntohs(r->sin_port); 985 | inet_ntop(AF_INET, &r->sin_addr, localip, 200); 986 | r = (struct sockaddr_in *)(&cmd_remote_addr[index]); 987 | c_rp = ntohs(r->sin_port); 988 | inet_ntop(AF_INET, &r->sin_addr, cmd_remoteip, 200); 989 | r = (struct sockaddr_in *)(&remote_addr[index]); 990 | rp = ntohs(r->sin_port); 991 | inet_ntop(AF_INET, &r->sin_addr, remoteip, 200); 992 | if (nat[index]) 993 | err_msg("%s: ST:%d %s:%d --> %s:%d(%s:%d)", index == 0 ? "MASTER" : " SLAVE", index == 0 ? master_status : slave_status, localip, lp, 994 | remoteip, rp, cmd_remoteip, c_rp); 995 | else 996 | err_msg("%s: ST:%d %s:%d --> %s:%d", index == 0 ? "MASTER" : " SLAVE", index == 0 ? master_status : slave_status, localip, lp, remoteip, 997 | rp); 998 | } else if (local_addr[index].ss_family == AF_INET6) { 999 | struct sockaddr_in6 *r = (struct sockaddr_in6 *)(&local_addr[index]); 1000 | int lp, c_rp, rp; 1001 | lp = ntohs(r->sin6_port); 1002 | inet_ntop(AF_INET6, &r->sin6_addr, localip, 200); 1003 | r = (struct sockaddr_in6 *)(&cmd_remote_addr[index]); 1004 | c_rp = ntohs(r->sin6_port); 1005 | inet_ntop(AF_INET6, &r->sin6_addr, cmd_remoteip, 200); 1006 | r = (struct sockaddr_in6 *)(&remote_addr[index]); 1007 | rp = ntohs(r->sin6_port); 1008 | inet_ntop(AF_INET6, &r->sin6_addr, remoteip, 200); 1009 | if (nat[index]) 1010 | err_msg("%s: ST:%d [%s]:%d --> [%s]:%d([%s]:%d)", index == 0 ? "MASTER" : " SLAVE", index == 0 ? master_status : slave_status, localip, 1011 | lp, remoteip, rp, cmd_remoteip, c_rp); 1012 | else 1013 | err_msg("%s: ST:%d [%s]:%d --> [%s]:%d", index == 0 ? "MASTER" : " SLAVE", index == 0 ? master_status : slave_status, localip, lp, 1014 | remoteip, rp); 1015 | } 1016 | } 1017 | 1018 | void send_keepalive_to_udp(void) // send keepalive to remote 1019 | { 1020 | u_int8_t buf[MAX_PACKET_SIZE + EVP_MAX_BLOCK_LENGTH]; 1021 | u_int8_t nbuf[MAX_PACKET_SIZE + EVP_MAX_BLOCK_LENGTH]; 1022 | u_int8_t *pbuf; 1023 | int len; 1024 | static u_int32_t lasttm; 1025 | while (1) { 1026 | if (got_signal || (myticket >= lasttm + 3600)) { // log ping/pong every hour 1027 | 1028 | err_msg("============= version: %s, myticket=%lu, master_slave=%d, current_remote=%s, loopback_check=%d", 1029 | VERSION, myticket, master_slave, current_remote == 0 ? "MASTER" : "SLAVE", loopback_check); 1030 | print_addrinfo(MASTER); 1031 | if (master_slave) 1032 | print_addrinfo(SLAVE); 1033 | err_msg("master ping_send/pong_recv: %lu/%lu, ping_recv/pong_send: %lu/%lu, udp_send_err: %lu", 1034 | ping_send[MASTER], pong_recv[MASTER], ping_recv[MASTER], pong_send[MASTER], udp_send_err[MASTER]); 1035 | if (master_slave) 1036 | err_msg(" slave ping_send/pong_recv: %lu/%lu, ping_recv/pong_send: %lu/%lu, udp_send_err: %lu", ping_send[SLAVE], 1037 | pong_recv[SLAVE], ping_recv[SLAVE], pong_send[SLAVE], udp_send_err[SLAVE]); 1038 | if (myticket >= lasttm + 3600) { 1039 | ping_send[MASTER] = ping_send[SLAVE] = ping_recv[MASTER] = ping_recv[SLAVE] = 0; 1040 | pong_send[MASTER] = pong_send[SLAVE] = pong_recv[MASTER] = pong_recv[SLAVE] = 0; 1041 | lasttm = myticket; 1042 | } 1043 | err_msg(" raw interface recv:%lu/%lu send:%lu/%lu, raw_send_err: %lu", raw_recv_pkt, raw_recv_byte, raw_send_pkt, raw_send_byte, 1044 | raw_send_err); 1045 | err_msg("master udp interface recv:%lu/%lu send:%lu/%lu", udp_recv_pkt[MASTER], udp_recv_byte[MASTER], udp_send_pkt[MASTER], 1046 | udp_send_byte[MASTER]); 1047 | if (master_slave) 1048 | err_msg(" slave udp interface recv:%lu/%lu send:%lu/%lu", udp_recv_pkt[SLAVE], udp_recv_byte[SLAVE], udp_send_pkt[SLAVE], 1049 | udp_send_byte[SLAVE]); 1050 | err_msg("udp %lu bytes, lz4 save %lu bytes, lz4 overhead %lu bytes, encrypt overhead %lu bytes, %.0f%%", 1051 | udp_total, compress_save, compress_overhead, encrypt_overhead, 1052 | 100.0 * (udp_total - compress_save + compress_overhead + encrypt_overhead) / udp_total); 1053 | got_signal = 0; 1054 | } 1055 | myticket++; 1056 | if (run_seconds > 0) { 1057 | if (myticket > run_seconds) { 1058 | err_msg("run_seconds %d expired, exit", run_seconds); 1059 | exit(0); 1060 | } 1061 | } 1062 | if (mypassword[0]) { 1063 | len = snprintf((char *)buf, MAX_PACKET_SIZE, "PASSWORD:%s", mypassword); 1064 | if (debug) 1065 | Debug("send password: %s", buf); 1066 | len++; 1067 | if ((enc_key_len > 0) || (lz4 > 0)) { 1068 | len = do_encrypt((u_int8_t *) buf, len, nbuf); 1069 | pbuf = nbuf; 1070 | } else 1071 | pbuf = buf; 1072 | if (nat[MASTER] == 0) 1073 | send_udp_to_remote(pbuf, len, MASTER); // send to master 1074 | if (master_slave && (nat[SLAVE] == 0)) 1075 | send_udp_to_remote(pbuf, len, SLAVE); // send to slave 1076 | } 1077 | memcpy(buf, "PING:PING:", 10); 1078 | len = 10; 1079 | if ((enc_key_len > 0) || (lz4 > 0)) { 1080 | len = do_encrypt((u_int8_t *) buf, len, nbuf); 1081 | pbuf = nbuf; 1082 | } else 1083 | pbuf = buf; 1084 | send_udp_to_remote(pbuf, len, MASTER); // send to master 1085 | ping_send[MASTER]++; 1086 | 1087 | if (master_status == STATUS_OK) { // now master is OK 1088 | if (myticket > last_pong[MASTER] + 5) { // master OK->BAD 1089 | master_status = STATUS_BAD; 1090 | if (master_slave) 1091 | current_remote = SLAVE; // switch to SLAVE 1092 | err_msg("master OK-->BAD, slave %s, current_remote is %s", slave_status == STATUS_OK ? "OK" : "BAD", 1093 | current_remote == 0 ? "MASTER" : "SLAVE"); 1094 | } 1095 | } else { // now master is BAD 1096 | if (myticket < last_pong[MASTER] + 4) { // master BAD->OK 1097 | master_status = STATUS_OK; 1098 | current_remote = MASTER; // switch to MASTER 1099 | err_msg("master BAD-->OK, slave %s, current_remote is %s", slave_status == STATUS_OK ? "OK" : "BAD", 1100 | current_remote == 0 ? "MASTER" : "SLAVE"); 1101 | } 1102 | } 1103 | 1104 | if (master_slave) { 1105 | send_udp_to_remote(pbuf, len, SLAVE); // send to slave 1106 | ping_send[SLAVE]++; 1107 | 1108 | if (slave_status == STATUS_OK) { // now slave is OK 1109 | if (myticket > last_pong[SLAVE] + 5) { // slave OK->BAD 1110 | slave_status = STATUS_BAD; 1111 | err_msg("slave OK-->BAD, master %s, current_remote is %s", master_status == STATUS_OK ? "OK" : "BAD", 1112 | current_remote == 0 ? "MASTER" : "SLAVE"); 1113 | } 1114 | } else { // now slave is BAD 1115 | if (myticket < last_pong[SLAVE] + 4) { // slave BAD->OK 1116 | slave_status = STATUS_OK; 1117 | err_msg("slave BAD-->OK, master %s, current_remote is %s", master_status == STATUS_OK ? "OK" : "BAD", 1118 | current_remote == 0 ? "MASTER" : "SLAVE"); 1119 | } 1120 | } 1121 | } 1122 | sleep(1); 1123 | } 1124 | } 1125 | 1126 | void process_raw_to_udp(void) // used by mode==0 & mode==1 1127 | { 1128 | u_int8_t *buf, mybuf[MAX_PACKET_SIZE + VLAN_TAG_LEN]; 1129 | u_int8_t nbuf[MAX_PACKET_SIZE + VLAN_TAG_LEN + EVP_MAX_BLOCK_LENGTH + LZ4_SPACE]; 1130 | u_int8_t *pbuf; 1131 | int len; 1132 | int offset = 0; 1133 | 1134 | while (1) { // read from eth rawsocket 1135 | if (mode == MODEE) { 1136 | buf = mybuf; 1137 | #ifdef HAVE_PACKET_AUXDATA 1138 | struct sockaddr from; 1139 | struct iovec iov; 1140 | struct msghdr msg; 1141 | struct cmsghdr *cmsg; 1142 | union { 1143 | struct cmsghdr cmsg; 1144 | char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))]; 1145 | } cmsg_buf; 1146 | msg.msg_name = &from; 1147 | msg.msg_namelen = sizeof(from); 1148 | msg.msg_iov = &iov; 1149 | msg.msg_iovlen = 1; 1150 | msg.msg_control = &cmsg_buf; 1151 | msg.msg_controllen = sizeof(cmsg_buf); 1152 | msg.msg_flags = 0; 1153 | 1154 | offset = VLAN_TAG_LEN; 1155 | iov.iov_len = MAX_PACKET_SIZE; 1156 | iov.iov_base = buf + offset; 1157 | len = recvmsg(fdraw, &msg, MSG_TRUNC); 1158 | if (len <= 0) 1159 | continue; 1160 | if (len >= MAX_PACKET_SIZE) { 1161 | err_msg("recv long pkt from raw, len=%d", len); 1162 | len = MAX_PACKET_SIZE; 1163 | } 1164 | for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 1165 | struct tpacket_auxdata *aux; 1166 | struct vlan_tag *tag; 1167 | 1168 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) 1169 | || cmsg->cmsg_level != SOL_PACKET || cmsg->cmsg_type != PACKET_AUXDATA) 1170 | continue; 1171 | 1172 | aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg); 1173 | 1174 | #if defined(TP_STATUS_VLAN_VALID) 1175 | if ((aux->tp_vlan_tci == 0) 1176 | && !(aux->tp_status & TP_STATUS_VLAN_VALID)) 1177 | #else 1178 | if (aux->tp_vlan_tci == 0) /* this is ambigious but without the */ 1179 | #endif 1180 | continue; 1181 | 1182 | if (debug) 1183 | Debug("len=%d, iov_len=%d, ", len, (int)iov.iov_len); 1184 | 1185 | len = len > iov.iov_len ? iov.iov_len : len; 1186 | if (len < 12) // MAC_len * 2 1187 | break; 1188 | if (debug) 1189 | Debug("len=%d", len); 1190 | 1191 | memmove(buf, buf + VLAN_TAG_LEN, 12); 1192 | offset = 0; 1193 | 1194 | /* 1195 | * Now insert the tag. 1196 | */ 1197 | tag = (struct vlan_tag *)(buf + 12); 1198 | if (debug) 1199 | Debug("insert vlan id, recv len=%d", len); 1200 | 1201 | #ifdef TP_STATUS_VLAN_TPID_VALID 1202 | tag->vlan_tpid = ((aux->tp_vlan_tpid || (aux->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? htons(aux->tp_vlan_tpid) : ETHP8021Q); 1203 | #else 1204 | tag->vlan_tpid = ETHP8021Q; 1205 | #endif 1206 | tag->vlan_tci = htons(aux->tp_vlan_tci); 1207 | 1208 | /* Add the tag to the packet lengths. 1209 | */ 1210 | len += VLAN_TAG_LEN; 1211 | break; 1212 | } 1213 | #else 1214 | len = recv(fdraw, buf, MAX_PACKET_SIZE, 0); 1215 | #endif 1216 | } else if ((mode == MODEI) || (mode == MODEB)) { 1217 | buf = mybuf; 1218 | len = read(fdraw, buf, MAX_PACKET_SIZE); 1219 | if (len >= MAX_PACKET_SIZE) { 1220 | err_msg("recv long pkt from raw, len=%d", len); 1221 | len = MAX_PACKET_SIZE; 1222 | } 1223 | } else if (mode == MODET) { 1224 | struct pcap_pkthdr *header; 1225 | int r = pcap_next_ex(pcap_handle, &header, (const u_char **)&buf); 1226 | if (r <= 0) 1227 | continue; 1228 | len = header->len; 1229 | } else if (mode == MODEU) { 1230 | struct pcap_pkthdr *header; 1231 | int r = pcap_next_ex(pcap_handle, &header, (const u_char **)&buf); 1232 | if (r <= 0) 1233 | continue; 1234 | len = header->len; 1235 | } else 1236 | return; 1237 | 1238 | if (len <= 0) 1239 | continue; 1240 | if (write_only) 1241 | continue; // write only 1242 | 1243 | raw_recv_pkt++; 1244 | raw_recv_byte += len; 1245 | if (loopback_check && do_loopback_check(buf + offset, len)) 1246 | continue; 1247 | if (debug) { 1248 | printPacket((EtherPacket *) (buf + offset), len, "from local rawsocket:"); 1249 | if (offset) 1250 | Debug("offset=%d", offset); 1251 | } 1252 | if (!read_only && fixmss) // read only, no fix_mss 1253 | fix_mss(buf + offset, len, current_remote); 1254 | 1255 | if (vlan_map && len >= 16) { 1256 | struct vlan_tag *tag; 1257 | tag = (struct vlan_tag *)(buf + offset + 12); 1258 | if (tag->vlan_tpid == ETHP8021Q) { 1259 | int vlan; 1260 | vlan = ntohs(tag->vlan_tci) & 0xfff; 1261 | if (my_vlan[vlan] != vlan) { 1262 | tag->vlan_tci = htons((ntohs(tag->vlan_tci) & 0xf000) + my_vlan[vlan]); 1263 | if (debug) { 1264 | if (debug) 1265 | Debug("maping vlan %d to %d", vlan, my_vlan[vlan]); 1266 | printPacket((EtherPacket *) (buf + offset), len, "from local rawsocket:"); 1267 | } 1268 | } 1269 | } 1270 | } 1271 | if ((enc_key_len > 0) || (lz4 > 0)) { 1272 | len = do_encrypt((u_int8_t *) buf + offset, len, nbuf); 1273 | pbuf = nbuf; 1274 | } else 1275 | pbuf = buf + offset; 1276 | if (mode == MODEU) { // find the UDP packet 1277 | u_int8_t *packet; 1278 | if (len < 40) 1279 | return; 1280 | packet = buf + 12; // skip ethernet dst & src addr 1281 | len -= 12; 1282 | if ((packet[0] == 0x81) && (packet[1] == 0x00)) { // skip 802.1Q tag 0x8100 1283 | packet += 4; 1284 | len -= 4; 1285 | } 1286 | if ((packet[0] == 0x08) && (packet[1] == 0x00)) { // IPv4 packet 0x0800 1287 | packet += 2; 1288 | len -= 2; 1289 | struct iphdr *ip = (struct iphdr *)packet; 1290 | if (ip->version != 4) 1291 | return; // only support IPv4 1292 | if (ntohs(ip->frag_off) & 0x1fff) 1293 | return; // not the first fragment 1294 | if (ip->protocol != IPPROTO_UDP) 1295 | return; // not UDP packet 1296 | if (ntohs(ip->tot_len) > len) 1297 | return; // tot_len should < len 1298 | 1299 | struct udphdr *udph = (struct udphdr *)(packet + ip->ihl * 4); 1300 | pbuf = packet + ip->ihl * 4 + 8; 1301 | len = ntohs(udph->len) - 8; 1302 | } else 1303 | return; 1304 | } 1305 | 1306 | send_udp_to_remote(pbuf, len, current_remote); 1307 | } 1308 | } 1309 | 1310 | void save_remote_addr(struct sockaddr_storage *rmt, int sock_len, int index) 1311 | { 1312 | char rip[200]; 1313 | if (memcmp((void *)rmt, (void *)(&remote_addr[index]), sock_len) == 0) 1314 | return; 1315 | if (rmt->ss_family == AF_INET) { 1316 | struct sockaddr_in *r = (struct sockaddr_in *)rmt; 1317 | struct sockaddr_in *cmdr = (struct sockaddr_in *)&cmd_remote_addr[index]; 1318 | if (((cmdr->sin_addr.s_addr == 0) || (cmdr->sin_addr.s_addr == r->sin_addr.s_addr)) 1319 | && ((cmdr->sin_port == 0) || (cmdr->sin_port == r->sin_port))) { 1320 | memcpy((void *)&remote_addr[index], rmt, sock_len); 1321 | err_msg("nat mode, change %s remote to %s:%d", index == 0 ? "master" : "slave", 1322 | inet_ntop(r->sin_family, (void *)&r->sin_addr, rip, 200), ntohs(r->sin_port)); 1323 | } else 1324 | err_msg("nat mode, do not change %s remote to %s:%d", index == 0 ? "master" : "slave", 1325 | inet_ntop(r->sin_family, (void *)&r->sin_addr, rip, 200), ntohs(r->sin_port)); 1326 | } else if (rmt->ss_family == AF_INET6) { 1327 | struct sockaddr_in6 *r = (struct sockaddr_in6 *)rmt; 1328 | struct sockaddr_in6 *cmdr = (struct sockaddr_in6 *)&cmd_remote_addr[index]; 1329 | struct in6_addr ia6 = IN6ADDR_ANY_INIT; 1330 | if (((memcmp(&ia6, &cmdr->sin6_addr, 16) == 0) || (memcmp(&r->sin6_addr, &cmdr->sin6_addr, 16) == 0)) 1331 | && ((cmdr->sin6_port == 0) || (cmdr->sin6_port == r->sin6_port))) { 1332 | memcpy((void *)&remote_addr[index], rmt, sock_len); 1333 | err_msg("nat mode, change %s remote to [%s]:%d", index == 0 ? "master" : "slave", 1334 | inet_ntop(r->sin6_family, (void *)&r->sin6_addr, rip, 200), ntohs(r->sin6_port)); 1335 | } 1336 | err_msg("nat mode, do not change %s remote to [%s]:%d", index == 0 ? "master" : "slave", 1337 | inet_ntop(r->sin6_family, (void *)&r->sin6_addr, rip, 200), ntohs(r->sin6_port)); 1338 | } 1339 | } 1340 | 1341 | void add_to_udp_frag_buf(time_t rcvt, int seq, unsigned char *buf, int len) 1342 | { 1343 | if (packet_bufs[seq].rcvt > 0) // del old packet 1344 | free(packet_bufs[seq].buf); 1345 | packet_bufs[seq].buf = malloc(len); 1346 | if (packet_bufs[seq].buf == NULL) { 1347 | Debug("malloc error\n"); 1348 | packet_bufs[seq].rcvt = 0; 1349 | return; 1350 | } 1351 | memcpy(packet_bufs[seq].buf, buf, len); 1352 | packet_bufs[seq].len = len; 1353 | packet_bufs[seq].rcvt = rcvt; 1354 | if (debug) 1355 | Debug("udp_frag seq %d, len=%d stored", seq, len); 1356 | } 1357 | 1358 | int do_udp_frag_recv(unsigned char *buf, int len) 1359 | { 1360 | time_t tm = time(NULL); 1361 | int seq = (buf[6] << 8) + buf[7]; 1362 | int pair_seq = (seq & 0xfffe) + ((seq & 1) ^ 1); 1363 | if (debug) 1364 | Debug("Got udp_frag seq %d, len=%d", seq, len - 8); 1365 | if ((len > 1008) || (len < 8)) { 1366 | if (debug) 1367 | Debug("len=%d is invalid, drop it\n", len); 1368 | return 0; 1369 | } 1370 | if (packet_bufs[pair_seq].rcvt == 0) { // pair not in buf, store in buf 1371 | add_to_udp_frag_buf(tm, seq, buf + 8, len - 8); 1372 | return 0; 1373 | } 1374 | 1375 | if (tm - packet_bufs[pair_seq].rcvt > 1) { // pair time is too long(>1s), invalid, store in buf 1376 | add_to_udp_frag_buf(tm, seq, buf + 8, len - 8); 1377 | return 0; 1378 | } 1379 | 1380 | if ((seq & 1) == 0) { // this is the first packet 1381 | memmove(buf, buf + 8, len - 8); 1382 | memcpy(buf + len - 8, packet_bufs[pair_seq].buf, packet_bufs[pair_seq].len); 1383 | } else { 1384 | memmove(buf + packet_bufs[pair_seq].len, buf + 8, len - 8); 1385 | memcpy(buf, packet_bufs[pair_seq].buf, packet_bufs[pair_seq].len); 1386 | } 1387 | len = len - 8 + packet_bufs[pair_seq].len; 1388 | packet_bufs[pair_seq].rcvt = 0; 1389 | packet_bufs[pair_seq].len = 0; 1390 | free(packet_bufs[pair_seq].buf); 1391 | packet_bufs[pair_seq].buf = NULL; 1392 | if (debug) 1393 | Debug("udp_frag new pkt len %d", len); 1394 | return len; 1395 | } 1396 | 1397 | void process_udp_to_raw(int index) 1398 | { 1399 | u_int8_t buf[MAX_PACKET_SIZE + EVP_MAX_BLOCK_LENGTH + LZ4_SPACE]; 1400 | u_int8_t nbuf[MAX_PACKET_SIZE + EVP_MAX_BLOCK_LENGTH]; 1401 | u_int8_t *pbuf; 1402 | int len; 1403 | 1404 | while (1) { // read from remote udp 1405 | if (nat[index]) { 1406 | struct sockaddr_storage rmt; 1407 | socklen_t sock_len = sizeof(struct sockaddr_storage); 1408 | len = recvfrom(fdudp[index], buf, MAX_PACKET_SIZE, 0, (struct sockaddr *)&rmt, &sock_len); 1409 | if (debug) { 1410 | char rip[200]; 1411 | if (rmt.ss_family == AF_INET) { 1412 | struct sockaddr_in *r = (struct sockaddr_in *)&rmt; 1413 | if (debug) 1414 | Debug("nat mode: len %d recv from %s:%d", 1415 | len, inet_ntop(r->sin_family, (void *)&r->sin_addr, rip, 200), ntohs(r->sin_port)); 1416 | } else if (rmt.ss_family == AF_INET6) { 1417 | struct sockaddr_in6 *r = (struct sockaddr_in6 *)&rmt; 1418 | if (debug) 1419 | Debug("nat mode: len %d recv from [%s]:%d", 1420 | len, inet_ntop(r->sin6_family, (void *)&r->sin6_addr, rip, 200), ntohs(r->sin6_port)); 1421 | } 1422 | } 1423 | if (len <= 0) 1424 | continue; 1425 | 1426 | if (len >= MAX_PACKET_SIZE) { 1427 | err_msg("recv long pkt from udp, len=%d", len); 1428 | len = MAX_PACKET_SIZE; 1429 | } 1430 | 1431 | if ((mtu > 0) && (memcmp(buf, "UDPFRG", 6) == 0)) { 1432 | len = do_udp_frag_recv(buf, len); 1433 | if (len <= 0) // waiting the pair packet 1434 | continue; 1435 | } 1436 | 1437 | if ((enc_key_len > 0) || (lz4 > 0)) { 1438 | len = do_decrypt((u_int8_t *) buf, len, nbuf); 1439 | pbuf = nbuf; 1440 | } else 1441 | pbuf = buf; 1442 | 1443 | if (len <= 0) 1444 | continue; 1445 | 1446 | udp_recv_pkt[index]++; 1447 | udp_recv_byte[index] += len; 1448 | nbuf[len] = 0; 1449 | if (mypassword[0] == 0) { // no password set, accept new ip and port 1450 | if (debug) 1451 | Debug("no password, accept new remote ip and port"); 1452 | save_remote_addr(&rmt, sock_len, index); 1453 | if (memcmp(pbuf, "PASSWORD:", 9) == 0) // got password packet, skip this packet 1454 | continue; 1455 | } else { 1456 | if (memcmp(pbuf, "PASSWORD:", 9) == 0) { // got password packet 1457 | if (debug) 1458 | Debug("password packet from remote %s", pbuf); 1459 | if ((memcmp(pbuf + 9, mypassword, strlen(mypassword)) == 0) 1460 | && (*(pbuf + 9 + strlen(mypassword)) 1461 | == 0)) { 1462 | if (debug) 1463 | Debug("password ok"); 1464 | save_remote_addr(&rmt, sock_len, index); 1465 | } else if (debug) 1466 | Debug("passowrd error"); 1467 | continue; 1468 | } 1469 | if (memcmp((void *)&remote_addr[index], &rmt, sock_len)) { 1470 | if (debug) 1471 | Debug("packet from unknow host, drop..."); 1472 | continue; 1473 | } 1474 | } 1475 | } else { 1476 | len = recv(fdudp[index], buf, MAX_PACKET_SIZE, 0); 1477 | if (len >= MAX_PACKET_SIZE) { 1478 | err_msg("recv long pkt from UDP, len=%d", len); 1479 | len = MAX_PACKET_SIZE; 1480 | } 1481 | if (len <= 0) 1482 | continue; 1483 | 1484 | if ((mtu > 0) && (memcmp(buf, "UDPFRG", 6) == 0)) { 1485 | len = do_udp_frag_recv(buf, len); 1486 | if (len <= 0) // waiting the pair packet 1487 | continue; 1488 | } 1489 | 1490 | if ((enc_key_len > 0) || (lz4 > 0)) { 1491 | len = do_decrypt((u_int8_t *) buf, len, nbuf); 1492 | pbuf = nbuf; 1493 | } else 1494 | pbuf = buf; 1495 | if (len <= 0) 1496 | continue; 1497 | udp_recv_pkt[index]++; 1498 | udp_recv_byte[index] += len; 1499 | if (memcmp(pbuf, "PASSWORD:", 9) == 0) { // got password packet 1500 | if (debug) { 1501 | Debug("password packet from remote %s", pbuf); 1502 | if ((memcmp(pbuf + 9, mypassword, strlen(mypassword)) == 0) 1503 | && (*(pbuf + 9 + strlen(mypassword)) == 0)) 1504 | Debug("password ok"); 1505 | else 1506 | Debug("error\n"); 1507 | } 1508 | continue; 1509 | } 1510 | } 1511 | 1512 | if (memcmp(pbuf, "PING:PING:", 10) == 0) { 1513 | #ifdef DEBUGPINGPONG 1514 | Debug("ping from index %d udp", index); 1515 | #endif 1516 | ping_recv[index]++; 1517 | memcpy(buf, "PONG:PONG:", 10); 1518 | len = 10; 1519 | if ((enc_key_len > 0) || (lz4 > 0)) { 1520 | len = do_encrypt((u_int8_t *) buf, len, nbuf); 1521 | pbuf = nbuf; 1522 | } else 1523 | pbuf = buf; 1524 | send_udp_to_remote(pbuf, len, index); 1525 | pong_send[index]++; 1526 | continue; 1527 | } 1528 | 1529 | if (memcmp(pbuf, "PONG:PONG:", 10) == 0) { 1530 | #ifdef DEBUGPINGPONG 1531 | Debug("pong from index %d udp", index); 1532 | #endif 1533 | last_pong[index] = myticket; 1534 | pong_recv[index]++; 1535 | continue; 1536 | } 1537 | 1538 | if (read_only) 1539 | continue; // read only 1540 | if (!write_only && fixmss) // write only, no fix_mss 1541 | fix_mss(pbuf, len, index); 1542 | 1543 | if (debug) 1544 | printPacket((EtherPacket *) pbuf, len, "from remote udpsocket:"); 1545 | raw_send_pkt++; 1546 | raw_send_byte += len; 1547 | 1548 | if (vlan_map && len >= 16) { 1549 | struct vlan_tag *tag; 1550 | tag = (struct vlan_tag *)(pbuf + 12); 1551 | if (tag->vlan_tpid == ETHP8021Q) { 1552 | int vlan = ntohs(tag->vlan_tci) & 0xfff; 1553 | if (remote_vlan[vlan] != vlan) { 1554 | tag->vlan_tci = htons((ntohs(tag->vlan_tci) & 0xf000) + remote_vlan[vlan]); 1555 | if (debug) { 1556 | Debug("maping vlan %d back to %d", vlan, remote_vlan[vlan]); 1557 | printPacket((EtherPacket *) (pbuf), len, "from remote udpsocket:"); 1558 | } 1559 | } 1560 | } 1561 | } 1562 | 1563 | if (mode == MODEE) { 1564 | struct sockaddr_ll sll; 1565 | memset(&sll, 0, sizeof(sll)); 1566 | sll.sll_family = AF_PACKET; 1567 | sll.sll_protocol = htons(ETH_P_ALL); 1568 | sll.sll_ifindex = ifindex; 1569 | if (sendto(fdraw, pbuf, len, 0, (struct sockaddr *)&sll, sizeof(sll)) != len) 1570 | raw_send_err++; 1571 | } else if ((mode == MODEI) || (mode == MODEB)) 1572 | if (write(fdraw, pbuf, len) != len) 1573 | raw_send_err++; 1574 | } 1575 | } 1576 | 1577 | void process_udp_to_raw_master(void) 1578 | { 1579 | process_udp_to_raw(MASTER); 1580 | } 1581 | 1582 | void process_udp_to_raw_slave(void) 1583 | { 1584 | process_udp_to_raw(SLAVE); 1585 | } 1586 | 1587 | int open_tun(const char *dev, char **actual) 1588 | { 1589 | struct ifreq ifr; 1590 | int fd; 1591 | // char *device = "/dev/tun"; //uClinux tun 1592 | char *device = "/dev/net/tun"; //RedHat tun 1593 | int size; 1594 | 1595 | if ((fd = open(device, O_RDWR)) < 0) //???? 1596 | { 1597 | Debug("Cannot open TUN/TAP dev %s", device); 1598 | exit(1); 1599 | } 1600 | memset(&ifr, 0, sizeof(ifr)); 1601 | ifr.ifr_flags = IFF_NO_PI; 1602 | if (!strncmp(dev, "tun", 3)) { 1603 | ifr.ifr_flags |= IFF_TUN; 1604 | } else if (!strncmp(dev, "tap", 3)) { 1605 | ifr.ifr_flags |= IFF_TAP; 1606 | } else { 1607 | Debug("I don't recognize device %s as a TUN or TAP device", dev); 1608 | exit(1); 1609 | } 1610 | if (strlen(dev) > 3) //unit number specified? 1611 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); 1612 | if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) //? 1613 | { 1614 | Debug("Cannot ioctl TUNSETIFF %s", dev); 1615 | exit(1); 1616 | } 1617 | Debug("TUN/TAP device %s opened", ifr.ifr_name); 1618 | size = strlen(ifr.ifr_name) + 1; 1619 | *actual = (char *)malloc(size); 1620 | memcpy(*actual, ifr.ifr_name, size); 1621 | // the following maybe no use 1622 | int n = 10 * 1024 * 1024; 1623 | setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); 1624 | if (debug) { 1625 | socklen_t ln = sizeof(n); 1626 | if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &n, &ln) == 0) 1627 | Debug("RAW socket RCVBUF setting to %d", n); 1628 | } 1629 | return fd; 1630 | } 1631 | 1632 | void read_vlan_map_file(char *fname) 1633 | { 1634 | int vlan; 1635 | FILE *fp; 1636 | char buf[MAXLEN]; 1637 | for (vlan = 0; vlan < 4096; vlan++) 1638 | my_vlan[vlan] = remote_vlan[vlan] = vlan; 1639 | fp = fopen(fname, "r"); 1640 | if (fp == NULL) 1641 | return; 1642 | while (fgets(buf, MAXLEN, fp)) { 1643 | int myvlan, remotevlan; 1644 | char *p; 1645 | p = buf; 1646 | while (isblank(*p)) 1647 | p++; 1648 | if (!isdigit(*p)) 1649 | continue; 1650 | myvlan = atoi(p) & 0xfff; 1651 | while (isdigit(*p)) 1652 | p++; 1653 | while (isblank(*p)) 1654 | p++; 1655 | if (!isdigit(*p)) 1656 | continue; 1657 | remotevlan = atoi(p) & 0xfff; 1658 | my_vlan[myvlan] = remotevlan; 1659 | remote_vlan[remotevlan] = myvlan; 1660 | } 1661 | fclose(fp); 1662 | } 1663 | 1664 | void usage(void) 1665 | { 1666 | printf("EthUDP Version: %s, by james@ustc.edu.cn (https://github.com/bg6cq/ethudp)\n", VERSION); 1667 | printf("Usage:\n"); 1668 | printf("./EthUDP -e [ options ] localip localport remoteip remoteport eth? \\\n"); 1669 | printf(" [ localip localport remoteip remoteport ]\n"); 1670 | printf("./EthUDP -i [ options ] localip localport remoteip remoteport ipaddress masklen \\\n"); 1671 | printf(" [ localip localport remoteip remoteport ]\n"); 1672 | printf("./EthUDP -b [ options ] localip localport remoteip remoteport bridge \\\n"); 1673 | printf(" [ localip localport remoteip remoteport ]\n"); 1674 | printf("./EthUDP -t localip localport remoteip remoteport eth? [ pcap_filter_string ]\n"); 1675 | printf("./EthUDP -u localip localport remoteip remoteport eth? pcap_filter_string\n"); 1676 | printf(" options:\n"); 1677 | printf(" -p password\n"); 1678 | printf(" -enc [ xor|aes-128|aes-192|aes-256 ]\n"); 1679 | printf(" -k key_string\n"); 1680 | printf(" -lz4 [ 0-9 ] lz4 acceleration, default is 0(disable), 1 is best, 9 is fast\n"); 1681 | printf(" -mss mss change tcp SYN mss\n"); 1682 | printf(" -mtu mtu fragment udp to mtu - 28 bytes packets, 1036 - 1500\n"); 1683 | printf(" -map vlanmap.txt vlan maping\n"); 1684 | printf(" -dev dev_name rename tap interface to dev_name(mode i & b)\n"); 1685 | printf(" -n name name for syslog prefix\n"); 1686 | printf(" -c run_cmd run run_cmd after tunnel connected\n"); 1687 | printf(" -x run_seconds child process exit after run_seconds run\n"); 1688 | printf(" -d enable debug\n"); 1689 | printf(" -r read only of ethernet interface\n"); 1690 | printf(" -w write only of ethernet interface\n"); 1691 | printf(" -B benchmark\n"); 1692 | printf(" -l packet_len\n"); 1693 | printf(" -nopromisc do not set ethernet interface to promisc mode(mode e)\n"); 1694 | printf(" -noloopcheck do not check loopback(-r default do check)\n"); 1695 | printf(" -loopcheck do check loopback\n"); 1696 | printf(" HUP signal: print statistics\n"); 1697 | printf(" USR1 signal: reset statistics\n"); 1698 | exit(0); 1699 | } 1700 | 1701 | #define BENCHCNT 300000 1702 | 1703 | void do_benchmark(void) 1704 | { 1705 | #ifdef ENABLE_OPENSSL 1706 | u_int8_t buf[MAX_PACKET_SIZE]; 1707 | u_int8_t nbuf[MAX_PACKET_SIZE + EVP_MAX_BLOCK_LENGTH]; 1708 | unsigned long int pkt_cnt; 1709 | unsigned long int pkt_len = 0, pkt_len_send = 0; 1710 | int len; 1711 | struct timeval start_tm, end_tm; 1712 | gettimeofday(&start_tm, NULL); 1713 | fprintf(stderr, "benchmarking for %d packets, %d size...\n", BENCHCNT, packet_len); 1714 | fprintf(stderr, "enc_algorithm = %s\n", 1715 | enc_algorithm == XOR ? "xor" : enc_algorithm == AES_128 ? "aes-128" : enc_algorithm == AES_192 ? "aes-192" : enc_algorithm == 1716 | AES_256 ? "aes-256" : "none"); 1717 | fprintf(stderr, " enc_key = %s\n", enc_key); 1718 | fprintf(stderr, " key_len = %d\n", enc_key_len); 1719 | fprintf(stderr, " lz4 = %d\n", lz4); 1720 | pkt_cnt = BENCHCNT; 1721 | memset(buf, 'a', packet_len); 1722 | 1723 | while (1) { 1724 | len = packet_len; 1725 | pkt_len += len; 1726 | len = do_encrypt(buf, len, nbuf); 1727 | pkt_len_send += len; 1728 | pkt_cnt--; 1729 | if (pkt_cnt == 0) 1730 | break; 1731 | } 1732 | gettimeofday(&end_tm, NULL); 1733 | float tspan = ((end_tm.tv_sec - start_tm.tv_sec) * 1000000L + end_tm.tv_usec) - start_tm.tv_usec; 1734 | tspan = tspan / 1000000L; 1735 | fprintf(stderr, "%0.3f seconds\n", tspan); 1736 | fprintf(stderr, "PPS: %.0f PKT/S, %lu(%lu) Byte, %.0f(%.0f) Byte/S\n", (float)BENCHCNT / tspan, pkt_len, pkt_len_send, 1.0 * pkt_len / tspan, 1737 | 1.0 * pkt_len_send / tspan); 1738 | fprintf(stderr, "UDP BPS: %.0f(%.0f) BPS\n", 8.0 * pkt_len / tspan, 8.0 * pkt_len_send / tspan); 1739 | #endif 1740 | exit(0); 1741 | } 1742 | 1743 | int main(int argc, char *argv[]) 1744 | { 1745 | pthread_t tid; 1746 | int i = 1; 1747 | int got_one = 0; 1748 | ETHP8021Q = htons(0x8100); 1749 | do { 1750 | got_one = 1; 1751 | if (argc - i <= 0) 1752 | usage(); 1753 | if (strcmp(argv[i], "-e") == 0) 1754 | mode = MODEE; 1755 | else if (strcmp(argv[i], "-i") == 0) 1756 | mode = MODEI; 1757 | else if (strcmp(argv[i], "-b") == 0) 1758 | mode = MODEB; 1759 | else if (strcmp(argv[i], "-t") == 0) 1760 | mode = MODET; 1761 | else if (strcmp(argv[i], "-u") == 0) 1762 | mode = MODEU; 1763 | else if (strcmp(argv[i], "-d") == 0) 1764 | debug = 1; 1765 | else if (strcmp(argv[i], "-r") == 0) { 1766 | read_only = 1; 1767 | loopback_check = 1; 1768 | } else if (strcmp(argv[i], "-w") == 0) 1769 | write_only = 1; 1770 | else if (strcmp(argv[i], "-nopromisc") == 0) 1771 | nopromisc = 1; 1772 | else if (strcmp(argv[i], "-noloopcheck") == 0) 1773 | loopback_check = 0; 1774 | else if (strcmp(argv[i], "-loopcheck") == 0) 1775 | loopback_check = 1; 1776 | else if (strcmp(argv[i], "-B") == 0) 1777 | do_benchmark(); 1778 | else if (strcmp(argv[i], "-mss") == 0) { 1779 | i++; 1780 | if (argc - i <= 0) 1781 | usage(); 1782 | fixmss = atoi(argv[i]); 1783 | } else if (strcmp(argv[i], "-mtu") == 0) { 1784 | i++; 1785 | if (argc - i <= 0) 1786 | usage(); 1787 | mtu = atoi(argv[i]); 1788 | if ((mtu < 1036) || (mtu > 1500)) { 1789 | printf("invalid mtu %d\n", mtu); 1790 | usage(); 1791 | } 1792 | } else if (strcmp(argv[i], "-map") == 0) { 1793 | i++; 1794 | if (argc - i <= 0) 1795 | usage(); 1796 | vlan_map = 1; 1797 | read_vlan_map_file(argv[i]); 1798 | } else if (strcmp(argv[i], "-dev") == 0) { 1799 | i++; 1800 | if (argc - i <= 0) 1801 | usage(); 1802 | strncpy(dev_name, argv[i], IFNAMSIZ - 1); 1803 | } else if (strcmp(argv[i], "-n") == 0) { 1804 | i++; 1805 | if (argc - i <= 0) 1806 | usage(); 1807 | strncpy(name, argv[i], MAXLEN - 1); 1808 | } else if (strcmp(argv[i], "-lz4") == 0) { 1809 | i++; 1810 | if (argc - i <= 0) 1811 | usage(); 1812 | lz4 = atoi(argv[i]); 1813 | } else if (strcmp(argv[i], "-l") == 0) { 1814 | i++; 1815 | if (argc - i <= 0) 1816 | usage(); 1817 | packet_len = atoi(argv[i]); 1818 | } else if (strcmp(argv[i], "-p") == 0) { 1819 | i++; 1820 | if (argc - i <= 0) 1821 | usage(); 1822 | strncpy(mypassword, argv[i], MAXLEN - 1); 1823 | } else if (strcmp(argv[i], "-enc") == 0) { 1824 | i++; 1825 | if (argc - i <= 0) 1826 | usage(); 1827 | if (strcmp(argv[i], "xor") == 0) 1828 | enc_algorithm = XOR; 1829 | #ifdef ENABLE_OPENSSL 1830 | else if (strcmp(argv[i], "aes-128") == 0) 1831 | enc_algorithm = AES_128; 1832 | else if (strcmp(argv[i], "aes-192") == 0) 1833 | enc_algorithm = AES_192; 1834 | else if (strcmp(argv[i], "aes-256") == 0) 1835 | enc_algorithm = AES_256; 1836 | #endif 1837 | } else if (strcmp(argv[i], "-k") == 0) { 1838 | i++; 1839 | if (argc - i <= 0) 1840 | usage(); 1841 | memset(enc_key, 0, MAXLEN); 1842 | strncpy((char *)enc_key, argv[i], MAXLEN - 1); 1843 | enc_key_len = strlen((char *)enc_key); 1844 | } else if (strcmp(argv[i], "-x") == 0) { 1845 | i++; 1846 | if (argc - i <= 0) 1847 | usage(); 1848 | run_seconds = atoi(argv[i]); 1849 | } else if (strcmp(argv[i], "-c") == 0) { 1850 | i++; 1851 | if (argc - i <= 0) 1852 | usage(); 1853 | memset(run_cmd, 0, MAXLEN); 1854 | strncpy((char *)run_cmd, argv[i], MAXLEN - 1); 1855 | } else 1856 | got_one = 0; 1857 | if (got_one) 1858 | i++; 1859 | } 1860 | while (got_one); 1861 | if ((mode == MODEE) || (mode == MODEB)) { 1862 | if (argc - i == 9) 1863 | master_slave = 1; 1864 | else if (argc - i != 5) 1865 | usage(); 1866 | } 1867 | if (mode == MODEI) { 1868 | if (argc - i == 10) 1869 | master_slave = 1; 1870 | else if (argc - i != 6) 1871 | usage(); 1872 | } 1873 | if (mode == MODET) { 1874 | if (argc - i < 5) 1875 | usage(); 1876 | } 1877 | if (mode == MODET) { 1878 | if (argc - i < 5) 1879 | usage(); 1880 | } 1881 | // enc_algorithm set, but enc_key not set, set enc_key to 123456 1882 | if ((enc_algorithm != 0) && (enc_key_len == 0)) { 1883 | memset(enc_key, 0, MAXLEN); 1884 | strncpy((char *)enc_key, "123456", MAXLEN - 1); 1885 | enc_key_len = strlen((char *)enc_key); 1886 | } else if ((enc_algorithm == 0) && (enc_key_len != 0)) // enc_key set, but enc_algorithm not set, set enc_algorithm to AES-128 1887 | enc_algorithm = AES_128; 1888 | if (mode == -1) 1889 | usage(); 1890 | if (debug) { 1891 | printf(" debug = 1\n"); 1892 | printf(" mode = %d (0 raw eth bridge, 1 interface, 2 bridge, 3 tcpdump, 4 tcpdump udp)\n", mode); 1893 | printf(" password = %s\n", mypassword); 1894 | printf(" enc_algorithm = %s\n", enc_algorithm == XOR ? "xor" 1895 | #ifdef ENABLE_OPENSSL 1896 | : enc_algorithm == AES_128 ? "aes-128" : enc_algorithm == AES_192 ? "aes-192" : enc_algorithm == AES_256 ? "aes-256" 1897 | #endif 1898 | : "none"); 1899 | printf(" enc_key = %s\n", enc_key); 1900 | printf(" key_len = %d\n", enc_key_len); 1901 | printf(" master_slave = %d\n", master_slave); 1902 | printf(" mss = %d\n", fixmss); 1903 | printf(" mtu = %d\n", mtu); 1904 | printf(" read_only = %d\n", read_only); 1905 | printf("loopback_check = %d\n", loopback_check); 1906 | printf(" write_only = %d\n", write_only); 1907 | printf(" nopromisc = %d\n", nopromisc); 1908 | printf(" lz4 = %d\n", lz4); 1909 | printf(" dev_name = %s\n", dev_name); 1910 | printf(" run_cmd = %s\n", run_cmd); 1911 | printf(" run_seconds = %d\n", run_seconds); 1912 | printf(" cmd_line = "); 1913 | int n; 1914 | for (n = i; n < argc; n++) 1915 | printf("%s ", argv[n]); 1916 | printf("\n"); 1917 | if (vlan_map) { 1918 | int vlan; 1919 | printf("vlan mapping\n"); 1920 | for (vlan = 0; vlan < 4095; vlan++) 1921 | if (my_vlan[vlan] != vlan) 1922 | printf(" % 4d --> % 4d\n", vlan, my_vlan[vlan]); 1923 | } 1924 | printf("\n"); 1925 | } 1926 | 1927 | if (debug == 0) { 1928 | daemon_init("EthUDP", LOG_DAEMON); 1929 | while (1) { 1930 | int pid; 1931 | pid = fork(); 1932 | if (pid == 0) // child do the job 1933 | break; 1934 | else if (pid == -1) // error 1935 | exit(0); 1936 | else 1937 | wait(NULL); // parent wait for child 1938 | sleep(2); // wait 2 second, and rerun 1939 | } 1940 | } 1941 | 1942 | signal(SIGHUP, sig_handler_hup); 1943 | signal(SIGUSR1, sig_handler_usr1); 1944 | 1945 | if (mode == MODEE) { // eth bridge mode 1946 | fdudp[MASTER] = udp_xconnect(argv[i], argv[i + 1], argv[i + 2], argv[i + 3], MASTER); 1947 | if (master_slave) 1948 | fdudp[SLAVE] = udp_xconnect(argv[i + 5], argv[i + 6], argv[i + 7], argv[i + 8], SLAVE); 1949 | fdraw = open_rawsocket(argv[i + 4], &ifindex); 1950 | } else if (mode == MODEI) { // interface mode 1951 | char *actualname = NULL; 1952 | char buf[MAXLEN]; 1953 | fdudp[MASTER] = udp_xconnect(argv[i], argv[i + 1], argv[i + 2], argv[i + 3], MASTER); 1954 | if (master_slave) 1955 | fdudp[SLAVE] = udp_xconnect(argv[i + 6], argv[i + 7], argv[i + 8], argv[i + 9], SLAVE); 1956 | fdraw = open_tun("tap", &actualname); 1957 | if (dev_name[0]) 1958 | snprintf(buf, MAXLEN, "%s link set %s name %s; %s addr add %s/%s dev %s; %s link set %s up", 1959 | IPCMD, actualname, dev_name, IPCMD, argv[i + 4], argv[i + 5], dev_name, IPCMD, dev_name); 1960 | else 1961 | snprintf(buf, MAXLEN, "%s addr add %s/%s dev %s; %s link set %s up", IPCMD, argv[i + 4], argv[i + 5], actualname, IPCMD, actualname); 1962 | if (debug) 1963 | printf(" run cmd: %s\n", buf); 1964 | if (system(buf) != 0) 1965 | printf(" run cmd: %s returned not 0\n", buf); 1966 | if (debug) { 1967 | snprintf(buf, MAXLEN, "%s addr", IPCMD); 1968 | if (system(buf) != 0) 1969 | printf(" run cmd: %s returned not 0\n", buf); 1970 | } 1971 | } else if (mode == MODEB) { // bridge mode 1972 | char *actualname = NULL; 1973 | char buf[MAXLEN]; 1974 | fdudp[MASTER] = udp_xconnect(argv[i], argv[i + 1], argv[i + 2], argv[i + 3], MASTER); 1975 | if (master_slave) 1976 | fdudp[SLAVE] = udp_xconnect(argv[i + 5], argv[i + 6], argv[i + 7], argv[i + 8], SLAVE); 1977 | fdraw = open_tun("tap", &actualname); 1978 | if (dev_name[0]) 1979 | snprintf(buf, MAXLEN, "%s link set %s name %s; %s link set %s up; %s addif %s %s", 1980 | IPCMD, actualname, dev_name, IPCMD, dev_name, BRIDGECMD, argv[i + 4], dev_name); 1981 | else 1982 | snprintf(buf, MAXLEN, "%s link set %s up; %s addif %s %s", IPCMD, actualname, BRIDGECMD, argv[i + 4], actualname); 1983 | if (debug) 1984 | printf(" run cmd: %s\n", buf); 1985 | if (system(buf) != 0) 1986 | printf(" run cmd: %s returned not 0\n", buf); 1987 | if (debug) { 1988 | snprintf(buf, MAXLEN, "%s addr", IPCMD); 1989 | if (system(buf) != 0) 1990 | printf(" run cmd: %s returned not 0\n", buf); 1991 | snprintf(buf, MAXLEN, "%s show", BRIDGECMD); 1992 | if (system(buf) != 0) 1993 | printf(" run cmd: %s returned not 0\n", buf); 1994 | } 1995 | } else if ((mode == MODET) || (mode == MODEU)) { // tcpdump mode 1996 | char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ 1997 | read_only = 1; 1998 | fdudp[MASTER] = udp_xconnect(argv[i], argv[i + 1], argv[i + 2], argv[i + 3], MASTER); 1999 | pcap_handle = pcap_open_live(argv[i + 4], MAX_PACKET_SIZE, 0, 1000, errbuf); 2000 | if (argc - i == 6) { 2001 | struct bpf_program pgm; 2002 | if (pcap_compile(pcap_handle, &pgm, argv[i + 5], 1, PCAP_NETMASK_UNKNOWN) == -1) { 2003 | err_msg("pcap_filter compile error\n"); 2004 | exit(0); 2005 | } 2006 | if (pcap_setfilter(pcap_handle, &pgm) == -1) { 2007 | err_msg("pcap_setfilter error\n"); 2008 | exit(0); 2009 | } 2010 | } 2011 | } 2012 | if (run_cmd[0]) { // run command when tunnel connected 2013 | if (debug) 2014 | printf(" run user cmd: %s\n", run_cmd); 2015 | if (system(run_cmd) != 0) 2016 | printf(" run cmd: %s returned not 0\n", run_cmd); 2017 | } 2018 | // create a pthread to forward packets from master udp to raw 2019 | if (pthread_create(&tid, NULL, (void *)process_udp_to_raw_master, NULL) != 0) 2020 | err_sys("pthread_create udp_to_raw_master error"); 2021 | 2022 | // create a pthread to forward packets from slave udp to raw 2023 | if (master_slave) 2024 | if (pthread_create(&tid, NULL, (void *)process_udp_to_raw_slave, NULL) != 0) 2025 | err_sys("pthread_create udp_to_raw_slave error"); 2026 | 2027 | if ((mode != MODET) && (mode != MODEU)) 2028 | if (pthread_create(&tid, NULL, (void *)send_keepalive_to_udp, NULL) != 0) // send keepalive to remote 2029 | err_sys("pthread_create send_keepalive error"); 2030 | 2031 | // forward packets from raw to udp 2032 | process_raw_to_udp(); 2033 | 2034 | return 0; 2035 | } 2036 | --------------------------------------------------------------------------------