Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8d065b09e | ||
|
|
2f2e64ae31 | ||
|
|
a4812dd596 | ||
|
|
2e420e921c | ||
|
|
99972f257a | ||
|
|
8e4ca75d36 | ||
|
|
360019d1a4 | ||
|
|
204c086a03 | ||
|
|
316834ffd0 | ||
|
|
aefbd2e062 | ||
|
|
ff6f60f079 | ||
|
|
b2a34fa18f | ||
|
|
984192c200 | ||
|
|
5747426565 | ||
|
|
0f78a61082 | ||
|
|
fa852f0b7d | ||
|
|
ff9ecd1b48 | ||
|
|
620c05b6bc | ||
|
|
5fffc80367 | ||
|
|
52ce3d69b4 | ||
|
|
259592e35c | ||
|
|
8866fc3a3a | ||
|
|
3dca97a235 | ||
|
|
9511680227 | ||
|
|
acb79bcf1f | ||
|
|
75adc0a669 | ||
|
|
2ef0200276 | ||
|
|
7940a4f949 | ||
|
|
81779637ba | ||
|
|
91d6129426 | ||
|
|
d333533639 | ||
|
|
2429f79721 | ||
|
|
044626152c | ||
|
|
0d7643ceb1 | ||
|
|
0e581ebf6f | ||
|
|
2fcfa6a001 | ||
|
|
546dfb74d3 | ||
|
|
a02a5a19c7 | ||
|
|
09b67f7dc6 | ||
|
|
731584cbd3 | ||
|
|
25a994213f | ||
|
|
c4a9f4c97e | ||
|
|
a56d0d4d58 | ||
|
|
9f01265981 | ||
|
|
1e96d85f88 | ||
|
|
a668a6deff | ||
|
|
9ae47ffaa4 | ||
|
|
8d1c6f69ca | ||
|
|
4bcc36489b | ||
|
|
e9e2bf759a | ||
|
|
c6e3af8ac8 | ||
|
|
5ab2ac455d | ||
|
|
ddc3aff29b | ||
|
|
8f75d7c40c | ||
|
|
3c02e4fbc4 | ||
|
|
5b2b3a63ab | ||
|
|
b96e3d9364 | ||
|
|
f9636ce89c | ||
|
|
c1b7585cd5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -37,6 +37,7 @@ CMakeFiles/
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
|
||||
# bin generated
|
||||
xfrpc
|
||||
|
||||
@@ -20,6 +20,9 @@ set(src_xfrpc
|
||||
session.c
|
||||
common.c
|
||||
login.c
|
||||
proxy_tcp.c
|
||||
proxy_ftp.c
|
||||
proxy.c
|
||||
)
|
||||
|
||||
set(libs
|
||||
|
||||
34
README.md
34
README.md
@@ -25,9 +25,10 @@
|
||||
|
||||
## What is xfrp and why start xfrp
|
||||
|
||||
xfrp was [xfrps](https://github.com/KunTengRom/xfrp) client implemented by c for OpenWRT system
|
||||
`xfrp` is [xfrps](https://github.com/KunTengRom/xfrp) client implemented by c for [OpenWRT](https://github.com/openwrt/openwrt) and [LEDE](https://github.com/lede-project/source) system
|
||||
|
||||
The motivation to start xfrp project is that we are OpenWRTer, and openwrt usually ran in device which has little ROM and RAM space, however golang always need more space and memory; therefore we start xfrp project.
|
||||
|
||||
The motivation to start xfrp project is that we are OpenWRTer, and openwrt usually ran in device which has little ROM and RAM space, however golang always need more space and memory; therefore we start xfrp project
|
||||
|
||||
## Compile
|
||||
|
||||
@@ -44,6 +45,7 @@ make
|
||||
|
||||
## Quick start
|
||||
|
||||
**before using xfrp, you should have built the proxy server: [xfrps](https://github.com/KunTengRom/xfrp), It's no difference with frp at usage, but support `FTP` and more embedded-client-friendly for linux.**
|
||||
|
||||
Run in debug mode :
|
||||
|
||||
@@ -57,6 +59,34 @@ Run in release mode :
|
||||
xfrpc -c frpc_mini.ini -d 0
|
||||
```
|
||||
|
||||
## FTP support
|
||||
|
||||
xfrp support ftp proxy after version [0.07.451](https://github.com/KunTengRom/xfrp/tree/0.07.451). **Hypothesize you have built [xfrps](https://github.com/KunTengRom/xfrp) succeed!**
|
||||
|
||||
Configure ftp in frpc.ini
|
||||
|
||||
```
|
||||
[common]
|
||||
server_addr = 111.112.113.114
|
||||
server_port = 7001
|
||||
|
||||
[router_ftp_example]
|
||||
type = ftp
|
||||
local_port = 21
|
||||
remote_port = 30621
|
||||
remote_data_port = 30622
|
||||
```
|
||||
|
||||
`remote_port` is the reporxy port of FTP command tunnel, and `remote_data_port` is FTP-DATA port reporxy.
|
||||
|
||||
Use `-p` (PASV Mode) of `ftp` command to connect to proxy ftp server:
|
||||
|
||||
```
|
||||
ftp -p 111.112.113.114 30621
|
||||
```
|
||||
|
||||
In [Master](https://github.com/KunTengRom/xfrp) version `server_addr` can use domain name intead of IP address in FTP proxy. [Issue #4](https://github.com/KunTengRom/xfrp/issues/4) and [Issue #5](https://github.com/KunTengRom/xfrp/issues/5).
|
||||
|
||||
----
|
||||
|
||||
## Todo list
|
||||
|
||||
93
client.c
93
client.c
@@ -52,8 +52,8 @@
|
||||
#include "const.h"
|
||||
#include "uthash.h"
|
||||
#include "zip.h"
|
||||
#include "msg.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
|
||||
#define MAX_OUTPUT (512*1024)
|
||||
|
||||
@@ -63,7 +63,8 @@ static void xfrp_event_cb(struct bufferevent *bev, short what, void *ctx);
|
||||
static void
|
||||
xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
@@ -74,13 +75,14 @@ xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
}
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
struct proxy *p_l = new_proxy_buf(bev);
|
||||
|
||||
if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
|
||||
/* We're giving the other side data faster than it can
|
||||
* pass it on. Stop reading here until we have drained the
|
||||
* other side to MAX_OUTPUT/2 bytes. */
|
||||
bufferevent_setcb(partner, xfrp_read_cb, drained_writecb,
|
||||
xfrp_event_cb, bev);
|
||||
xfrp_event_cb, p_l);
|
||||
bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
|
||||
MAX_OUTPUT);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
@@ -90,11 +92,12 @@ xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
static void
|
||||
drained_writecb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
|
||||
/* We were choking the other side until we drained our outbuf a bit.
|
||||
* Now it seems drained. */
|
||||
bufferevent_setcb(bev, xfrp_read_cb, NULL, xfrp_event_cb, partner);
|
||||
bufferevent_setcb(bev, xfrp_read_cb, NULL, xfrp_event_cb, p);
|
||||
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
|
||||
if (partner)
|
||||
bufferevent_enable(partner, EV_READ);
|
||||
@@ -113,13 +116,14 @@ close_on_finished_writecb(struct bufferevent *bev, void *ctx)
|
||||
static void
|
||||
xfrp_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
debug(LOG_DEBUG, "working connection closed");
|
||||
debug(LOG_DEBUG, "working connection closed!");
|
||||
if (partner) {
|
||||
/* Flush all pending data */
|
||||
xfrp_read_cb(bev, ctx);
|
||||
xfrp_read_cb(bev, p);
|
||||
|
||||
if (evbuffer_get_length(bufferevent_get_output(partner))) {
|
||||
/* We still have to flush data from the other
|
||||
@@ -134,42 +138,41 @@ xfrp_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
/* We have nothing left to say to the other
|
||||
* side; close it. */
|
||||
bufferevent_free(partner);
|
||||
free_proxy(p);
|
||||
}
|
||||
}
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xfrp_decrypt_cb(struct bufferevent *bev, void *ctx)
|
||||
int is_ftp_proxy(const struct proxy_service *ps)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
if (! ps || ! ps->proxy_type)
|
||||
return 0;
|
||||
|
||||
static void
|
||||
xfrp_encrypt_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len > 0) {
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
if (0 == strcmp(ps->proxy_type, "ftp") && ps->remote_data_port > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create frp tunnel for service
|
||||
void start_frp_tunnel(struct proxy_client *client)
|
||||
void start_xfrp_tunnel(struct proxy_client *client)
|
||||
{
|
||||
if (! client->ctl_bev) {
|
||||
debug(LOG_ERR, "proxy client control bev is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
struct event_base *base = client->base;
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct proxy_service *ps = client->ps;
|
||||
|
||||
if (! base) {
|
||||
debug(LOG_ERR, "service event base get failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (! ps) {
|
||||
debug(LOG_ERR, "service tunnel started failed, no proxy service resource.");
|
||||
return;
|
||||
@@ -189,21 +192,34 @@ void start_frp_tunnel(struct proxy_client *client)
|
||||
|
||||
debug(LOG_DEBUG, "proxy server [%s:%d] <---> client [%s:%d]",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port,
|
||||
ps->remote_port,
|
||||
ps->local_ip ? ps->local_ip:"::1",
|
||||
ps->local_port);
|
||||
|
||||
struct proxy *ctl_prox = new_proxy_buf(client->ctl_bev);
|
||||
struct proxy *local_prox = new_proxy_buf(client->local_proxy_bev);
|
||||
bufferevent_data_cb proxy_s2c_cb, proxy_c2s_cb;
|
||||
if (is_ftp_proxy(client->ps)) {
|
||||
proxy_c2s_cb = ftp_proxy_c2s_cb;
|
||||
proxy_s2c_cb = ftp_proxy_s2c_cb;
|
||||
ctl_prox->remote_data_port = client->ps->remote_data_port;
|
||||
ctl_prox->proxy_name = strdup(ps->proxy_name);
|
||||
} else {
|
||||
proxy_c2s_cb = tcp_proxy_c2s_cb;
|
||||
proxy_s2c_cb = tcp_proxy_s2c_cb;
|
||||
}
|
||||
|
||||
bufferevent_setcb(client->ctl_bev,
|
||||
xfrp_decrypt_cb,
|
||||
proxy_s2c_cb,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
client->local_proxy_bev);
|
||||
local_prox);
|
||||
|
||||
bufferevent_setcb(client->local_proxy_bev,
|
||||
xfrp_encrypt_cb,
|
||||
proxy_c2s_cb,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
client->ctl_bev);
|
||||
ctl_prox);
|
||||
|
||||
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
|
||||
bufferevent_enable(client->local_proxy_bev, EV_READ|EV_WRITE);
|
||||
@@ -221,9 +237,7 @@ int send_client_data_tail(struct proxy_client *client)
|
||||
|
||||
void free_proxy_client(struct proxy_client *client)
|
||||
{
|
||||
if (client->name) free(client->name);
|
||||
if (client->local_ip) free(client->local_ip);
|
||||
if (client->locations) free(client->locations);
|
||||
|
||||
free_base_config(client->bconf);
|
||||
|
||||
@@ -250,4 +264,11 @@ struct proxy_service *get_proxy_service(const char *proxy_name)
|
||||
struct proxy_service *all_ps = get_all_proxy_services();
|
||||
HASH_FIND_STR(all_ps, proxy_name, ps);
|
||||
return ps;
|
||||
}
|
||||
|
||||
struct proxy_client *new_proxy_client()
|
||||
{
|
||||
struct proxy_client *client = calloc(1, sizeof(struct proxy_client));
|
||||
assert(client);
|
||||
return client;
|
||||
}
|
||||
9
client.h
9
client.h
@@ -45,14 +45,10 @@ struct proxy_client {
|
||||
struct event *ev_timeout;
|
||||
|
||||
struct base_conf *bconf;
|
||||
char *name; // pointer to bconf->name
|
||||
char *local_ip;
|
||||
char *type;
|
||||
int local_port;
|
||||
int remote_port;
|
||||
|
||||
char *subdomain;
|
||||
char *locations;
|
||||
char *host_header_rewrite;
|
||||
|
||||
//provate arguments
|
||||
@@ -92,7 +88,7 @@ struct proxy_service {
|
||||
// when xfrp client receive that request, it will start
|
||||
// frp tunnel
|
||||
// if client has data-tail(not NULL), client value will be changed
|
||||
void start_frp_tunnel(struct proxy_client *client);
|
||||
void start_xfrp_tunnel(struct proxy_client *client);
|
||||
|
||||
void del_proxy_client(struct proxy_client *client);
|
||||
|
||||
@@ -102,4 +98,7 @@ struct proxy_service *get_proxy_service(const char *proxy_name);
|
||||
|
||||
int send_client_data_tail(struct proxy_client *client);
|
||||
|
||||
int is_ftp_proxy(const struct proxy_service *ps);
|
||||
struct proxy_client *new_proxy_client();
|
||||
|
||||
#endif //_CLIENT_H_
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "commandline.h"
|
||||
#include "debug.h"
|
||||
#include "version.h"
|
||||
#include "utils.h"
|
||||
|
||||
typedef void signal_func (int);
|
||||
|
||||
@@ -122,6 +123,7 @@ usage(const char *appname)
|
||||
fprintf(stdout, " -d <level> Debug level\n");
|
||||
fprintf(stdout, " -h Print usage\n");
|
||||
fprintf(stdout, " -v Print version information\n");
|
||||
fprintf(stdout, " -r Print run id of client\n");
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
@@ -134,7 +136,7 @@ parse_commandline(int argc, char **argv)
|
||||
int c;
|
||||
int flag = 0;
|
||||
|
||||
while (-1 != (c = getopt(argc, argv, "c:hfd:sw:vx:i:a:"))) {
|
||||
while (-1 != (c = getopt(argc, argv, "c:hfd:sw:vrx:i:a:"))) {
|
||||
|
||||
|
||||
switch (c) {
|
||||
@@ -165,10 +167,28 @@ parse_commandline(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
fprintf(stdout, "This is %s version " VERSION "\n", argv[0]);
|
||||
fprintf(stdout, "version: " VERSION "\n");
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
{
|
||||
char ifname[16] = {0};
|
||||
if(get_net_ifname(ifname, 16)){
|
||||
debug(LOG_ERR, "error: get device sign ifname failed!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char if_mac[64] = {0};
|
||||
if(get_net_mac(ifname, if_mac, sizeof(if_mac))) {
|
||||
debug(LOG_ERR, "error: Hard ware MAC address of [%s] get failed!", ifname);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fprintf(stdout, "run ID:%s\n", if_mac);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
|
||||
80
config.c
80
config.c
@@ -38,12 +38,14 @@
|
||||
#include "client.h"
|
||||
#include "debug.h"
|
||||
#include "msg.h"
|
||||
#include "utils.h"
|
||||
#include "version.h"
|
||||
|
||||
static struct common_conf *c_conf;
|
||||
static struct proxy_client *p_clients;
|
||||
static struct proxy_service *p_services;
|
||||
|
||||
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps);
|
||||
|
||||
struct common_conf *get_common_config()
|
||||
{
|
||||
@@ -61,8 +63,18 @@ void free_common_config()
|
||||
if (c_conf->log_level) free(c_conf->log_level);
|
||||
if (c_conf->auth_token) free(c_conf->auth_token);
|
||||
if (c_conf->privilege_token) free(c_conf->privilege_token);
|
||||
SAFE_FREE(c_conf->server_ip);
|
||||
};
|
||||
|
||||
void set_common_server_ip(const char *ip)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
c_conf->server_ip = strdup(ip);
|
||||
assert(c_conf->server_ip);
|
||||
|
||||
debug(LOG_DEBUG, "server IP address: [%s]", c_conf->server_ip);
|
||||
}
|
||||
|
||||
void free_base_config(struct base_conf *bconf)
|
||||
{
|
||||
if (bconf->name) free(bconf->name);
|
||||
@@ -110,7 +122,7 @@ static const char *get_valid_type(const char *val)
|
||||
|
||||
static void dump_common_conf()
|
||||
{
|
||||
if(!c_conf) {
|
||||
if(! c_conf) {
|
||||
debug(LOG_ERR, "Error: c_conf is NULL");
|
||||
return;
|
||||
}
|
||||
@@ -135,8 +147,12 @@ static void dump_proxy_service(const int index, struct proxy_service *ps)
|
||||
} else if (strcmp(ps->proxy_type, "ftp") == 0) {
|
||||
if (ps->remote_data_port <= 0) {
|
||||
debug(LOG_ERR,
|
||||
"Proxy [%s] error: remote_data_port must be exist when type is ftp");
|
||||
"Proxy [%s] error: remote_data_port must be exist when type is ftp",
|
||||
ps->proxy_name);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
new_ftp_data_proxy_service(ps);
|
||||
}
|
||||
|
||||
debug(LOG_DEBUG,
|
||||
@@ -187,6 +203,32 @@ static struct proxy_service *new_proxy_service(const char *name)
|
||||
return ps;
|
||||
}
|
||||
|
||||
// create a new proxy service with suffix "_ftp_data_proxy"
|
||||
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name((const char *)ftp_ps->proxy_name);
|
||||
|
||||
HASH_FIND_STR(p_services, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
ps = new_proxy_service(ftp_data_proxy_name);
|
||||
if (! ps) {
|
||||
debug(LOG_ERR,
|
||||
"cannot create ftp data proxy service, it should not happenned!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ps->proxy_type = strdup("tcp");
|
||||
ps->remote_port = ftp_ps->remote_data_port;
|
||||
ps->local_ip = ftp_ps->local_ip;
|
||||
ps->local_port = 0; //will be init in working tunnel connectting
|
||||
|
||||
HASH_ADD_KEYPTR(hh, p_services, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
}
|
||||
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
static int
|
||||
proxy_service_handler(void *user, const char *sect, const char *nm, const char *value)
|
||||
{
|
||||
@@ -232,6 +274,8 @@ proxy_service_handler(void *user, const char *sect, const char *nm, const char *
|
||||
ps->use_encryption = is_true(value);
|
||||
} else if (MATCH_NAME("remote_port")) {
|
||||
ps->remote_port = atoi(value);
|
||||
} else if (MATCH_NAME("remote_data_port")) {
|
||||
ps->remote_data_port = atoi(value);
|
||||
} else if (MATCH_NAME("http_user")) {
|
||||
ps->http_user = strdup(value);
|
||||
assert(ps->http_user);
|
||||
@@ -267,8 +311,13 @@ static int common_handler(void *user, const char *section, const char *name, con
|
||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||
if (MATCH("common", "server_addr")) {
|
||||
SAFE_FREE(config->server_addr);
|
||||
config->server_addr = strdup(value);
|
||||
int addr_len = strlen(value) + 1;
|
||||
config->server_addr = (char *)calloc(1, addr_len);
|
||||
assert(config->server_addr);
|
||||
if(dns_unified(value, config->server_addr, addr_len)) {
|
||||
debug(LOG_ERR, "error: server_addr [%s] is invalid!", value);
|
||||
exit(0);
|
||||
}
|
||||
} else if (MATCH("common", "server_port")) {
|
||||
config->server_port = atoi(value);
|
||||
} else if (MATCH("common", "http_proxy")) {
|
||||
@@ -330,6 +379,26 @@ static void init_common_conf(struct common_conf *config)
|
||||
config->heartbeat_timeout = 60;
|
||||
config->tcp_mux = 0;
|
||||
config->user = NULL;
|
||||
config->server_ip = NULL;
|
||||
config->is_router = 0;
|
||||
}
|
||||
|
||||
// it should be free after using
|
||||
// because of assert it will never return NULL
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name)
|
||||
{
|
||||
char *ftp_tail_data_name = FTP_DATA_PROXY_SUFFIX;
|
||||
char *ftp_data_proxy_name = (char *)calloc(1,
|
||||
strlen(ftp_proxy_name)+strlen(ftp_tail_data_name)+1);
|
||||
assert(ftp_data_proxy_name);
|
||||
|
||||
snprintf(ftp_data_proxy_name,
|
||||
strlen(ftp_proxy_name) + strlen(ftp_tail_data_name) + 1,
|
||||
"%s%s",
|
||||
ftp_proxy_name,
|
||||
ftp_tail_data_name);
|
||||
|
||||
return ftp_data_proxy_name;
|
||||
}
|
||||
|
||||
void load_config(const char *confile)
|
||||
@@ -362,3 +431,8 @@ void load_config(const char *confile)
|
||||
|
||||
dump_all_ps();
|
||||
}
|
||||
|
||||
int is_running_in_router()
|
||||
{
|
||||
return c_conf->is_router;
|
||||
}
|
||||
|
||||
21
config.h
21
config.h
@@ -29,6 +29,8 @@
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
|
||||
#define FTP_DATA_PROXY_SUFFIX "_ftp_data_proxy"
|
||||
|
||||
struct base_conf{
|
||||
char *name;
|
||||
char *auth_token;
|
||||
@@ -43,19 +45,23 @@ struct base_conf{
|
||||
|
||||
// common config
|
||||
struct common_conf {
|
||||
char *server_addr; /* default 0.0.0.0 */
|
||||
int server_port; /* default 7000 */
|
||||
char *server_addr; /* default 0.0.0.0 */
|
||||
char *server_ip;
|
||||
int server_port; /* default 7000 */
|
||||
char *http_proxy;
|
||||
char *log_file; /* default consol */
|
||||
char *log_way; /* default console */
|
||||
char *log_level; /* default info */
|
||||
char *log_file; /* default consol */
|
||||
char *log_way; /* default console */
|
||||
char *log_level; /* default info */
|
||||
int log_max_days; /* default 3 */
|
||||
char *privilege_token;
|
||||
char *auth_token;
|
||||
int heartbeat_interval; /* default 10 */
|
||||
int heartbeat_timeout; /* default 30 */
|
||||
int tcp_mux; /* default 0 */
|
||||
int tcp_mux; /* default 0 */
|
||||
char *user;
|
||||
|
||||
/* private fields */
|
||||
int is_router; // to sign router (Openwrt/LEDE) or not
|
||||
};
|
||||
|
||||
struct common_conf *get_common_config();
|
||||
@@ -68,5 +74,8 @@ void free_base_config(struct base_conf *bconf);
|
||||
struct proxy_client *get_all_pc();
|
||||
|
||||
void load_config(const char *confile);
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name);
|
||||
void set_common_server_ip(const char *ip);
|
||||
int is_running_in_router();
|
||||
|
||||
#endif //_CONFIG_H_
|
||||
|
||||
260
control.c
260
control.c
@@ -29,10 +29,9 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <syslog.h>
|
||||
|
||||
@@ -60,7 +59,6 @@
|
||||
#include "login.h"
|
||||
|
||||
static struct control *main_ctl;
|
||||
static char *request_buf;
|
||||
static int clients_conn_signel = 0;
|
||||
|
||||
static void sync_new_work_connection(struct bufferevent *bev);
|
||||
@@ -71,13 +69,6 @@ static int is_client_connected()
|
||||
return clients_conn_signel;
|
||||
}
|
||||
|
||||
static void init_request_buffer()
|
||||
{
|
||||
size_t len = (1<<16) + get_header_size();
|
||||
request_buf = calloc(1, len);
|
||||
assert(request_buf);
|
||||
}
|
||||
|
||||
static int client_connected(int is_connected)
|
||||
{
|
||||
if (is_connected)
|
||||
@@ -90,16 +81,17 @@ static int client_connected(int is_connected)
|
||||
|
||||
static int set_client_work_start(struct proxy_client *client, int is_start_work)
|
||||
{
|
||||
if (is_start_work)
|
||||
if (is_start_work) {
|
||||
assert(client->ps);
|
||||
client->work_started = 1;
|
||||
else
|
||||
}else
|
||||
client->work_started = 0;
|
||||
|
||||
return client->work_started;
|
||||
}
|
||||
|
||||
static int is_client_work_started(struct proxy_client *client) {
|
||||
return client->work_started;
|
||||
return client->work_started && client->ps;
|
||||
}
|
||||
|
||||
static void client_start_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
@@ -121,14 +113,13 @@ static void client_start_event_cb(struct bufferevent *bev, short what, void *ctx
|
||||
bufferevent_setcb(bev, recv_cb, NULL, client_start_event_cb, client);
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||
sync_new_work_connection(bev);
|
||||
debug(LOG_INFO, "proxy service connected");
|
||||
debug(LOG_INFO, "proxy service start");
|
||||
}
|
||||
}
|
||||
|
||||
static void new_client_connect()
|
||||
{
|
||||
struct proxy_client *client = calloc(1, sizeof(struct proxy_client)); //NEED FREE
|
||||
assert(client);
|
||||
struct proxy_client *client = new_proxy_client();
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
assert(c_conf);
|
||||
client->base = main_ctl->connect_base;;
|
||||
@@ -195,43 +186,21 @@ static size_t request(struct bufferevent *bev, struct frame *f)
|
||||
bout = main_ctl->connect_bev;
|
||||
}
|
||||
|
||||
if ( ! bout) {
|
||||
goto REQ_END;
|
||||
}
|
||||
if ( ! bout)
|
||||
return 0;
|
||||
|
||||
struct common_conf *c = get_common_config();
|
||||
if ( ! c)
|
||||
goto REQ_END;
|
||||
return 0;
|
||||
|
||||
write_len = (size_t)f->len;
|
||||
if ( 0 == write_len)
|
||||
goto REQ_END;;
|
||||
return 0;
|
||||
|
||||
bufferevent_write(bout, f->data, write_len);
|
||||
|
||||
REQ_END:
|
||||
return write_len;
|
||||
}
|
||||
|
||||
void control_request_free(struct control_request *req)
|
||||
{
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
if (req->proxy_name) free(req->proxy_name);
|
||||
if (req->auth_key) free(req->auth_key);
|
||||
if (req->privilege_key) free(req->privilege_key);
|
||||
if (req->proxy_type) free(req->proxy_type);
|
||||
if (req->custom_domains) free(req->custom_domains);
|
||||
if (req->locations) free(req->locations);
|
||||
if (req->host_header_rewrite) free(req->host_header_rewrite);
|
||||
if (req->http_username) free(req->http_username);
|
||||
if (req->http_password) free(req->http_password);
|
||||
if (req->subdomain) free(req->subdomain);
|
||||
|
||||
free(req);
|
||||
}
|
||||
|
||||
static void base_control_ping(struct bufferevent *bev) {
|
||||
if ( ! is_client_connected())
|
||||
return;
|
||||
@@ -274,6 +243,7 @@ static void ping(struct bufferevent *bev)
|
||||
struct frame *f = new_frame(cmdNOP, 0); //ping sid is 0
|
||||
assert(f);
|
||||
request(bout, f);
|
||||
free_frame(f);
|
||||
}
|
||||
|
||||
uint32_t sid = get_main_control()->session_id;
|
||||
@@ -347,11 +317,12 @@ static void sync_new_work_connection(struct bufferevent *bev)
|
||||
SAFE_FREE(work_c);
|
||||
}
|
||||
|
||||
struct bufferevent *connect_server(struct event_base *base, const char *name, const int port)
|
||||
struct bufferevent *
|
||||
connect_server(struct event_base *base, const char *name, const int port)
|
||||
{
|
||||
struct bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
|
||||
assert(bev);
|
||||
|
||||
|
||||
if (bufferevent_socket_connect_hostname(bev,
|
||||
main_ctl->dnsbase,
|
||||
AF_INET,
|
||||
@@ -388,7 +359,7 @@ raw_message(struct message *msg, struct bufferevent *bev, struct proxy_client *c
|
||||
{
|
||||
if (client) {
|
||||
if (client->work_started) {
|
||||
debug(LOG_DEBUG, "raw client [%s] control message.", client->name);
|
||||
debug(LOG_DEBUG, "raw client [%s] control message.", client->ps->proxy_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,14 +425,13 @@ raw_message(struct message *msg, struct bufferevent *bev, struct proxy_client *c
|
||||
}
|
||||
|
||||
client->ps = ps;
|
||||
client->name = ps->proxy_name;
|
||||
debug(LOG_INFO,
|
||||
"proxy service [%s] [%s:%d] start work connection.",
|
||||
sr->proxy_name,
|
||||
ps->local_ip,
|
||||
ps->local_port);
|
||||
|
||||
start_frp_tunnel(client);
|
||||
start_xfrp_tunnel(client);
|
||||
set_client_work_start(client, 1);
|
||||
break;
|
||||
case TypePong:
|
||||
@@ -477,7 +447,8 @@ static size_t data_handler(unsigned char *buf, ushort len, struct proxy_client *
|
||||
{
|
||||
struct bufferevent *bev = NULL;
|
||||
if (client) {
|
||||
debug(LOG_DEBUG, "client [name:%s] recved control data", client->name);
|
||||
debug(LOG_DEBUG, "client(%s): recved control data",
|
||||
is_client_work_started(client)?"work":"free");
|
||||
bev = client->ctl_bev;
|
||||
}
|
||||
unsigned char *ret_buf = NULL;
|
||||
@@ -635,7 +606,7 @@ static unsigned char
|
||||
if (is_client_work_started(client)) {
|
||||
debug(LOG_DEBUG,
|
||||
"client [%s] send all work data to proxy tunnel.",
|
||||
client->name);
|
||||
client->ps->proxy_name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -739,7 +710,7 @@ static void recv_cb(struct bufferevent *bev, void *ctx)
|
||||
for(i = 0; i<read_n && ((2 * i) < (read_n * 2 + 1)); i++) {
|
||||
snprintf(dbg_buf + 4*i, 5, "%3u ", (unsigned char)raw_buf_p[i]);
|
||||
}
|
||||
debug(LOG_DEBUG, "[%s]: RECV ctl byte:%s", client ? "client":"control", dbg_buf);
|
||||
debug(LOG_DEBUG, "[%s]: RECV ctl byte:%s", client?"client":"control", dbg_buf);
|
||||
SAFE_FREE(dbg_buf);
|
||||
#endif //CONN_DEBUG
|
||||
|
||||
@@ -775,14 +746,26 @@ static void open_connection_session(struct bufferevent *bev)
|
||||
{
|
||||
struct frame *f = new_frame(cmdSYN, main_ctl->session_id);
|
||||
assert(f);
|
||||
|
||||
request(bev, f);
|
||||
free_frame(f);
|
||||
}
|
||||
|
||||
static void connect_event_cb (struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
static int retry_times = 0;
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
debug(LOG_ERR, "connect server [%s:%d] failed",
|
||||
if (retry_times >= 10) { // only try 10 times consecutively
|
||||
debug(LOG_ERR,
|
||||
"have retry connect to xfrp server for %d times, exit!",
|
||||
retry_times);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
retry_times++;
|
||||
debug(LOG_ERR, "error: connect server [%s:%d] failed",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
free_control();
|
||||
@@ -790,11 +773,15 @@ static void connect_event_cb (struct bufferevent *bev, short what, void *ctx)
|
||||
start_base_connect();
|
||||
close_main_control();
|
||||
} else if (what & BEV_EVENT_CONNECTED) {
|
||||
retry_times = 0;
|
||||
|
||||
// recv login-response message before recving othfer fprs messages,
|
||||
bufferevent_setcb(bev, recv_cb, NULL, connect_event_cb, NULL);
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);
|
||||
|
||||
open_connection_session(bev);
|
||||
if (get_common_config()->tcp_mux)
|
||||
open_connection_session(bev);
|
||||
|
||||
login();
|
||||
}
|
||||
}
|
||||
@@ -811,16 +798,42 @@ static void keep_control_alive()
|
||||
set_ticker_ping_timer(main_ctl->ticker_ping);
|
||||
}
|
||||
|
||||
static void server_dns_cb(int event_code, struct evutil_addrinfo *addr, void *ctx)
|
||||
{
|
||||
if (event_code) {
|
||||
set_common_server_ip((const char *)evutil_gai_strerror(event_code));
|
||||
} else {
|
||||
struct evutil_addrinfo *ai;
|
||||
if (addr->ai_canonname)
|
||||
debug(LOG_DEBUG, "addr->ai_canonname [%s]", addr->ai_canonname);
|
||||
for (ai = addr; ai; ai = ai->ai_next) {
|
||||
char buf[128];
|
||||
const char *s = NULL;
|
||||
if (ai->ai_family == AF_INET) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
|
||||
s = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, 128);
|
||||
} else if (ai->ai_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
|
||||
s = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 128);
|
||||
}
|
||||
|
||||
if (s) set_common_server_ip(s);
|
||||
}
|
||||
if (addr) evutil_freeaddrinfo(addr);
|
||||
}
|
||||
}
|
||||
|
||||
void start_base_connect()
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
assert(c_conf);
|
||||
|
||||
main_ctl->connect_bev = connect_server(main_ctl->connect_base,
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
if ( ! main_ctl->connect_bev) {
|
||||
debug(LOG_ERR, "Connect server [%s:%d] failed", c_conf->server_addr, c_conf->server_port);
|
||||
debug(LOG_ERR,
|
||||
"error: connect server [%s:%d] failed",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -833,6 +846,7 @@ void sync_iv(unsigned char *iv)
|
||||
{
|
||||
struct frame *f = new_frame(cmdPSH, main_ctl->session_id);
|
||||
assert(f);
|
||||
|
||||
f->len = (ushort) get_encrypt_block_size();
|
||||
f->data = calloc(f->len, 1);
|
||||
memcpy(f->data, iv, f->len);
|
||||
@@ -852,14 +866,15 @@ void login()
|
||||
char *lg_msg = NULL;
|
||||
int len = login_request_marshal(&lg_msg); //marshal login request
|
||||
if ( ! lg_msg || ! len) {
|
||||
debug(LOG_ERR, "login_request_marshal failed");
|
||||
assert(lg_msg);
|
||||
debug(LOG_ERR,
|
||||
"error: login_request_marshal failed, it should never be happenned");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (get_common_config()->tcp_mux) {
|
||||
// using sid = 3 is only for matching fprs, it will change after using tcp-mux
|
||||
// using sid = 3 is only for matching fprs, it will change after using tcp-mux
|
||||
if (get_common_config()->tcp_mux)
|
||||
sync_session_id(3);
|
||||
}
|
||||
|
||||
send_msg_frp_server(NULL, TypeLogin, lg_msg, len, main_ctl->session_id);
|
||||
SAFE_FREE(lg_msg);
|
||||
}
|
||||
@@ -886,10 +901,8 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
} else {
|
||||
bout = main_ctl->connect_bev;
|
||||
}
|
||||
assert(bout);
|
||||
|
||||
if ( ! bout) {
|
||||
return;
|
||||
}
|
||||
debug(LOG_DEBUG, "send ----> [%c: %s]", type, msg);
|
||||
|
||||
struct message req_msg;
|
||||
@@ -899,7 +912,9 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
|
||||
char frame_type = 0;
|
||||
struct frame *f = NULL;
|
||||
f = new_frame(frame_type, sid); // frame_type not truely matter, it will reset by set_frame_cmd
|
||||
|
||||
// frame_type not truely matter, it will reset by set_frame_cmd
|
||||
f = new_frame(frame_type, sid);
|
||||
assert(f);
|
||||
|
||||
if (msg) {
|
||||
@@ -907,37 +922,15 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
assert(req_msg.data_p);
|
||||
}
|
||||
|
||||
unsigned char *puck_buf = NULL;
|
||||
size_t pack_buf_len = pack(&req_msg, &puck_buf);
|
||||
if ( ! pack_buf_len || ! puck_buf) {
|
||||
debug(LOG_ERR, "send buffer pack failed!");
|
||||
unsigned char *pack_buf = NULL;
|
||||
size_t pack_buf_len = pack(&req_msg, &pack_buf);
|
||||
if ( ! pack_buf_len || ! pack_buf) {
|
||||
debug(LOG_ERR, "error: send buffer pack failed!");
|
||||
goto S_M_F_END;
|
||||
}
|
||||
|
||||
#ifdef ENCRYPTO
|
||||
debug(LOG_DEBUG, "start encode message ...");
|
||||
unsigned char *encode_ret;
|
||||
unsigned char *encode_ret_test;
|
||||
unsigned char *decode_ret_test;
|
||||
struct frp_coder *encoder = get_main_encoder();
|
||||
|
||||
if (encoder) {
|
||||
size_t encode_ret_len = encrypt_data(puck_buf, pack_buf_len, encoder, &encode_ret);
|
||||
debug(LOG_DEBUG, "encode len:[%lu]", encode_ret_len);
|
||||
|
||||
if (encode_ret_len > 0) {
|
||||
f->data = encode_ret;
|
||||
set_frame_len(f, (ushort) encode_ret_len);
|
||||
}
|
||||
|
||||
set_frame_len(f, (ushort) pack_buf_len);
|
||||
}
|
||||
|
||||
#endif //ENCRYPTO
|
||||
if (! f->data) {
|
||||
set_frame_len(f, (ushort) pack_buf_len);
|
||||
f->data = puck_buf;
|
||||
}
|
||||
set_frame_len(f, (ushort) pack_buf_len);
|
||||
f->data = pack_buf;
|
||||
|
||||
if (get_common_config()->tcp_mux) {
|
||||
switch (type)
|
||||
@@ -961,7 +954,8 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
|
||||
S_M_F_END:
|
||||
SAFE_FREE(req_msg.data_p);
|
||||
SAFE_FREE(f->data);
|
||||
SAFE_FREE(pack_buf);
|
||||
f->data = NULL;
|
||||
free_frame(f);
|
||||
}
|
||||
|
||||
@@ -973,13 +967,18 @@ struct control *get_main_control()
|
||||
void start_login_frp_server(struct event_base *base)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct bufferevent *bev = connect_server(base, c_conf->server_addr, c_conf->server_port);
|
||||
struct bufferevent *bev = connect_server(base,
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
if (!bev) {
|
||||
debug(LOG_DEBUG, "Connect server [%s:%d] failed", c_conf->server_addr, c_conf->server_port);
|
||||
debug(LOG_DEBUG,
|
||||
"Connect server [%s:%d] failed",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
return;
|
||||
}
|
||||
|
||||
debug(LOG_INFO, "Xfrpc login: connect server [%s:%d] ......", c_conf->server_addr, c_conf->server_port);
|
||||
debug(LOG_INFO, "Xfrpc login: connect server [%s:%d] ...", c_conf->server_addr, c_conf->server_port);
|
||||
|
||||
bufferevent_enable(bev, EV_WRITE|EV_READ);
|
||||
bufferevent_setcb(bev, NULL, NULL, connect_event_cb, NULL);
|
||||
@@ -1006,20 +1005,38 @@ void send_new_proxy(struct proxy_service *ps)
|
||||
|
||||
void init_main_control()
|
||||
{
|
||||
if (main_ctl && main_ctl->connect_base)
|
||||
if (main_ctl && main_ctl->connect_base) {
|
||||
event_base_loopbreak(main_ctl->connect_base);
|
||||
free(main_ctl);
|
||||
}
|
||||
|
||||
main_ctl = calloc(sizeof(struct control), 1);
|
||||
assert(main_ctl);
|
||||
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
if (c_conf->tcp_mux) {
|
||||
uint32_t *sid = init_sid_index();
|
||||
assert(sid);
|
||||
main_ctl->session_id = *sid;
|
||||
|
||||
debug(LOG_DEBUG, "Connect Frps with control session ID: %d", main_ctl->session_id);
|
||||
}
|
||||
|
||||
struct event_base *base = NULL;
|
||||
struct evdns_base *dnsbase = NULL;
|
||||
struct evdns_base *dnsbase = NULL;
|
||||
base = event_base_new();
|
||||
if (!base)
|
||||
return;
|
||||
if (! base) {
|
||||
debug(LOG_ERR, "error: event base init failed!");
|
||||
exit(0);
|
||||
}
|
||||
main_ctl->connect_base = base;
|
||||
|
||||
dnsbase = evdns_base_new(base, 1);
|
||||
if (!dnsbase)
|
||||
return;
|
||||
if (! dnsbase) {
|
||||
debug(LOG_ERR, "error: evdns base init failed!");
|
||||
exit(0);
|
||||
}
|
||||
main_ctl->dnsbase = dnsbase;
|
||||
|
||||
evdns_base_set_option(dnsbase, "timeout", "1.0");
|
||||
|
||||
@@ -1027,20 +1044,34 @@ void init_main_control()
|
||||
// http://www.wuqiong.info/archives/13/
|
||||
evdns_base_set_option(dnsbase, "randomize-case:", "0"); //TurnOff DNS-0x20 encoding
|
||||
evdns_base_nameserver_ip_add(dnsbase, "180.76.76.76"); //BaiduDNS
|
||||
evdns_base_nameserver_ip_add(dnsbase, "223.5.5.5"); //AliDNS
|
||||
evdns_base_nameserver_ip_add(dnsbase, "223.5.5.5"); //AliDNS
|
||||
evdns_base_nameserver_ip_add(dnsbase, "223.6.6.6"); //AliDNS
|
||||
evdns_base_nameserver_ip_add(dnsbase, "114.114.114.114"); //114DNS
|
||||
evdns_base_nameserver_ip_add(dnsbase, "114.114.114.114"); //114DNS
|
||||
|
||||
main_ctl->connect_base = base;
|
||||
main_ctl->dnsbase = dnsbase;
|
||||
init_request_buffer();
|
||||
// if server_addr is ip, done control init.
|
||||
if (is_valid_ip_address((const char *)c_conf->server_addr))
|
||||
return;
|
||||
|
||||
// if server_addr is domain, analyze it to ip for server_ip
|
||||
debug(LOG_DEBUG, "Get ip address of [%s] from DNServer", c_conf->server_addr);
|
||||
|
||||
if (get_common_config()->tcp_mux) {
|
||||
uint32_t *sid = init_sid_index();
|
||||
assert(sid);
|
||||
main_ctl->session_id = *sid;
|
||||
struct evutil_addrinfo hints;
|
||||
struct evdns_getaddrinfo_request *dns_req;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = EVUTIL_AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
debug(LOG_DEBUG, "Connect Frps with control session ID: %d", main_ctl->session_id);
|
||||
dns_req = evdns_getaddrinfo(dnsbase,
|
||||
c_conf->server_addr,
|
||||
NULL /* no service name given */,
|
||||
&hints,
|
||||
server_dns_cb,
|
||||
NULL);
|
||||
if (! dns_req) {
|
||||
debug(LOG_ERR, "error: can not analyse the dns of [%s]", c_conf->server_addr);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1063,6 +1094,5 @@ void free_control()
|
||||
if (!main_ctl)
|
||||
return;
|
||||
|
||||
SAFE_FREE(request_buf);
|
||||
SAFE_FREE(main_ctl);
|
||||
}
|
||||
@@ -70,6 +70,4 @@ void send_new_proxy(struct proxy_service *ps);
|
||||
struct bufferevent
|
||||
*connect_server(struct event_base *base, const char *name, const int port);
|
||||
|
||||
void control_request_free(struct control_request *req);
|
||||
|
||||
#endif //_CONTROL_H_
|
||||
@@ -1,2 +0,0 @@
|
||||
/usr/bin/xfrpc
|
||||
/usr/bin/xfrp_test_server
|
||||
26
login.c
26
login.c
@@ -15,6 +15,7 @@
|
||||
#include "msg.h"
|
||||
#include "version.h"
|
||||
#include "login.h"
|
||||
#include "utils.h"
|
||||
|
||||
static struct login *c_login;
|
||||
|
||||
@@ -37,12 +38,12 @@ void init_login()
|
||||
{
|
||||
if (! c_login)
|
||||
c_login = calloc(sizeof(struct login), 1);
|
||||
|
||||
|
||||
assert(c_login);
|
||||
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
assert(c_conf);
|
||||
|
||||
|
||||
struct utsname uname_buf;
|
||||
if (uname(&uname_buf)) {
|
||||
return;
|
||||
@@ -64,6 +65,27 @@ void init_login()
|
||||
c_login->user = c_conf->user;
|
||||
|
||||
c_login->logged = 0;
|
||||
|
||||
/* start to init login->run_id */
|
||||
char ifname[16] = {0};
|
||||
if(get_net_ifname(ifname, 16)){
|
||||
debug(LOG_ERR, "error: get device sign ifname failed!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (strcmp(ifname, "br-lan") == 0) {
|
||||
c_conf->is_router = 1;
|
||||
debug(LOG_DEBUG, "working in router");
|
||||
}
|
||||
|
||||
char if_mac[64] = {0};
|
||||
if(get_net_mac(ifname, if_mac, sizeof(if_mac))) {
|
||||
debug(LOG_ERR, "error: Hard ware MAC address of [%s] get failed!", ifname);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
c_login->run_id = strdup(if_mac);
|
||||
assert(c_login->run_id);
|
||||
}
|
||||
|
||||
int login_resp_check(struct login_resp *lr)
|
||||
|
||||
22
msg.c
22
msg.c
@@ -41,6 +41,8 @@
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "login.h"
|
||||
#include "client.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define JSON_MARSHAL_TYPE(jobj,key,jtype,item) \
|
||||
json_object_object_add(jobj, key, json_object_new_##jtype((item)));
|
||||
@@ -79,7 +81,14 @@ static void fill_custom_domains(struct json_object *j_ctl_req, const char *custo
|
||||
char *tok = tmp, *end = tmp;
|
||||
while (tok != NULL) {
|
||||
strsep(&end, ",");
|
||||
json_object_array_add(jarray_cdomains, json_object_new_string(tok));
|
||||
|
||||
int dname_len = strlen(tok) + 1;
|
||||
char *dname_buf = (char *)calloc(1, dname_len);
|
||||
assert(dname_buf);
|
||||
dns_unified(tok, dname_buf, dname_len);
|
||||
json_object_array_add(jarray_cdomains, json_object_new_string(dname_buf));
|
||||
|
||||
free(dname_buf);
|
||||
tok = end;
|
||||
}
|
||||
SAFE_FREE(tmp);
|
||||
@@ -171,12 +180,21 @@ int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
|
||||
JSON_MARSHAL_TYPE(j_np_req, "proxy_type", string, np_req->proxy_type);
|
||||
JSON_MARSHAL_TYPE(j_np_req, "use_encryption", boolean, np_req->use_encryption);
|
||||
JSON_MARSHAL_TYPE(j_np_req, "use_compression", boolean, np_req->use_compression);
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_port", int, np_req->remote_port);
|
||||
|
||||
if (is_ftp_proxy(np_req)) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_data_port", int, np_req->remote_data_port);
|
||||
}
|
||||
|
||||
if (np_req->custom_domains) {
|
||||
fill_custom_domains(j_np_req, np_req->custom_domains);
|
||||
json_object_object_add(j_np_req, "remote_port", NULL);
|
||||
} else {
|
||||
json_object_object_add(j_np_req, "custom_domains", NULL);
|
||||
if (np_req->remote_port != -1) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_port", int, np_req->remote_port);
|
||||
} else {
|
||||
json_object_object_add(j_np_req, "remote_port", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
JSON_MARSHAL_TYPE(j_np_req, "subdomain", string, SAFE_JSON_STRING(np_req->subdomain));
|
||||
|
||||
24
msg.h
24
msg.h
@@ -61,29 +61,6 @@ struct general_response {
|
||||
char *msg;
|
||||
};
|
||||
|
||||
// messages between control connections of frpc and frps
|
||||
struct control_request {
|
||||
int type;
|
||||
char *proxy_name;
|
||||
char *auth_key;
|
||||
int use_encryption;
|
||||
int use_gzip;
|
||||
int pool_count;
|
||||
|
||||
int privilege_mode;
|
||||
char *privilege_key;
|
||||
char *proxy_type;
|
||||
int remote_port;
|
||||
char *custom_domains;
|
||||
char *locations;
|
||||
char *host_header_rewrite;
|
||||
char *http_username;
|
||||
char *http_password;
|
||||
char *subdomain;
|
||||
long timestamp;
|
||||
};
|
||||
|
||||
|
||||
struct control_response {
|
||||
int type;
|
||||
int code;
|
||||
@@ -114,7 +91,6 @@ size_t pack(struct message *req_msg, unsigned char **ret_buf);
|
||||
struct message *unpack(unsigned char *recv_msg, const ushort len);
|
||||
|
||||
// tranlate control request to json string
|
||||
int control_request_marshal(const struct control_request *req, char **msg);
|
||||
struct login_resp *login_resp_unmarshal(const char *jres);
|
||||
struct start_work_conn_resp *start_work_conn_resp_unmarshal(const char *resp_msg);
|
||||
|
||||
|
||||
36
proxy.c
Normal file
36
proxy.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
|
||||
struct proxy *new_proxy_buf(struct bufferevent *bev)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)calloc(1, sizeof(struct proxy));
|
||||
assert(p);
|
||||
p->bev = bev;
|
||||
p->remote_data_port = -1;
|
||||
p->proxy_name = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
void free_proxy(struct proxy *p)
|
||||
{
|
||||
SAFE_FREE(p->proxy_name);
|
||||
SAFE_FREE(p);
|
||||
}
|
||||
37
proxy.h
Normal file
37
proxy.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef _PROXY_H_
|
||||
#define _PROXY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
|
||||
#define IP_LEN 16
|
||||
|
||||
struct ftp_pasv {
|
||||
int code;
|
||||
char ftp_server_ip[IP_LEN];
|
||||
int ftp_server_port;
|
||||
};
|
||||
|
||||
struct proxy {
|
||||
struct bufferevent *bev;
|
||||
char *proxy_name;
|
||||
int remote_data_port; //used in ftp proxy
|
||||
};
|
||||
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
struct proxy *new_proxy_buf(struct bufferevent *bev);
|
||||
void free_proxy(struct proxy *p);
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp);
|
||||
#endif //_PROXY_H_
|
||||
267
proxy_ftp.c
Normal file
267
proxy_ftp.c
Normal file
@@ -0,0 +1,267 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
#include "client.h"
|
||||
|
||||
#define FTP_PRO_BUF 256
|
||||
#define FTP_PASV_PORT_BLOCK 256
|
||||
|
||||
static struct ftp_pasv *new_ftp_pasv();
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp);
|
||||
static struct ftp_pasv * pasv_unpack(char *data);
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p);
|
||||
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name(ftp_proxy_name);
|
||||
|
||||
struct proxy_service *p_services = get_all_proxy_services();
|
||||
HASH_FIND_STR(p_services, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
debug(LOG_ERR,
|
||||
"error: ftp data proxy not inserted in proxy-service queue, it should not happend!");
|
||||
goto FTP_DATA_PROXY_TUNNEL_END;
|
||||
}
|
||||
|
||||
ps->local_port = local_fp->ftp_server_port;
|
||||
ps->local_ip = strdup(local_fp->ftp_server_ip);
|
||||
assert(ps->local_ip);
|
||||
|
||||
ps->remote_port = remote_fp->ftp_server_port;
|
||||
|
||||
debug(LOG_DEBUG,
|
||||
"set ftp proxy DATA port [local:remote] = [%d:%d]",
|
||||
ps->local_port, ps->remote_port);
|
||||
|
||||
FTP_DATA_PROXY_TUNNEL_END:
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
// read from client-working host port
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
assert(p);
|
||||
struct bufferevent *partner = p->bev;
|
||||
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
dst = bufferevent_get_output(partner);
|
||||
assert(dst);
|
||||
|
||||
unsigned char *buf = calloc(1, len);
|
||||
assert(buf);
|
||||
size_t read_n = 0;
|
||||
read_n = evbuffer_remove(src, buf, len);
|
||||
|
||||
// #define FTP_P_DEBUG 1
|
||||
#ifdef FTP_P_DEBUG
|
||||
char *dbg_buf = calloc(1, read_n * 7 + 1);
|
||||
assert(dbg_buf);
|
||||
unsigned int i = 0;
|
||||
for(i = 0; i<read_n && ((2 * i) < (read_n * 2 + 1)); i++) {
|
||||
snprintf(dbg_buf + 7*i, 8, "%3u[%c] ",
|
||||
(unsigned char)buf[i],
|
||||
(unsigned char)buf[i]);
|
||||
}
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl byte:%s", dbg_buf);
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl stri:%s", buf);
|
||||
SAFE_FREE(dbg_buf);
|
||||
#endif //FTP_P_DEBUG
|
||||
|
||||
struct ftp_pasv *local_fp = pasv_unpack((char *)buf);
|
||||
|
||||
if (local_fp) {
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct ftp_pasv *r_fp = new_ftp_pasv();
|
||||
r_fp->code = local_fp->code;
|
||||
|
||||
if (! c_conf->server_ip) {
|
||||
debug(LOG_ERR, "error: FTP proxy without server ip!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
strncpy(r_fp->ftp_server_ip, c_conf->server_ip, IP_LEN);
|
||||
r_fp->ftp_server_port = p->remote_data_port;
|
||||
|
||||
if (r_fp->ftp_server_port <= 0) {
|
||||
debug(LOG_ERR, "error: remote ftp data port is not init!");
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
char *pasv_msg = NULL;
|
||||
size_t pack_len = pasv_pack(r_fp, &pasv_msg);
|
||||
if ( ! pack_len){
|
||||
debug(LOG_ERR, "error: ftp proxy replace failed!");
|
||||
SAFE_FREE(pasv_msg);
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
#ifdef FTP_P_DEBUG
|
||||
debug(LOG_DEBUG, "ftp pack result:%s", pasv_msg);
|
||||
#endif //FTP_P_DEBUG
|
||||
|
||||
set_ftp_data_proxy_tunnel(p->proxy_name, local_fp, r_fp);
|
||||
evbuffer_add(dst, pasv_msg, pack_len);
|
||||
SAFE_FREE(pasv_msg);
|
||||
} else {
|
||||
evbuffer_add(dst, buf, read_n);
|
||||
}
|
||||
|
||||
FTP_C2S_CB_END:
|
||||
SAFE_FREE(buf);
|
||||
free_ftp_pasv(local_fp);
|
||||
return;
|
||||
}
|
||||
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
tcp_proxy_s2c_cb(bev, ctx);
|
||||
}
|
||||
|
||||
static struct ftp_pasv *pasv_unpack(char *data)
|
||||
{
|
||||
char cd_buf[4] = {0};
|
||||
snprintf(cd_buf, 4, "%s", data);
|
||||
int code = atoi(cd_buf);
|
||||
if (code != 227 && code != 211 && code != 229)
|
||||
return NULL;
|
||||
|
||||
struct ftp_pasv *fp = new_ftp_pasv();
|
||||
assert(fp);
|
||||
|
||||
fp->code = code;
|
||||
switch(fp->code) {
|
||||
case 227:
|
||||
{
|
||||
int i = 0, ip_i = 0, port_i = 0, ip_start = 0, comma_n = 0;
|
||||
char port[2][4] = { {0}, {0} };
|
||||
for (i=0; i<strlen(data) && ip_i<IP_LEN; i++) {
|
||||
if (data[i] == '(') {
|
||||
ip_start = 1;
|
||||
continue;
|
||||
}
|
||||
if (! ip_start)
|
||||
continue;
|
||||
|
||||
if (data[i] == ')')
|
||||
break;
|
||||
|
||||
if (data[i] == ','){
|
||||
comma_n++;
|
||||
port_i = 0;
|
||||
if (comma_n < 4){
|
||||
fp->ftp_server_ip[ip_i] = '.';
|
||||
ip_i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comma_n >= 4 && port_i < 4) {
|
||||
port[comma_n - 4][port_i] = data[i];
|
||||
port_i++;
|
||||
continue;
|
||||
}
|
||||
fp->ftp_server_ip[ip_i] = data[i];
|
||||
ip_i++;
|
||||
}
|
||||
|
||||
fp->ftp_server_port = atoi(port[0]) * FTP_PASV_PORT_BLOCK + atoi(port[1]);
|
||||
debug(LOG_DEBUG, "ftp pasv unpack:[%s:%d]", fp->ftp_server_ip, fp->ftp_server_port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
free_ftp_pasv(fp);
|
||||
break;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// the value returned need FREE after using
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p)
|
||||
{
|
||||
*pack_p = (char *)calloc(1, FTP_PRO_BUF);
|
||||
assert(*pack_p);
|
||||
size_t pack_len = 0;
|
||||
|
||||
switch (fp->code){
|
||||
case 227:
|
||||
{
|
||||
char ftp_ip[IP_LEN] = {0};
|
||||
int i =0;
|
||||
for (i=0; i<strlen(fp->ftp_server_ip) && i < IP_LEN; i++) {
|
||||
if (fp->ftp_server_ip[i] == '.') {
|
||||
ftp_ip[i] = ',';
|
||||
continue;
|
||||
}
|
||||
|
||||
ftp_ip[i] = fp->ftp_server_ip[i];
|
||||
}
|
||||
snprintf(*pack_p,
|
||||
FTP_PRO_BUF,
|
||||
"227 Entering Passive Mode (%s,%d,%d).\n",
|
||||
ftp_ip,
|
||||
fp->ftp_server_port / FTP_PASV_PORT_BLOCK,
|
||||
fp->ftp_server_port % FTP_PASV_PORT_BLOCK);
|
||||
|
||||
pack_len = strlen(*pack_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
debug(LOG_DEBUG, "ftp pasv protocol data not supportted in pasv_pack");
|
||||
free(*pack_p);
|
||||
break;
|
||||
}
|
||||
|
||||
return pack_len;
|
||||
}
|
||||
|
||||
// need be free after using
|
||||
static struct ftp_pasv *new_ftp_pasv()
|
||||
{
|
||||
struct ftp_pasv *fp = (struct ftp_pasv *)calloc(1, sizeof(struct ftp_pasv));
|
||||
if (! fp)
|
||||
return NULL;
|
||||
|
||||
memset(fp->ftp_server_ip, 0, IP_LEN);
|
||||
fp->ftp_server_port = -1;
|
||||
fp->code = -1;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// can be used to free NULL pointer also
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp)
|
||||
{
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
SAFE_FREE(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
44
proxy_tcp.c
Normal file
44
proxy_tcp.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
|
||||
// read from client-working host port
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len > 0) {
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
188
utils.c
188
utils.c
@@ -7,6 +7,15 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <linux/if_link.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
@@ -20,3 +29,182 @@ void s_sleep(unsigned int s, unsigned int u)
|
||||
timeout.tv_usec = u;
|
||||
select(0, NULL, NULL, NULL, &timeout);
|
||||
}
|
||||
|
||||
// is_valid_ip_address:
|
||||
// return 0:ipaddress unlegal
|
||||
int is_valid_ip_address(const char *ip_address)
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
int result = inet_pton(AF_INET, ip_address, &(sa.sin_addr));
|
||||
return result;
|
||||
}
|
||||
|
||||
// net_if_name: name of network interface, e.g. br-lan
|
||||
// return: 1: error 0:get succeed
|
||||
int get_net_mac(char *net_if_name, char *mac, int mac_len) {
|
||||
int ret = 1;
|
||||
int i = 0;
|
||||
int sock = 0;
|
||||
|
||||
if (mac_len < 12 || net_if_name == NULL) {
|
||||
return 1;
|
||||
}
|
||||
struct ifreq ifreq;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( sock < 0 ) {
|
||||
perror("error sock");
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
strncpy(ifreq.ifr_name, net_if_name, IFNAMSIZ);
|
||||
if( ioctl(sock, SIOCGIFHWADDR,&ifreq) < 0 ) {
|
||||
perror("error ioctl");
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
for( i = 0; i < 6; i++ ){
|
||||
snprintf(mac+2*i, mac_len - 2*i, "%02X",
|
||||
(unsigned char)ifreq.ifr_hwaddr.sa_data[i]);
|
||||
}
|
||||
mac[strlen(mac)] = 0;
|
||||
ret = 0;
|
||||
|
||||
OUT:
|
||||
close(sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// return: -1: network interface check failed; other: ifname numbers
|
||||
int show_net_ifname()
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int family, s, n;
|
||||
char host[NI_MAXHOST];
|
||||
|
||||
if (getifaddrs(&ifaddr) == -1) {
|
||||
perror("getifaddrs");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Walk through linked list, maintaining head pointer so we
|
||||
can free list later */
|
||||
|
||||
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
|
||||
if (ifa->ifa_addr == NULL) continue;
|
||||
|
||||
family = ifa->ifa_addr->sa_family;
|
||||
|
||||
/* Display interface name and family (including symbolic
|
||||
form of the latter for the common families) */
|
||||
|
||||
printf("%-8s %s (%d)\n",
|
||||
ifa->ifa_name,
|
||||
(family == AF_PACKET) ? "AF_PACKET" :
|
||||
(family == AF_INET) ? "AF_INET" :
|
||||
(family == AF_INET6) ? "AF_INET6" : "???",
|
||||
family);
|
||||
|
||||
/* For an AF_INET* interface address, display the address */
|
||||
|
||||
if (family == AF_INET || family == AF_INET6) {
|
||||
s = getnameinfo(ifa->ifa_addr,
|
||||
(family == AF_INET) ? sizeof(struct sockaddr_in) :
|
||||
sizeof(struct sockaddr_in6),
|
||||
host, NI_MAXHOST,
|
||||
NULL, 0, NI_NUMERICHOST);
|
||||
if (s != 0) {
|
||||
printf("getnameinfo() failed: %s\n", gai_strerror(s));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("\t\taddress: <%s>\n", host);
|
||||
|
||||
} else if (family == AF_PACKET && ifa->ifa_data != NULL) {
|
||||
struct rtnl_link_stats *stats = (struct rtnl_link_stats *)ifa->ifa_data;
|
||||
|
||||
printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
|
||||
"\t\ttx_bytes = %10u; rx_bytes = %10u\n",
|
||||
stats->tx_packets, stats->rx_packets,
|
||||
stats->tx_bytes, stats->rx_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return: 0: network interface get succeed
|
||||
int get_net_ifname(char *if_buf, int blen)
|
||||
{
|
||||
if (NULL == if_buf || blen < 8) return -1;
|
||||
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int family, n;
|
||||
int ret = 1;
|
||||
if (getifaddrs(&ifaddr) == -1) {
|
||||
perror("getifaddrs");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
char tmp_if_buf[16];
|
||||
memset(tmp_if_buf, 0, sizeof(tmp_if_buf));
|
||||
/* Walk through linked list, maintaining head pointer so we
|
||||
can free list later */
|
||||
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
|
||||
if (ifa->ifa_addr == NULL) continue;
|
||||
|
||||
family = ifa->ifa_addr->sa_family;
|
||||
|
||||
if (family == AF_INET) {
|
||||
// for LEDE/OpenWRT embedded router os
|
||||
if (strcmp(ifa->ifa_name, "br-lan") == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
} else if (family == AF_PACKET &&
|
||||
ifa->ifa_data != NULL &&
|
||||
strcmp(ifa->ifa_name, "lo") != 0) { // skip local loop interface
|
||||
|
||||
strncpy(tmp_if_buf, ifa->ifa_name, 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
strncpy(if_buf, ifa->ifa_name, blen);
|
||||
ret = 0;
|
||||
} else if (tmp_if_buf[0] != 0) {
|
||||
strncpy(if_buf, tmp_if_buf, blen);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// e.g. wWw.Baidu.com/China will be trans into www.baidu.com/China
|
||||
// return: 0:check and trant succeed, 1:failed or domain name is invalid
|
||||
int dns_unified(const char *dname, char *udname_buf, int udname_buf_len)
|
||||
{
|
||||
if (! dname || ! udname_buf || udname_buf_len < strlen(dname)+1)
|
||||
return 1;
|
||||
|
||||
int has_dot = 0;
|
||||
int dlen = strlen(dname);
|
||||
int i = 0;
|
||||
for(i=0; i<dlen; i++) {
|
||||
if(dname[i] == '/')
|
||||
break;
|
||||
|
||||
if (dname[i] == '.' && i != dlen-1)
|
||||
has_dot = 1;
|
||||
|
||||
udname_buf[i] = tolower(dname[i]);
|
||||
}
|
||||
|
||||
if (! has_dot) //domain name should have 1 dot leastly
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
utils.h
8
utils.h
@@ -3,4 +3,12 @@
|
||||
|
||||
void s_sleep(unsigned int s, unsigned int u);
|
||||
|
||||
// is_valid_ip_address:
|
||||
// return 0:ipaddress unlegal
|
||||
int is_valid_ip_address(const char *ip_address);
|
||||
int show_net_ifname();
|
||||
int get_net_ifname(char *if_buf, int blen);
|
||||
int get_net_mac(char *net_if_name, char *mac, int mac_len);
|
||||
int dns_unified(const char *dname, char *udname_buf, int udname_buf_len);
|
||||
|
||||
#endif //_UTILS_H_
|
||||
|
||||
Reference in New Issue
Block a user