From b6defc6a7f09b73e0972c83a8fdfa75907772c96 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 6 Mar 2014 15:55:13 -0600 Subject: [PATCH 1/3] rsrv: Use EPICS_CAS_INTF_ADDR_LIST in req_server Parse EPICS_CAS_INTF_ADDR_LIST into new ELLLIST casIntfAddrList. Display warning if contains more than one entry. Bind the TCP socket to the first address in this list. --- src/ioc/rsrv/caservertask.c | 79 +++++++++++++++++++++---------------- src/ioc/rsrv/server.h | 1 + 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/ioc/rsrv/caservertask.c b/src/ioc/rsrv/caservertask.c index e3ab087f1..14c7ce1b0 100644 --- a/src/ioc/rsrv/caservertask.c +++ b/src/ioc/rsrv/caservertask.c @@ -63,8 +63,9 @@ static void req_server (void *pParm) unsigned priorityOfSelf = epicsThreadGetPrioritySelf (); unsigned priorityOfBeacons; epicsThreadBooleanStatus tbs; + osiSockAddrNode *pNode; struct sockaddr_in serverAddr; /* server's address */ - osiSocklen_t addrSize; + osiSocklen_t addrSize = (osiSocklen_t) sizeof(struct sockaddr_in); int status; SOCKET clientSock; epicsThreadId tid; @@ -85,6 +86,24 @@ static void req_server (void *pParm) (unsigned short) CA_SERVER_PORT ); } + addAddrToChannelAccessAddressList ( &casIntfAddrList, + &EPICS_CAS_INTF_ADDR_LIST, ca_server_port, 0 ); + if (ellCount(&casIntfAddrList) == 0) { + pNode = (osiSockAddrNode *) calloc ( 1, sizeof(*pNode) ); + pNode->addr.ia.sin_family = AF_INET; + pNode->addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY ); + pNode->addr.ia.sin_port = htons ( ca_server_port ); + ellAdd ( &casIntfAddrList, &pNode->node ); + } + else { + if (ellCount ( &casIntfAddrList ) > 1) + epicsPrintf ("CAS: Multiple entries in EPICS_CAS_INTF_ADDR_LIST, " + "only the first will be used.\n"); + pNode = (osiSockAddrNode *) ellFirst ( &casIntfAddrList ); + } + + memcpy ( &serverAddr, &pNode->addr.ia, addrSize ); + if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) { epicsSocketDestroy ( IOC_sock ); } @@ -100,50 +119,43 @@ static void req_server (void *pParm) epicsSocketEnableAddressReuseDuringTimeWaitState ( IOC_sock ); - /* Zero the sock_addr structure */ - memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) ); - serverAddr.sin_family = AF_INET; - serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); - serverAddr.sin_port = htons ( ca_server_port ); - /* get server's Internet address */ - status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); - if ( status < 0 ) { - if ( SOCKERRNO == SOCK_EADDRINUSE ) { - /* - * enable assignment of a default port - * (so the getsockname() call below will - * work correctly) - */ - serverAddr.sin_port = ntohs (0); - status = bind ( IOC_sock, - (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); - } - if ( status < 0 ) { + + status = bind(IOC_sock, (struct sockaddr *) &serverAddr, addrSize); + if ( status < 0 ) { + if ( SOCKERRNO == SOCK_EADDRINUSE ) { + /* + * enable assignment of a default port + * (so the getsockname() call below will + * work correctly) + */ + serverAddr.sin_port = ntohs (0); + status = bind(IOC_sock, (struct sockaddr *) &serverAddr, addrSize); + } + if ( status < 0 ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "CAS: Socket bind error was \"%s\"\n", sockErrBuf ); epicsThreadSuspendSelf (); - } + } portChange = 1; - } + } else { portChange = 0; } - addrSize = ( osiSocklen_t ) sizeof ( serverAddr ); - status = getsockname ( IOC_sock, - (struct sockaddr *)&serverAddr, &addrSize); - if ( status ) { + status = getsockname ( IOC_sock, + (struct sockaddr *)&serverAddr, &addrSize); + if ( status ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ( "CAS: getsockname() error %s\n", - sockErrBuf ); + errlogPrintf ( "CAS: getsockname() error %s\n", + sockErrBuf ); epicsThreadSuspendSelf (); - } + } ca_server_port = ntohs (serverAddr.sin_port); @@ -274,6 +286,7 @@ int rsrv_init (void) } } freeListInitPvt ( &rsrvLargeBufFreeListTCP, rsrvSizeofLargeBufTCP, 1 ); + ellInit ( &casIntfAddrList ); ellInit ( &beaconAddrList ); prsrv_cast_client = NULL; pCaBucket = NULL; @@ -948,16 +961,16 @@ struct client *create_tcp_client ( SOCKET sock ) void casStatsFetch ( unsigned *pChanCount, unsigned *pCircuitCount ) { - LOCK_CLIENTQ; + LOCK_CLIENTQ; { int circuitCount = ellCount ( &clientQ ); if ( circuitCount < 0 ) { - *pCircuitCount = 0; + *pCircuitCount = 0; } else { - *pCircuitCount = (unsigned) circuitCount; + *pCircuitCount = (unsigned) circuitCount; } *pChanCount = rsrvChannelCount; } - UNLOCK_CLIENTQ; + UNLOCK_CLIENTQ; } diff --git a/src/ioc/rsrv/server.h b/src/ioc/rsrv/server.h index 9651ca601..c45728593 100644 --- a/src/ioc/rsrv/server.h +++ b/src/ioc/rsrv/server.h @@ -165,6 +165,7 @@ GLBLTYPE SOCKET IOC_cast_sock; GLBLTYPE unsigned short ca_server_port; GLBLTYPE ELLLIST clientQ; /* locked by clientQlock */ GLBLTYPE ELLLIST beaconAddrList; +GLBLTYPE ELLLIST casIntfAddrList; GLBLTYPE epicsMutexId clientQlock; GLBLTYPE struct client *prsrv_cast_client; GLBLTYPE BUCKET *pCaBucket; From 56cc1a638a6f3b321b90613668265b9a386c583e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 6 Mar 2014 16:00:02 -0600 Subject: [PATCH 2/3] rsrv: Use casIntfAddrList in cast_server Remove re-parsing of EPICS_CA[S]_SERVER_PORT params. Bind the UDP socket to the first address in the list. --- src/ioc/rsrv/cast_server.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/ioc/rsrv/cast_server.c b/src/ioc/rsrv/cast_server.c index 27cbea355..939cc5514 100644 --- a/src/ioc/rsrv/cast_server.c +++ b/src/ioc/rsrv/cast_server.c @@ -115,23 +115,14 @@ static void clean_addrq(void) */ void cast_server(void *pParm) { - struct sockaddr_in sin; + osiSockAddrNode *paddrNode; + struct sockaddr_in sin; int status; int count=0; struct sockaddr_in new_recv_addr; osiSocklen_t recv_addr_size; - unsigned short port; osiSockIoctl_t nchars; - if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) { - port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, - (unsigned short) CA_SERVER_PORT ); - } - else { - port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, - (unsigned short) CA_SERVER_PORT ); - } - recv_addr_size = sizeof(new_recv_addr); if( IOC_cast_sock!=0 && IOC_cast_sock!=INVALID_SOCKET ) { @@ -174,13 +165,11 @@ void cast_server(void *pParm) #endif epicsSocketEnableAddressUseForDatagramFanout ( IOC_cast_sock ); - - /* Zero the sock_addr structure */ - memset((char *)&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_ANY); - sin.sin_port = htons(port); - + + paddrNode = (osiSockAddrNode *) ellFirst ( &casIntfAddrList ); + + memcpy(&sin, &paddrNode->addr.ia, sizeof (sin)); + /* get server's Internet address */ if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) < 0){ char sockErrBuf[64]; @@ -245,7 +234,8 @@ void cast_server(void *pParm) * see if the next message is for this same client. */ if (prsrv_cast_client->send.stk>sizeof(caHdr)) { - status = memcmp( (void *)&prsrv_cast_client->addr, (void *)&new_recv_addr, recv_addr_size); + status = memcmp(&prsrv_cast_client->addr, + &new_recv_addr, recv_addr_size); if(status){ /* * if the address is different From 7b9b2b19d33ae411329c4f1d7ba9b349ab80ff9a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 6 Mar 2014 16:02:20 -0600 Subject: [PATCH 3/3] Document changes. --- documentation/RELEASE_NOTES.html | 7 +++++++ src/ca/client/CAref.html | 15 ++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index e0d26ef01..3c1634639 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -15,6 +15,13 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.

Changes between 3.15.0.1 and 3.15.0.2

+

Implement EPICS_CAS_INTF_ADDR_LIST in rsrv

+ +

The IOC server can now bind to a single IP address (and optional port number) +read from the standard environment parameter EPICS_CAS_INTF_ADDR_LIST. +Additional addresses included in that parameter after the first will be ignored +and a warning message displayed at iocInit time.

+

Added echo command to iocsh

The single argument string may contain escaped characters, which will be diff --git a/src/ca/client/CAref.html b/src/ca/client/CAref.html index 9753a151d..98dbdd5e5 100644 --- a/src/ca/client/CAref.html +++ b/src/ca/client/CAref.html @@ -796,7 +796,7 @@ been done to address this issue so far).

EPICS_CAS_BEACON_ADDR_LIST - {N.N.N.NN.N.N.N:P...} + {N.N.N.N N.N.N.N:P ...} EPICS_CA_ADDR_LIST1 @@ -811,12 +811,12 @@ been done to address this issue so far).

EPICS_CAS_INTF_ADDR_LIST - {N.N.N.NN.N.N.N:P...} + {N.N.N.N N.N.N.N:P ...} <none> EPICS_CAS_IGNORE_ADDR_LIST - {N.N.N.NN.N.N.N:P...} + {N.N.N.N N.N.N.N:P ...} <none> @@ -874,8 +874,13 @@ network interfaces. Specifically, UDP search messages addressed to both the IP addresses in EPICS_CAS_INTF_ADDR_LIST and also to the broadcast addresses of the corresponding LAN interfaces will be accepted by the server. By default, the CA server is accessible from all network interfaces configured into its -host. In R3.14 and previous releases the CA server employed by iocCore does -not implement this feature.

+host.

+ +

In R3.14 and previous releases the CA server employed by iocCore did not +implement the EPICS_CAS_INTF_ADDR_LIST feature. In this release the iocCore +server will read the first IP address from the parameter variable and use that +to select which interface to bind to. Any additional IP addresses will be +ignored and a warning message displayed during IOC initialization.

Ignoring Process Variable Name Resolution Requests From Certain Hosts