This is Unofficial EPICS BASE Doxygen Site
iocinf.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 
10 /*
11  *
12  * L O S A L A M O S
13  * Los Alamos National Laboratory
14  * Los Alamos, New Mexico 87545
15  *
16  * Copyright, 1986, The Regents of the University of California.
17  *
18  * Author: Jeff Hill
19  */
20 
21 #define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
22 
23 #include <ctype.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stddef.h>
27 
28 #include "envDefs.h"
29 #include "epicsAssert.h"
30 #include "epicsStdioRedirect.h"
31 #include "errlog.h"
32 #include "osiWireFormat.h"
33 
34 #include "addrList.h"
35 #include "iocinf.h"
36 
37 /*
38  * getToken()
39  */
40 static char *getToken ( const char **ppString, char *pBuf, unsigned bufSIze )
41 {
42  bool tokenFound = false;
43  const char *pToken;
44  unsigned i;
45 
46  pToken = *ppString;
47  while ( isspace (*pToken) && *pToken ){
48  pToken++;
49  }
50 
51  for ( i=0u; i<bufSIze; i++ ) {
52  if ( isspace (pToken[i]) || pToken[i]=='\0' ) {
53  pBuf[i] = '\0';
54  *ppString = &pToken[i];
55  if ( i != 0 ) {
56  tokenFound = true;
57  }
58  break;
59  }
60  pBuf[i] = pToken[i];
61  }
62 
63  if ( tokenFound ) {
64  pBuf[bufSIze-1] = '\0';
65  return pBuf;
66  }
67  return NULL;
68 }
69 
70 /*
71  * addAddrToChannelAccessAddressList ()
72  */
73 extern "C" int epicsStdCall addAddrToChannelAccessAddressList
74  ( ELLLIST *pList, const ENV_PARAM *pEnv,
75  unsigned short port, int ignoreNonDefaultPort )
76 {
77  osiSockAddrNode *pNewNode;
78  const char *pStr;
79  const char *pToken;
80  struct sockaddr_in addr;
81  char buf[32u]; /* large enough to hold an IP address */
82  int status, ret = -1;
83 
84  pStr = envGetConfigParamPtr (pEnv);
85  if (!pStr) {
86  return ret;
87  }
88 
89  while ( ( pToken = getToken (&pStr, buf, sizeof (buf) ) ) ) {
90  status = aToIPAddr ( pToken, port, &addr );
91  if (status<0) {
92  fprintf ( stderr, "%s: Parsing '%s'\n", __FILE__, pEnv->name);
93  fprintf ( stderr, "\tBad internet address or host name: '%s'\n", pToken);
94  continue;
95  }
96 
97  if ( ignoreNonDefaultPort && ntohs ( addr.sin_port ) != port ) {
98  continue;
99  }
100 
101  pNewNode = (osiSockAddrNode *) calloc (1, sizeof(*pNewNode));
102  if (pNewNode==NULL) {
103  fprintf ( stderr, "addAddrToChannelAccessAddressList(): no memory available for configuration\n");
104  break;
105  }
106 
107  pNewNode->addr.ia = addr;
108 
109  /*
110  * LOCK applied externally
111  */
112  ellAdd (pList, &pNewNode->node);
113  ret = 0; /* success if anything is added to the list */
114  }
115 
116  return ret;
117 }
118 
119 /*
120  * removeDuplicateAddresses ()
121  */
122 extern "C" void epicsStdCall removeDuplicateAddresses
123  ( ELLLIST *pDestList, ELLLIST *pSrcList, int silent )
124 {
125  ELLNODE *pRawNode;
126 
127  while ( (pRawNode = ellGet ( pSrcList ) ) ) {
128  STATIC_ASSERT ( offsetof (osiSockAddrNode, node) == 0 );
129  osiSockAddrNode *pNode = reinterpret_cast <osiSockAddrNode *> ( pRawNode );
130  osiSockAddrNode *pTmpNode;
131 
132  if ( pNode->addr.sa.sa_family == AF_INET ) {
133 
134  pTmpNode = (osiSockAddrNode *) ellFirst (pDestList);
135  while ( pTmpNode ) {
136  if (pTmpNode->addr.sa.sa_family == AF_INET) {
137  if ( pNode->addr.ia.sin_addr.s_addr == pTmpNode->addr.ia.sin_addr.s_addr &&
138  pNode->addr.ia.sin_port == pTmpNode->addr.ia.sin_port ) {
139  if ( ! silent ) {
140  char buf[64];
141  ipAddrToDottedIP ( &pNode->addr.ia, buf, sizeof (buf) );
142  fprintf ( stderr,
143  "Warning: Duplicate EPICS CA Address list entry \"%s\" discarded\n", buf );
144  }
145  free (pNode);
146  pNode = NULL;
147  break;
148  }
149  }
150  pTmpNode = (osiSockAddrNode *) ellNext (&pTmpNode->node);
151  }
152  if (pNode) {
153  ellAdd (pDestList, &pNode->node);
154  }
155  }
156  else {
157  ellAdd (pDestList, &pNode->node);
158  }
159  }
160 }
161 
162 /*
163  * forcePort ()
164  */
165 static void forcePort ( ELLLIST *pList, unsigned short port )
166 {
167  osiSockAddrNode *pNode;
168 
169  pNode = ( osiSockAddrNode * ) ellFirst ( pList );
170  while ( pNode ) {
171  if ( pNode->addr.sa.sa_family == AF_INET ) {
172  pNode->addr.ia.sin_port = htons ( port );
173  }
174  pNode = ( osiSockAddrNode * ) ellNext ( &pNode->node );
175  }
176 }
177 
178 
179 /*
180  * configureChannelAccessAddressList ()
181  */
182 extern "C" void epicsStdCall configureChannelAccessAddressList
183  ( ELLLIST *pList, SOCKET sock, unsigned short port )
184 {
185  ELLLIST tmpList;
186  char *pstr;
187  char yesno[32u];
188  int yes;
189 
190  /*
191  * dont load the list twice
192  */
193  assert ( ellCount (pList) == 0 );
194 
195  ellInit ( &tmpList );
196 
197  /*
198  * Check to see if the user has disabled
199  * initializing the search b-cast list
200  * from the interfaces found.
201  */
202  yes = true;
204  sizeof (yesno), yesno );
205  if ( pstr ) {
206  if ( strstr ( pstr, "no" ) || strstr ( pstr, "NO" ) ) {
207  yes = false;
208  }
209  }
210 
211  /*
212  * LOCK is for piiu->destAddr list
213  * (lock outside because this is used by the server also)
214  */
215  if (yes) {
216  ELLLIST bcastList;
217  osiSockAddr addr;
218  ellInit ( &bcastList );
219  addr.ia.sin_family = AF_UNSPEC;
220  osiSockDiscoverBroadcastAddresses ( &bcastList, sock, &addr );
221  forcePort ( &bcastList, port );
222  removeDuplicateAddresses ( &tmpList, &bcastList, 1 );
223  if ( ellCount ( &tmpList ) == 0 ) {
224  osiSockAddrNode *pNewNode;
225  pNewNode = (osiSockAddrNode *) calloc ( 1, sizeof (*pNewNode) );
226  if ( pNewNode ) {
227  /*
228  * if no interfaces found then look for local channels
229  * with the loop back interface
230  */
231  pNewNode->addr.ia.sin_family = AF_INET;
232  pNewNode->addr.ia.sin_addr.s_addr = htonl ( INADDR_LOOPBACK );
233  pNewNode->addr.ia.sin_port = htons ( port );
234  ellAdd ( &tmpList, &pNewNode->node );
235  }
236  else {
237  errlogPrintf ( "configureChannelAccessAddressList(): no memory available for configuration\n" );
238  }
239  }
240  }
241  addAddrToChannelAccessAddressList ( &tmpList, &EPICS_CA_ADDR_LIST, port, false );
242 
243  removeDuplicateAddresses ( pList, &tmpList, 0 );
244 }
245 
246 
247 /*
248  * printChannelAccessAddressList ()
249  */
250 extern "C" void epicsStdCall printChannelAccessAddressList ( const ELLLIST *pList )
251 {
252  osiSockAddrNode *pNode;
253 
254  ::printf ( "Channel Access Address List\n" );
255  pNode = (osiSockAddrNode *) ellFirst ( pList );
256  while (pNode) {
257  char buf[64];
258  ipAddrToA ( &pNode->addr.ia, buf, sizeof ( buf ) );
259  ::printf ( "%s\n", buf );
260  pNode = (osiSockAddrNode *) ellNext ( &pNode->node );
261  }
262 }
LIBCOM_API void epicsStdCall osiSockDiscoverBroadcastAddresses(ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
Definition: osdNetIntf.c:68
#define INADDR_LOOPBACK
Definition: osdSock.h:76
LIBCOM_API int epicsStdCall aToIPAddr(const char *pAddrString, unsigned short defaultPort, struct sockaddr_in *pIP)
Definition: aToIPAddr.c:78
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
osiSockAddr addr
Definition: osiSock.h:163
pvd::Status status
An EPICS-specific replacement for ANSI C&#39;s assert.
void epicsStdCall configureChannelAccessAddressList(ELLLIST *pList, SOCKET sock, unsigned short port)
Definition: iocinf.cpp:183
char * name
Name of the parameter.
Definition: envDefs.h:42
int i
Definition: scan.c:967
LIBCOM_API const char *epicsStdCall envGetConfigParamPtr(const ENV_PARAM *pParam)
Get a configuration parameter&#39;s value or default string.
Definition: envSubr.c:81
struct sockaddr sa
Definition: osiSock.h:158
struct sockaddr_in ia
Definition: osiSock.h:157
void epicsStdCall printChannelAccessAddressList(const ELLLIST *pList)
Definition: iocinf.cpp:250
Routines to get and set EPICS environment parameters.
#define printf
Definition: epicsStdio.h:41
ELLNODE * ellGet(ELLLIST *pList)
Deletes and returns the first node from a list.
Definition: ellLib.c:147
#define NULL
Definition: catime.c:38
A structure to hold a single environment parameter.
Definition: envDefs.h:41
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
#define STATIC_ASSERT(expr)
Declare a condition that should be true at compile-time.
Definition: epicsAssert.h:86
int SOCKET
Definition: osdSock.h:31
LIBCOM_API const ENV_PARAM EPICS_CA_ADDR_LIST
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
List node type.
Definition: ellLib.h:45
ELLNODE node
Definition: osiSock.h:162
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
unsigned epicsStdCall ipAddrToA(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)
Definition: osiSock.c:92
int epicsStdCall addAddrToChannelAccessAddressList(ELLLIST *pList, const ENV_PARAM *pEnv, unsigned short port, int ignoreNonDefaultPort)
Definition: iocinf.cpp:74
void epicsStdCall removeDuplicateAddresses(ELLLIST *pDestList, ELLLIST *pSrcList, int silent)
Definition: iocinf.cpp:123
#define stderr
Definition: epicsStdio.h:32
List header type.
Definition: ellLib.h:56
LIBCOM_API char *epicsStdCall envGetConfigParam(const ENV_PARAM *pParam, int bufDim, char *pBuf)
Get value of a configuration parameter.
Definition: envSubr.c:139
LIBCOM_API const ENV_PARAM EPICS_CA_AUTO_ADDR_LIST
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)
Definition: osiSock.c:144
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89