From 2aa063db791781da2472564da5dd4c9fdefb36f7 Mon Sep 17 00:00:00 2001 From: Victor Antonovich Date: Tue, 16 Jul 2019 11:14:37 +0400 Subject: [PATCH] Add command-line and config options to set an TCP socket address (#53) Still no IPv6 support though. --- README.md | 6 ++++-- conf/mbusd.conf.example | 3 +++ doc/mbusd.8.in | 4 ++++ src/cfg.c | 5 +++++ src/cfg.h | 2 ++ src/conn.c | 7 +++---- src/conn.h | 1 + src/main.c | 12 +++++++++--- src/sock.c | 39 +++++++++++++++++++++++++-------------- 9 files changed, 56 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index c317180..3e1def3 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ Usage: ------ mbusd [-h] [-d] [-L logfile] [-v level] [-c cfgfile] [-p device] [-s speed] [-m mode] - [-t] [-y file] [-Y file] [-P port] [-C maxconn] [-N retries] - [-R pause] [-W wait] [-T timeout] + [-t] [-y file] [-Y file] [-A address] [-P port] [-C maxconn] [-N retries] + [-R pause] [-W wait] [-T timeout] -h Usage help. -d Instruct mbusd not to fork itself (non-daemonize). @@ -80,6 +80,8 @@ Usage: -Y file Enable RS-485 direction data direction control by writing '0' to file for transmitter enable and '1' to file for transmitter disable + -A address + Specifies TCP address to bind (default 0.0.0.0). -P port Specifies TCP port number (default 502). -C maxconn diff --git a/conf/mbusd.conf.example b/conf/mbusd.conf.example index 5e5db92..dc2ada0 100644 --- a/conf/mbusd.conf.example +++ b/conf/mbusd.conf.example @@ -23,6 +23,9 @@ trx_control = addc ############# TCP port settings ############# +# TCP server address to bind +address = 0.0.0.0 + # TCP server port number port = 502 diff --git a/doc/mbusd.8.in b/doc/mbusd.8.in index 2da2b4f..07300eb 100644 --- a/doc/mbusd.8.in +++ b/doc/mbusd.8.in @@ -22,6 +22,8 @@ mbusd \- MODBUS/TCP to MODBUS/RTU gateway. .IR file ] .RB [ -Y .IR file ] +.RB [ -A +.IR address ] .RB [ -P .IR port ] .RB [ -C @@ -57,6 +59,8 @@ Specifies serial port device name. Specifies serial port speed. .IP "\fB-m \fImode\fR" Specifies serial port mode (like 8N1). +.IP "\fB-A \fIaddress\fR" +Specifies TCP address to bind. .IP "\fB-P \fIport\fR" Specifies TCP port number. .IP \fB-t\fR diff --git a/src/cfg.c b/src/cfg.c index a3a98b6..5a4bb10 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -67,6 +67,7 @@ cfg_init(void) cfg.trxcntl = TRX_ADDC; *cfg.trxcntl_file = '\0'; #endif + strncpy(cfg.serveraddr, DEFAULT_SERVERADDR, INTBUFSIZE); cfg.serverport = DEFAULT_SERVERPORT; cfg.maxconn = DEFAULT_MAXCONN; cfg.maxtry = DEFAULT_MAXTRY; @@ -122,6 +123,10 @@ cfg_handle_param(char *name, char *value) } strncpy(cfg.ttymode, value, INTBUFSIZE); } + else if (CFG_NAME_MATCH("address")) + { + strncpy(cfg.serveraddr, value, INTBUFSIZE); + } else if (CFG_NAME_MATCH("port")) { cfg.serverport = strtoul(value, NULL, 0); diff --git a/src/cfg.h b/src/cfg.h index 9b60fa1..5f4be57 100644 --- a/src/cfg.h +++ b/src/cfg.h @@ -58,6 +58,8 @@ typedef struct int trxcntl; /* trx control sysfs file */ char trxcntl_file[INTBUFSIZE + 1]; + /* TCP server address */ + char serveraddr[INTBUFSIZE + 1]; /* TCP server port number */ int serverport; /* maximum number of connections */ diff --git a/src/conn.c b/src/conn.c index 3e26588..77c2060 100644 --- a/src/conn.c +++ b/src/conn.c @@ -113,13 +113,12 @@ conn_init(void) state_tty_set(&tty, TTY_PAUSE); /* create server socket */ - if ((server_sd = - sock_create_server("", cfg.serverport, TRUE)) < 0) + if ((server_sd = sock_create_server(cfg.serveraddr, cfg.serverport, TRUE)) < 0) { #ifdef LOG logw(0, "conn_init():" - " can't create listen() socket (%s)", - strerror(errno)); + " can't create listen socket (%s)", + (errno != 0) ? strerror(errno) : "failed"); #endif return RC_ERR; } diff --git a/src/conn.h b/src/conn.h index 9b7c121..45fcc06 100644 --- a/src/conn.h +++ b/src/conn.h @@ -46,6 +46,7 @@ /* * Default values */ +#define DEFAULT_SERVERADDR "0.0.0.0" #define DEFAULT_SERVERPORT 502 #define DEFAULT_MAXCONN 32 #define DEFAULT_MAXTRY 3 diff --git a/src/main.c b/src/main.c index bb951fc..2f6fe94 100644 --- a/src/main.c +++ b/src/main.c @@ -111,7 +111,8 @@ usage(char *exename) #ifdef TRXCTL " [-t] [-y sysfsfile] [-Y sysfsfile]\n" #endif - " [-P port] [-C maxconn] [-N retries] [-R pause] [-W wait] [-T timeout]\n\n" + " [-A address] [-P port] [-C maxconn] [-N retries]\n" + " [-R pause] [-W wait] [-T timeout]\n\n" "Options:\n" " -h : this help\n" " -d : don't daemonize\n" @@ -128,6 +129,7 @@ usage(char *exename) " -p device : set serial port device name (default %s)\n" " -s speed : set serial port speed (default %d)\n" " -m mode : set serial port mode (default %s)\n" + " -A address : set TCP server address to bind (default %s)\n" " -P port : set TCP server port number (default %d)\n" #ifdef TRXCTL " -t : enable RTS RS-485 data direction control using RTS\n" @@ -148,7 +150,8 @@ usage(char *exename) #ifdef LOG LOGPATH, LOGNAME, cfg.dbglvl, #endif - cfg.ttyport, cfg.ttyspeed, cfg.ttymode, cfg.serverport, + cfg.ttyport, cfg.ttyspeed, cfg.ttymode, + cfg.serveraddr, cfg.serverport, MAX_MAXCONN, cfg.maxconn, MAX_MAXTRY, cfg.maxtry, MAX_RQSTPAUSE, cfg.rqstpause, MAX_RESPWAIT, cfg.respwait, MAX_CONNTIMEOUT, cfg.conntimeout); @@ -180,7 +183,7 @@ main(int argc, char *argv[]) #ifdef LOG "v:L:" #endif - "p:s:m:P:C:N:R:W:T:c:")) != RC_ERR) + "p:s:m:A:P:C:N:R:W:T:c:")) != RC_ERR) { switch (rc) { @@ -290,6 +293,9 @@ main(int argc, char *argv[]) exit(-1); } break; + case 'A': + strncpy(cfg.serveraddr, optarg, INTBUFSIZE); + break; case 'P': cfg.serverport = strtoul(optarg, NULL, 0); break; diff --git a/src/sock.c b/src/sock.c index 15d1837..970afc1 100644 --- a/src/sock.c +++ b/src/sock.c @@ -94,13 +94,33 @@ sock_create(int blkmode) * Return: socket descriptor, otherwise RC_ERR if there some errors */ int -sock_create_server(char *server_ip, - unsigned short server_port, int blkmode) +sock_create_server(char *server_ip, unsigned short server_port, int blkmode) { struct sockaddr_in server_sockaddr; int sock_opt = 1; int server_s; + memset(&server_sockaddr, 0, sizeof(server_sockaddr)); + server_sockaddr.sin_family = AF_INET; // FIXME IPv6 support + + /* parse address to bind socket */ + if (server_ip != NULL) + { + if (inet_aton(server_ip, &server_sockaddr.sin_addr) == 0) + { +#ifdef LOG + logw(0, "sock_create_server():" + " can't parse address: %s", + server_ip); +#endif + return RC_ERR; + } + } + else + server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + + server_sockaddr.sin_port = htons(server_port); + /* create socket in desired blocking mode */ server_s = sock_create(blkmode); if (server_s < 0) return server_s; @@ -144,18 +164,9 @@ sock_create_server(char *server_ip, return RC_ERR; } - memset(&server_sockaddr, 0, sizeof(server_sockaddr)); - server_sockaddr.sin_family = AF_INET; - - if (server_ip != NULL) - inet_aton(server_ip, &server_sockaddr.sin_addr); - else - server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); - - server_sockaddr.sin_port = htons(server_port); - + /* bind socket to given address and port */ if (bind(server_s, (struct sockaddr *) & server_sockaddr, - sizeof(server_sockaddr)) == -1) + sizeof(server_sockaddr)) == -1) { #ifdef LOG logw(0, "sock_create_server():" @@ -207,7 +218,7 @@ sock_accept(int server_sd, struct sockaddr_in *rmt_addr, int blkmode) if (sock_set_blkmode(sd, blkmode) == RC_ERR) { #ifdef LOG - logw(0, "sock_accept(): can't set socket blocking mode (%s)", + logw(0, "sock_accept(): can't set socket blocking mode (%s)", strerror(errno)); #endif close(sd);