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

View File

@ -104,7 +104,7 @@ typedef struct conn_t
int sd; /* socket descriptor */
int state; /* current state */
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 read_len; /* length of modbus frame to read */
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
*/
int
sock_create(int blkmode)
sock_create(int blkmode, sa_family_t sa_family)
{
int sock;
if ((sock =
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
if ((sock = socket(sa_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
#ifdef LOG
logw(0, "sock_create(): unable to create socket (%s)",
@ -96,17 +95,23 @@ sock_create(int blkmode)
int
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 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)
/* 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
logw(0, "sock_create_server():"
@ -117,12 +122,23 @@ sock_create_server(char *server_ip, unsigned short server_port, int blkmode)
}
}
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 */
server_s = sock_create(blkmode);
server_s = sock_create(blkmode, server_sockaddr.ss_family);
if (server_s < 0) return server_s;
/* set to close socket on exec() */
@ -165,8 +181,8 @@ sock_create_server(char *server_ip, unsigned short server_port, int blkmode)
}
/* bind socket to given address and port */
if (bind(server_s, (struct sockaddr *) & server_sockaddr,
sizeof(server_sockaddr)) == -1)
if (bind(server_s, (struct sockaddr *)&server_sockaddr,
sa_len((struct sockaddr *)&server_sockaddr)) == -1)
{
#ifdef LOG
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
*/
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 rmt_len = sizeof(struct sockaddr_in);
sd = accept(server_sd, (struct sockaddr *) rmt_addr,
(socklen_t *) &rmt_len);
sd = accept(server_sd, rmt_addr, &rmt_len);
if (sd == -1)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
@ -241,3 +255,17 @@ sock_accept(int server_sd, struct sockaddr_in *rmt_addr, int blkmode)
}
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

@ -1,21 +1,21 @@
/*
* OpenMODBUS/TCP to RS-232/485 MODBUS RTU gateway
*
* sock.h - socket manipulation routines
* sock.h - socket manipulation routines
*
* Copyright (c) 2002-2003, 2013, Victor Antonovich (v.antonovich@gmail.com)
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -44,11 +44,13 @@
/* Socket buffers size */
#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_create(int blkmode);
int sock_create_server(char *server_ip,
unsigned short server_port, int blkmode);
int sock_accept(int server_sd,
struct sockaddr_in *rmt_addr, int blkmode);
int sock_create(int blkmode, sa_family_t sa_family);
int sock_create_server(char *server_ip, unsigned short server_port, int blkmode);
int sock_accept(int server_sd, struct sockaddr *rmt_addr, socklen_t rmt_len, int blkmode);
void *sock_addr(struct sockaddr *sa);
#endif

View File

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