27 # define ifDepenDebugPrintf(argsInParen) printf argsInParen 29 # define ifDepenDebugPrintf(argsInParen) 40 static size_t ifreqSize (
struct ifreq *pifreq )
45 if ( size <
sizeof ( *pifreq ) ) {
46 size =
sizeof ( *pifreq );
54 static struct ifreq * ifreqNext (
struct ifreq *pifreq )
58 ifr = (
struct ifreq * )( ifreqSize (pifreq) + (
char * ) pifreq );
59 ifDepenDebugPrintf( (
"ifreqNext() pifreq %p, size 0x%x, ifr 0x%p\n", pifreq, (
unsigned)ifreqSize (pifreq), ifr) );
70 static const unsigned nelem = 100;
73 struct ifreq *pIfreqList;
74 struct ifreq *pIfreqListEnd;
76 struct ifreq *pnextifreq;
79 if ( pMatchAddr->
sa.sa_family == AF_INET ) {
82 if ( pNewNode ==
NULL ) {
83 errlogPrintf (
"osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
86 pNewNode->
addr.
ia.sin_family = AF_INET;
87 pNewNode->
addr.
ia.sin_port = htons ( 0 );
100 pIfreqList = (
struct ifreq *) calloc ( nelem,
sizeof(*pifreq) );
102 errlogPrintf (
"osiSockDiscoverBroadcastAddresses(): no memory to complete request\n");
106 ifconf.ifc_len = nelem *
sizeof(*pifreq);
107 ifconf.ifc_req = pIfreqList;
109 if (status < 0 || ifconf.ifc_len == 0) {
110 errlogPrintf (
"osiSockDiscoverBroadcastAddresses(): unable to fetch network interface configuration (%d)\n", status);
115 pIfreqListEnd = (
struct ifreq *) (ifconf.ifc_len + (
char *) pIfreqList);
118 for ( pifreq = pIfreqList; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
119 uint32_t current_ifreqsize;
124 pnextifreq = ifreqNext (pifreq);
127 current_ifreqsize = ifreqSize ( pifreq );
129 memmove(pIfreqList, pifreq, current_ifreqsize);
131 ifDepenDebugPrintf ((
"osiSockDiscoverBroadcastAddresses(): found IFACE: %s len: 0x%x current_ifreqsize: 0x%x \n",
132 pIfreqList->ifr_name,
134 (
unsigned)current_ifreqsize));
139 if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
140 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): interface \"%s\" was not AF_INET\n", pIfreqList->ifr_name) );
148 if ( pMatchAddr->
sa.sa_family != AF_UNSPEC ) {
149 if ( pMatchAddr->
sa.sa_family != AF_INET ) {
152 if ( pMatchAddr->
ia.sin_addr.s_addr != htonl (INADDR_ANY) ) {
153 struct sockaddr_in *pInetAddr = (
struct sockaddr_in *) &pIfreqList->ifr_addr;
154 if ( pInetAddr->sin_addr.s_addr != pMatchAddr->
ia.sin_addr.s_addr ) {
155 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): net intf \"%s\" didnt match\n", pIfreqList->ifr_name) );
161 status =
socket_ioctl ( socket, SIOCGIFFLAGS, pIfreqList );
163 errlogPrintf (
"osiSockDiscoverBroadcastAddresses(): net intf flags fetch for \"%s\" failed\n", pIfreqList->ifr_name);
166 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): net intf \"%s\" flags: %x\n", pIfreqList->ifr_name, pIfreqList->ifr_flags) );
171 if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
172 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): net intf \"%s\" was down\n", pIfreqList->ifr_name) );
179 if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
180 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): ignoring loopback interface: \"%s\"\n", pIfreqList->ifr_name) );
185 if ( pNewNode ==
NULL ) {
186 errlogPrintf (
"osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
201 if ( pIfreqList->ifr_flags & IFF_BROADCAST ) {
203 status =
socket_ioctl (socket, SIOCGIFBRDADDR, pIfreqList);
205 errlogPrintf (
"osiSockDiscoverBroadcastAddresses(): net intf \"%s\": bcast addr fetch fail\n", pIfreqList->ifr_name);
209 baddr.
sa = pIfreqList->ifr_broadaddr;
210 if (baddr.
ia.sin_family==AF_INET && baddr.
ia.sin_addr.s_addr != INADDR_ANY) {
211 pNewNode->
addr.
sa = pIfreqList->ifr_broadaddr;
219 #if defined (IFF_POINTOPOINT) 220 else if ( pIfreqList->ifr_flags & IFF_POINTOPOINT ) {
221 status =
socket_ioctl ( socket, SIOCGIFDSTADDR, pIfreqList);
223 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): net intf \"%s\": pt to pt addr fetch fail\n", pIfreqList->ifr_name) );
227 pNewNode->
addr.
sa = pIfreqList->ifr_dstaddr;
231 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): net intf \"%s\": not point to point or bcast?\n", pIfreqList->ifr_name ) );
236 ifDepenDebugPrintf ( (
"osiSockDiscoverBroadcastAddresses(): net intf \"%s\" found\n", pIfreqList->ifr_name) );
250 static void osiLocalAddrOnce (
void *raw)
253 const unsigned nelem = 100;
256 struct ifconf ifconf;
257 struct ifreq *pIfreqList;
258 struct ifreq *pifreq;
259 struct ifreq *pIfreqListEnd;
260 struct ifreq *pnextifreq;
262 memset ( (
void *) &addr,
'\0',
sizeof ( addr ) );
263 addr.
sa.sa_family = AF_UNSPEC;
265 pIfreqList = (
struct ifreq *) calloc ( nelem,
sizeof(*pIfreqList) );
266 if ( ! pIfreqList ) {
267 errlogPrintf (
"osiLocalAddr(): no memory to complete request\n" );
271 ifconf.ifc_len = nelem *
sizeof ( *pIfreqList );
272 ifconf.ifc_req = pIfreqList;
273 status =
socket_ioctl ( *psocket, SIOCGIFCONF, &ifconf );
274 if ( status < 0 || ifconf.ifc_len == 0 ) {
277 sockErrBuf,
sizeof ( sockErrBuf ) );
279 "osiLocalAddr(): SIOCGIFCONF ioctl failed because \"%s\"\n",
284 pIfreqListEnd = (
struct ifreq *) ( ifconf.ifc_len + (
char *) ifconf.ifc_req );
287 for ( pifreq = ifconf.ifc_req; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
289 uint32_t current_ifreqsize;
294 pnextifreq = ifreqNext ( pifreq );
297 current_ifreqsize = ifreqSize ( pifreq );
299 memmove(pIfreqList, pifreq, current_ifreqsize);
301 if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
302 ifDepenDebugPrintf ( (
"osiLocalAddr(): interface %s was not AF_INET\n", pIfreqList->ifr_name) );
306 addrCpy.
sa = pIfreqList->ifr_addr;
308 status =
socket_ioctl ( *psocket, SIOCGIFFLAGS, pIfreqList );
310 errlogPrintf (
"osiLocalAddr(): net intf flags fetch for %s failed\n", pIfreqList->ifr_name );
314 if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
315 ifDepenDebugPrintf ( (
"osiLocalAddr(): net intf %s was down\n", pIfreqList->ifr_name) );
322 if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
323 ifDepenDebugPrintf ( (
"osiLocalAddr(): ignoring loopback interface: %s\n", pIfreqList->ifr_name) );
329 osiLocalAddrResult = addrCpy;
335 "osiLocalAddr(): only loopback found\n");
338 memset ( (
void *) &addr,
'\0',
sizeof ( addr ) );
339 addr.
ia.sin_family = AF_INET;
341 osiLocalAddrResult = addr;
350 return osiLocalAddrResult;
LIBCOM_API void epicsStdCall osiSockDiscoverBroadcastAddresses(ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
An EPICS-specific replacement for ANSI C's assert.
#define ifDepenDebugPrintf(argsInParen)
#define ifreq_size(pifreq)
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
#define socket_ioctl(A, B, C)
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
LIBCOM_API osiSockAddr epicsStdCall osiLocalAddr(SOCKET socket)
#define EPICS_THREAD_ONCE_INIT
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
int errlogPrintf(const char *pFormat,...)
C++ and C descriptions for a thread.