├── 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 | 
10 |
11 |
12 | 
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 | 
24 |
25 | ## 使用设备
26 |
27 | Linux机器,我们采购的是
28 | [N10Plus多网口千兆迷你小主机](https://detail.tmall.com/item.htm?id=542409856806)
29 |
30 | N10Plus有4个千兆接口,无风扇运行,外形如下:
31 |
32 | 
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 |
--------------------------------------------------------------------------------