Add IPv6 support (#53)

This commit is contained in:
Victor Antonovich 2019-07-17 17:04:22 +04:00
parent 2aa063db79
commit 88916fe82d
5 changed files with 78 additions and 59 deletions

View File

@ -139,26 +139,28 @@ conn_open(void)
{ {
int sd; int sd;
conn_t *newconn; conn_t *newconn;
struct sockaddr_in rmt_addr; struct sockaddr_storage rmt_addr;
char ipstr[INET6_ADDRSTRLEN];
if ((sd = sock_accept(server_sd, &rmt_addr, TRUE)) == RC_ERR) if ((sd = sock_accept(server_sd, (struct sockaddr *)&rmt_addr,
sizeof(rmt_addr), TRUE)) == RC_ERR)
{ /* error in conn_accept() */ { /* error in conn_accept() */
#ifdef LOG #ifdef LOG
logw(0, "conn_open(): error in accept() (%s)", strerror(errno)); logw(0, "conn_open(): error in accept() (%s)", strerror(errno));
#endif #endif
return; return;
} }
inet_ntop(rmt_addr.ss_family, sock_addr((struct sockaddr *)&rmt_addr),
ipstr, sizeof(ipstr));
#ifdef LOG #ifdef LOG
logw(2, "conn_open(): accepting connection from %s", logw(2, "conn_open(): accepting connection from %s", ipstr);
inet_ntoa(rmt_addr.sin_addr));
#endif #endif
/* compare descriptor of connection with FD_SETSIZE */ /* compare descriptor of connection with FD_SETSIZE */
if (sd >= FD_SETSIZE) if (sd >= FD_SETSIZE)
{ {
#ifdef LOG #ifdef LOG
logw(1, "conn_open(): FD_SETSIZE limit reached," logw(1, "conn_open(): FD_SETSIZE limit reached,"
" connection from %s will be dropped", " connection from %s will be dropped", ipstr);
inet_ntoa(rmt_addr.sin_addr));
#endif #endif
close(sd); close(sd);
return; return;
@ -168,8 +170,7 @@ conn_open(void)
{ {
#ifdef LOG #ifdef LOG
logw(1, "conn_open(): number of connections limit reached," logw(1, "conn_open(): number of connections limit reached,"
" connection from %s will be dropped", " connection from %s will be dropped", ipstr);
inet_ntoa(rmt_addr.sin_addr));
#endif #endif
close(sd); close(sd);
return; return;
@ -177,8 +178,7 @@ conn_open(void)
/* enqueue connection */ /* enqueue connection */
newconn = queue_new_elem(&queue); newconn = queue_new_elem(&queue);
newconn->sd = sd; newconn->sd = sd;
memcpy((void *) &newconn->sockaddr, memcpy((void *) &newconn->remote_addr, &ipstr, sizeof(ipstr));
&rmt_addr, sizeof(struct sockaddr_in));
state_conn_set(newconn, CONN_HEADER); state_conn_set(newconn, CONN_HEADER);
} }
@ -192,8 +192,7 @@ conn_close(conn_t *conn)
{ {
conn_t *nextconn; conn_t *nextconn;
#ifdef LOG #ifdef LOG
logw(2, "conn_close(): closing connection from %s", logw(2, "conn_close(): closing connection from %s", conn->remote_addr);
inet_ntoa(conn->sockaddr.sin_addr));
#endif #endif
/* close socket */ /* close socket */
close(conn->sd); close(conn->sd);
@ -535,15 +534,13 @@ conn_loop(void)
if (curconn->state == CONN_TTY) if (curconn->state == CONN_TTY)
{ /* deadlock in CONN_TTY state, make attempt to reinitialize serial port */ { /* deadlock in CONN_TTY state, make attempt to reinitialize serial port */
#ifdef LOG #ifdef LOG
logw(0, "conn[%s]: state CONN_TTY deadlock.", logw(0, "conn[%s]: state CONN_TTY deadlock.", curconn->remote_addr);
inet_ntoa(curconn->sockaddr.sin_addr));
#endif #endif
tty_reinit(); tty_reinit();
} }
/* purge connection */ /* purge connection */
#ifdef LOG #ifdef LOG
logw(2, "conn[%s]: timeout, closing connection", logw(2, "conn[%s]: timeout, closing connection", curconn->remote_addr);
inet_ntoa(curconn->sockaddr.sin_addr));
#endif #endif
curconn = conn_close(curconn); curconn = conn_close(curconn);
continue; continue;
@ -789,8 +786,7 @@ conn_loop(void)
/* check request function code */ /* check request function code */
unsigned char fc = MB_FRAME(curconn->buf, MB_FCODE); unsigned char fc = MB_FRAME(curconn->buf, MB_FCODE);
#ifdef DEBUG #ifdef DEBUG
logw(7, "conn[%s]: read request fc %d", logw(7, "conn[%s]: read request fc %d", curconn->remote_addr, fc);
inet_ntoa(curconn->sockaddr.sin_addr), fc);
#endif #endif
switch (fc) switch (fc)
{ {
@ -849,7 +845,7 @@ conn_loop(void)
sprintf(v, "[%2.2x]", curconn->buf[i]); sprintf(v, "[%2.2x]", curconn->buf[i]);
strncat(t, v, 1024-strlen(t)); strncat(t, v, 1024-strlen(t));
} }
logw(5, "conn[%s]: request: %s", inet_ntoa(curconn->sockaddr.sin_addr), t); logw(5, "conn[%s]: request: %s", curconn->remote_addr, t);
#endif #endif
state_conn_set(curconn, CONN_TTY); state_conn_set(curconn, CONN_TTY);
if (tty.state == TTY_READY) if (tty.state == TTY_READY)

View File

@ -104,7 +104,7 @@ typedef struct conn_t
int sd; /* socket descriptor */ int sd; /* socket descriptor */
int state; /* current state */ int state; /* current state */
int timeout; /* timeout value, secs */ int timeout; /* timeout value, secs */
struct sockaddr_in sockaddr; /* connection structure */ char remote_addr[INET6_ADDRSTRLEN]; /* remote client address */
int ctr; /* counter of data in the buffer */ int ctr; /* counter of data in the buffer */
int read_len; /* length of modbus frame to read */ int read_len; /* length of modbus frame to read */
unsigned char buf[HDRSIZE + BUFSIZE]; /* data buffer */ unsigned char buf[HDRSIZE + BUFSIZE]; /* data buffer */

View File

@ -58,12 +58,11 @@ sock_set_blkmode(int sd, int blkmode)
* Return: socket descriptor, otherwise RC_ERR if there some errors * Return: socket descriptor, otherwise RC_ERR if there some errors
*/ */
int int
sock_create(int blkmode) sock_create(int blkmode, sa_family_t sa_family)
{ {
int sock; int sock;
if ((sock = if ((sock = socket(sa_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{ {
#ifdef LOG #ifdef LOG
logw(0, "sock_create(): unable to create socket (%s)", logw(0, "sock_create(): unable to create socket (%s)",
@ -96,17 +95,23 @@ sock_create(int blkmode)
int 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; struct sockaddr_storage server_sockaddr;
int sock_opt = 1; int sock_opt = 1;
int server_s; int server_s;
memset(&server_sockaddr, 0, sizeof(server_sockaddr)); memset(&server_sockaddr, 0, sizeof(server_sockaddr));
server_sockaddr.sin_family = AF_INET; // FIXME IPv6 support
/* parse address to bind socket */ /* parse address to bind socket */
if (server_ip != NULL) if (server_ip != NULL)
{ {
if (inet_aton(server_ip, &server_sockaddr.sin_addr) == 0) /* try first to parse server_ip as IPv6 address, if it fail, try to parse as IPv4 */
if (inet_pton(AF_INET6, server_ip,
&(*((struct sockaddr_in6 *)&server_sockaddr)).sin6_addr) != 0)
server_sockaddr.ss_family = AF_INET6;
else if (inet_pton(AF_INET, server_ip,
&(*((struct sockaddr_in *)&server_sockaddr)).sin_addr) != 0)
server_sockaddr.ss_family = AF_INET;
else
{ {
#ifdef LOG #ifdef LOG
logw(0, "sock_create_server():" logw(0, "sock_create_server():"
@ -117,12 +122,23 @@ sock_create_server(char *server_ip, unsigned short server_port, int blkmode)
} }
} }
else else
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); {
server_sockaddr.ss_family = AF_INET; // TODO AF_INET6/in6addr_any?
(*((struct sockaddr_in *)&server_sockaddr)).sin_addr.s_addr = htonl(INADDR_ANY);
}
server_sockaddr.sin_port = htons(server_port); /* parse IP port */
switch (server_sockaddr.ss_family) {
case AF_INET:
(*((struct sockaddr_in *)&server_sockaddr)).sin_port = htons(server_port);
break;
case AF_INET6:
(*((struct sockaddr_in6 *)&server_sockaddr)).sin6_port = htons(server_port);
break;
}
/* create socket in desired blocking mode */ /* create socket in desired blocking mode */
server_s = sock_create(blkmode); server_s = sock_create(blkmode, server_sockaddr.ss_family);
if (server_s < 0) return server_s; if (server_s < 0) return server_s;
/* set to close socket on exec() */ /* set to close socket on exec() */
@ -166,7 +182,7 @@ sock_create_server(char *server_ip, unsigned short server_port, int blkmode)
/* bind socket to given address and port */ /* bind socket to given address and port */
if (bind(server_s, (struct sockaddr *)&server_sockaddr, if (bind(server_s, (struct sockaddr *)&server_sockaddr,
sizeof(server_sockaddr)) == -1) sa_len((struct sockaddr *)&server_sockaddr)) == -1)
{ {
#ifdef LOG #ifdef LOG
logw(0, "sock_create_server():" logw(0, "sock_create_server():"
@ -198,13 +214,11 @@ sock_create_server(char *server_ip, unsigned short server_port, int blkmode)
* RMT_ADDR - ptr to connection info structure * RMT_ADDR - ptr to connection info structure
*/ */
int int
sock_accept(int server_sd, struct sockaddr_in *rmt_addr, int blkmode) sock_accept(int server_sd, struct sockaddr *rmt_addr, socklen_t rmt_len, int blkmode)
{ {
int sd, sock_opt = SOCKBUFSIZE; int sd, sock_opt = SOCKBUFSIZE;
int rmt_len = sizeof(struct sockaddr_in);
sd = accept(server_sd, (struct sockaddr *) rmt_addr, sd = accept(server_sd, rmt_addr, &rmt_len);
(socklen_t *) &rmt_len);
if (sd == -1) if (sd == -1)
{ {
if (errno != EAGAIN && errno != EWOULDBLOCK) if (errno != EAGAIN && errno != EWOULDBLOCK)
@ -241,3 +255,17 @@ sock_accept(int server_sd, struct sockaddr_in *rmt_addr, int blkmode)
} }
return sd; return sd;
} }
/*
* Return reference to socket address structure according to its family (AF_INET/AF_INET6)
*/
void *
sock_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET)
{
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

View File

@ -44,11 +44,13 @@
/* Socket buffers size */ /* Socket buffers size */
#define SOCKBUFSIZE 512 #define SOCKBUFSIZE 512
#define sa_len(sa_ptr) ((sa_ptr)->sa_family == AF_INET \
? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6))
int sock_set_blkmode(int sd, int blkmode); int sock_set_blkmode(int sd, int blkmode);
int sock_create(int blkmode); int sock_create(int blkmode, sa_family_t sa_family);
int sock_create_server(char *server_ip, int sock_create_server(char *server_ip, unsigned short server_port, int blkmode);
unsigned short server_port, int blkmode); int sock_accept(int server_sd, struct sockaddr *rmt_addr, socklen_t rmt_len, int blkmode);
int sock_accept(int server_sd, void *sock_addr(struct sockaddr *sa);
struct sockaddr_in *rmt_addr, int blkmode);
#endif #endif

View File

@ -76,47 +76,40 @@ state_conn_set(conn_t *conn, int state)
conn->ctr = 0; conn->ctr = 0;
conn->read_len = HDRSIZE; conn->read_len = HDRSIZE;
#ifdef DEBUG #ifdef DEBUG
logw(5, "conn[%s]: state now is CONN_HEADER", logw(5, "conn[%s]: state now is CONN_HEADER", conn->remote_addr);
inet_ntoa(conn->sockaddr.sin_addr));
#endif #endif
break; break;
case CONN_RQST_FUNC: case CONN_RQST_FUNC:
conn->read_len = HDRSIZE + MB_FRAME(conn->buf, MB_LENGTH_L); conn->read_len = HDRSIZE + MB_FRAME(conn->buf, MB_LENGTH_L);
#ifdef DEBUG #ifdef DEBUG
logw(5, "conn[%s]: state now is CONN_RQST_FUNC", logw(5, "conn[%s]: state now is CONN_RQST_FUNC", conn->remote_addr);
inet_ntoa(conn->sockaddr.sin_addr));
#endif #endif
break; break;
case CONN_RQST_NVAL: case CONN_RQST_NVAL:
#ifdef DEBUG #ifdef DEBUG
logw(5, "conn[%s]: state now is CONN_RQST_NVAL", logw(5, "conn[%s]: state now is CONN_RQST_NVAL", conn->remote_addr);
inet_ntoa(conn->sockaddr.sin_addr));
#endif #endif
break; break;
case CONN_RQST_TAIL: case CONN_RQST_TAIL:
#ifdef DEBUG #ifdef DEBUG
logw(5, "conn[%s]: state now is CONN_RQST_TAIL", logw(5, "conn[%s]: state now is CONN_RQST_TAIL", conn->remote_addr);
inet_ntoa(conn->sockaddr.sin_addr));
#endif #endif
break; break;
case CONN_TTY: case CONN_TTY:
#ifdef DEBUG #ifdef DEBUG
logw(5, "conn[%s]: state now is CONN_TTY", logw(5, "conn[%s]: state now is CONN_TTY", conn->remote_addr);
inet_ntoa(conn->sockaddr.sin_addr));
#endif #endif
break; break;
case CONN_RESP: case CONN_RESP:
conn->ctr = 0; conn->ctr = 0;
#ifdef DEBUG #ifdef DEBUG
logw(5, "conn[%s]: state now is CONN_RESP", logw(5, "conn[%s]: state now is CONN_RESP", conn->remote_addr);
inet_ntoa(conn->sockaddr.sin_addr));
#endif #endif
break; break;
default: default:
/* unknown state, exiting */ /* unknown state, exiting */
#ifdef DEBUG #ifdef DEBUG
logw(5, "conn_set_state([%s]) - invalid state (%d)", logw(5, "conn_set_state([%s]) - invalid state (%d)", conn->remote_addr, state);
inet_ntoa(conn->sockaddr.sin_addr), state);
#endif #endif
exit (-1); exit (-1);
} }