mirror of
https://github.com/3cky/mbusd.git
synced 2024-06-24 10:14:49 +02:00
Add IPv6 support (#53)
This commit is contained in:
parent
2aa063db79
commit
88916fe82d
34
src/conn.c
34
src/conn.c
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
58
src/sock.c
58
src/sock.c
|
@ -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);
|
||||
}
|
||||
|
|
22
src/sock.h
22
src/sock.h
|
@ -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
|
||||
|
|
21
src/state.c
21
src/state.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user