From c542b4f4d122099b9d03cc789876312d75e3855f Mon Sep 17 00:00:00 2001 From: "Janet B. Anderson" Date: Wed, 1 Mar 2006 19:44:55 +0000 Subject: [PATCH] Initial version. --- src/libCom/osi/os/interix/osdNetIntf.c | 310 ++++++++++++++++++++++++ src/libCom/osi/os/interix/osdSock.h | 147 +++++++++++ src/libCom/osi/os/interix/osdThread.h | 27 +++ src/libCom/osi/os/interix/osiFileName.h | 21 ++ 4 files changed, 505 insertions(+) create mode 100644 src/libCom/osi/os/interix/osdNetIntf.c create mode 100644 src/libCom/osi/os/interix/osdSock.h create mode 100644 src/libCom/osi/os/interix/osdThread.h create mode 100644 src/libCom/osi/os/interix/osiFileName.h diff --git a/src/libCom/osi/os/interix/osdNetIntf.c b/src/libCom/osi/os/interix/osdNetIntf.c new file mode 100644 index 000000000..3ea38322f --- /dev/null +++ b/src/libCom/osi/os/interix/osdNetIntf.c @@ -0,0 +1,310 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* $Id$ */ +/* + * Author: Jeff Hill + * Date: 04-05-94 + */ + +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "osiSock.h" +#include "epicsAssert.h" +#include "errlog.h" + +#ifdef DEBUG +# define ifDepenDebugPrintf(argsInParen) printf argsInParen +#else +# define ifDepenDebugPrintf(argsInParen) +#endif + +#define ifreq_size(pifreq) IFNAMSIZ + +#define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ +#define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ +#define SIOCGIFFLAGS 0x8913 /* get flags */ +#define SIOCGIFCONF 0x8912 /* get iface list */ + +/* + * Move to the next ifreq structure + * Made difficult by the fact that addresses larger than the structure + * size may be returned from the kernel. + */ +static struct ifreq * ifreqNext ( struct ifreq *pifreq ) +{ + size_t size; + + size = ifreq_size ( pifreq ); + if ( size < sizeof ( *pifreq ) ) { + size = sizeof ( *pifreq ); + } + + return ( struct ifreq * )( size + ( char * ) pifreq ); +} + + +/* + * osiSockDiscoverBroadcastAddresses () + */ +epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses + (ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr) +{ + static const unsigned nelem = 100; + int status; + struct ifconf ifconf; + struct ifreq *pIfreqList; + struct ifreq *pIfreqListEnd; + struct ifreq *pifreq; + struct ifreq *pnextifreq; + osiSockAddrNode *pNewNode; + + if ( pMatchAddr->sa.sa_family == AF_INET ) { + if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) { + pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) ); + if ( pNewNode == NULL ) { + errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" ); + return; + } + pNewNode->addr.ia.sin_family = AF_INET; + pNewNode->addr.ia.sin_port = 0u; + pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + ellAdd ( pList, &pNewNode->node ); + return; + } + } + + /* + * use pool so that we avoid using too much stack space + * + * nelem is set to the maximum interfaces + * on one machine here + */ + pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pifreq) ); + if (!pIfreqList) { + errlogPrintf ("osiSockDiscoverBroadcastAddresses(): no memory to complete request\n"); + return; + } + + ifconf.ifc_len = nelem * sizeof(*pifreq); + ifconf.ifc_req = pIfreqList; + status = socket_ioctl (socket, SIOCGIFCONF, &ifconf); + if (status < 0 || ifconf.ifc_len == 0) { + errlogPrintf ("osiSockDiscoverBroadcastAddresses(): unable to fetch network interface configuration\n"); + free (pIfreqList); + return; + } + + pIfreqListEnd = (struct ifreq *) (ifconf.ifc_len + (char *) pIfreqList); + pIfreqListEnd--; + + for ( pifreq = pIfreqList; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) { + + /* + * find the next if req + */ + pnextifreq = ifreqNext (pifreq); + + /* + * If its not an internet interface then dont use it + */ + if ( pifreq->ifr_addr.sa_family != AF_INET ) { + ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): interface \"%s\" was not AF_INET\n", pifreq->ifr_name) ); + continue; + } + + /* + * if it isnt a wildcarded interface then look for + * an exact match + */ + if ( pMatchAddr->sa.sa_family != AF_UNSPEC ) { + if ( pMatchAddr->sa.sa_family != AF_INET ) { + continue; + } + if ( pMatchAddr->ia.sin_addr.s_addr != htonl (INADDR_ANY) ) { + struct sockaddr_in *pInetAddr = (struct sockaddr_in *) &pifreq->ifr_addr; + if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) { + ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" didnt match\n", pifreq->ifr_name) ); + continue; + } + } + } + + status = socket_ioctl ( socket, SIOCGIFFLAGS, pifreq ); + if ( status ) { + errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf flags fetch for \"%s\" failed\n", pifreq->ifr_name); + continue; + } + + /* + * dont bother with interfaces that have been disabled + */ + if ( ! ( pifreq->ifr_flags & IFF_UP ) ) { + ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" was down\n", pifreq->ifr_name) ); + continue; + } + + /* + * dont use the loop back interface + */ + if ( pifreq->ifr_flags & IFF_LOOPBACK ) { + ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): ignoring loopback interface: \"%s\"\n", pifreq->ifr_name) ); + continue; + } + + pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) ); + if ( pNewNode == NULL ) { + errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" ); + free ( pIfreqList ); + return; + } + + /* + * If this is an interface that supports + * broadcast fetch the broadcast address. + * + * Otherwise if this is a point to point + * interface then use the destination address. + * + * Otherwise CA will not query through the + * interface. + */ + if ( pifreq->ifr_flags & IFF_BROADCAST ) { + status = socket_ioctl (socket, SIOCGIFBRDADDR, pifreq); + if ( status ) { + errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": bcast addr fetch fail\n", pifreq->ifr_name); + free ( pNewNode ); + continue; + } + pNewNode->addr.sa = pifreq->ifr_broadaddr; + ifDepenDebugPrintf ( ( "found broadcast addr = %x\n", ntohl ( pNewNode->addr.ia.sin_addr.s_addr ) ) ); + } +#if defined (IFF_POINTOPOINT) + else if ( pifreq->ifr_flags & IFF_POINTOPOINT ) { + status = socket_ioctl ( socket, SIOCGIFDSTADDR, pifreq); + if ( status ) { + ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": pt to pt addr fetch fail\n", pifreq->ifr_name) ); + free ( pNewNode ); + continue; + } + pNewNode->addr.sa = pifreq->ifr_dstaddr; + } +#endif + else { + ifDepenDebugPrintf ( ( "osiSockDiscoverBroadcastAddresses(): net intf \"%s\": not point to point or bcast?\n", pifreq->ifr_name ) ); + free ( pNewNode ); + continue; + } + + ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" found\n", pifreq->ifr_name) ); + + /* + * LOCK applied externally + */ + ellAdd ( pList, &pNewNode->node ); + } + + free ( pIfreqList ); +} + +/* + * osiLocalAddr () + */ +epicsShareFunc osiSockAddr epicsShareAPI osiLocalAddr (SOCKET socket) +{ + static const unsigned nelem = 100; + static char init = 0; + static osiSockAddr addr; + int status; + struct ifconf ifconf; + struct ifreq *pIfreqList; + struct ifreq *pifreq; + struct ifreq *pIfreqListEnd; + struct ifreq *pnextifreq; + + if ( init ) { + return addr; + } + + memset ( (void *) &addr, '\0', sizeof ( addr ) ); + addr.sa.sa_family = AF_UNSPEC; + + pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pIfreqList) ); + if ( ! pIfreqList ) { + errlogPrintf ( "osiLocalAddr(): no memory to complete request\n" ); + return addr; + } + + ifconf.ifc_len = nelem * sizeof ( *pIfreqList ); + ifconf.ifc_req = pIfreqList; + status = socket_ioctl ( socket, SIOCGIFCONF, &ifconf ); + if ( status < 0 || ifconf.ifc_len == 0 ) { + char sockErrBuf[64]; + epicsSocketConvertErrnoToString ( + sockErrBuf, sizeof ( sockErrBuf ) ); + errlogPrintf ( + "osiLocalAddr(): SIOCGIFCONF ioctl failed because \"%s\"\n", + sockErrBuf ); + free ( pIfreqList ); + return addr; + } + + pIfreqListEnd = (struct ifreq *) ( ifconf.ifc_len + (char *) ifconf.ifc_req ); + pIfreqListEnd--; + + for ( pifreq = ifconf.ifc_req; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) { + osiSockAddr addrCpy; + + /* + * find the next if req + */ + pnextifreq = ifreqNext ( pifreq ); + + if ( pifreq->ifr_addr.sa_family != AF_INET ) { + ifDepenDebugPrintf ( ("osiLocalAddr(): interface %s was not AF_INET\n", pifreq->ifr_name) ); + continue; + } + + addrCpy.sa = pifreq->ifr_addr; + + status = socket_ioctl ( socket, SIOCGIFFLAGS, pifreq ); + if ( status < 0 ) { + errlogPrintf ( "osiLocalAddr(): net intf flags fetch for %s failed\n", pifreq->ifr_name ); + continue; + } + + if ( ! ( pifreq->ifr_flags & IFF_UP ) ) { + ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s was down\n", pifreq->ifr_name) ); + continue; + } + + /* + * dont use the loop back interface + */ + if ( pifreq->ifr_flags & IFF_LOOPBACK ) { + ifDepenDebugPrintf ( ("osiLocalAddr(): ignoring loopback interface: %s\n", pifreq->ifr_name) ); + continue; + } + + ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s found\n", pifreq->ifr_name) ); + + init = 1; + addr = addrCpy; + break; + } + + free ( pIfreqList ); + return addr; +} + diff --git a/src/libCom/osi/os/interix/osdSock.h b/src/libCom/osi/os/interix/osdSock.h new file mode 100644 index 000000000..52a2cb00d --- /dev/null +++ b/src/libCom/osi/os/interix/osdSock.h @@ -0,0 +1,147 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Interix specific socket include + */ + +#ifndef osdSockH +#define osdSockH + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* gethosthname,close() and others */ + +#if 0 +#include +#include /* for MAXHOSTNAMELEN */ +#endif + +#ifdef __cplusplus +} +#endif + +typedef int SOCKET; +#if defined ( _SOCKLEN_T ) + typedef uint32_t osiSocklen_t; +#else + typedef int osiSocklen_t; +#endif +#define SOCKERRNO errno +#define INVALID_SOCKET (-1) +typedef int osiSockIoctl_t; +#define socket_ioctl(A,B,C) ioctl(A,B,C) + +#define FD_IN_FDSET(FD) ((FD)=0) + +#define DOES_NOT_ACCEPT_ZERO_LENGTH_UDP + +#define SOCK_EWOULDBLOCK EWOULDBLOCK +#define SOCK_ENOBUFS ENOBUFS +#define SOCK_ECONNRESET ECONNRESET +#define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EADDRINUSE EADDRINUSE +#define SOCK_ECONNREFUSED ECONNREFUSED +#define SOCK_ECONNABORTED ECONNABORTED +#define SOCK_EINPROGRESS EINPROGRESS +#define SOCK_EISCONN EISCONN +#define SOCK_EALREADY EALREADY +#define SOCK_EINTR EINTR +#define SOCK_EINVAL EINVAL +#define SOCK_EPIPE EPIPE +#define SOCK_EMFILE EMFILE +#define SOCK_SHUTDOWN ESHUTDOWN +#define SOCK_ENOTSOCK ENOTSOCK +#define SOCK_EBADF EBADF + + +#define IFF_UP 0x1 /* interface is up */ +#define IFF_BROADCAST 0x2 /* broadcast address valid */ +#define IFF_LOOPBACK 0x8 /* is a loopback net */ +#define IFF_POINTOPOINT 0x10 /* interface is point to point */ + +/* + * Interface request structure used for socket + * ioctl's. All interface ioctl's must have parameter + * definitions which begin with ifr_name. The + * remainder may be interface specific. + */ +struct ifreq { +#define IFNAMSIZ 16 + char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + caddr_t ifru_data; + } ifr_ifru; +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_data ifr_ifru.ifru_data /* for use by interface */ +}; + +/* Structure used in SIOCGIFCONF request. + * Used to retrieve interface configuration + * for machine (useful for programs which + * must know all networks accessible). + */ +struct ifconf { + int ifc_len; /* size of associated buffer */ + union { + caddr_t ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; +#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ +#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ +}; + +#ifndef NBBY +#define NBBY 8 +#endif + +#ifndef FD_SETSIZE +#define FD_SETSIZE 256 +#endif + +#define NFDBITS (sizeof (fd_mask) * NBBY ) /* bits per mask */ +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif + +#define TWOPOWER32 4294967296.0 +#define TWOPOWER31 2147483648.0 +#define UNIX_EPOCH_AS_MJD 40587.0 + +#define INVALID_SOCKET (-1) +#define INADDR_LOOPBACK ((u_long)0x7f000001) + +#ifndef INADDR_NONE +# define INADDR_NONE (0xffffffff) +#endif + + +#endif /*osdSockH*/ + diff --git a/src/libCom/osi/os/interix/osdThread.h b/src/libCom/osi/os/interix/osdThread.h new file mode 100644 index 000000000..b7b162432 --- /dev/null +++ b/src/libCom/osi/os/interix/osdThread.h @@ -0,0 +1,27 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +#ifndef osdThreadh +#define osdThreadh + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define nanosleep(x, y) usleep( ((x)->tv_sec)*1000000 + ((y)->tv_nsec)/1000 ) + +pthread_t epicsThreadGetPosixThreadId ( epicsThreadId id ); + +#ifdef __cplusplus +} +#endif + +#endif /* osdThreadh */ diff --git a/src/libCom/osi/os/interix/osiFileName.h b/src/libCom/osi/os/interix/osiFileName.h new file mode 100644 index 000000000..b79203992 --- /dev/null +++ b/src/libCom/osi/os/interix/osiFileName.h @@ -0,0 +1,21 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * osiFileName.h + * Author: Jeff Hill + * + * + */ +#ifndef osiFileNameH +#define osiFileNameH + +#include "unixFileName.h" + +#endif /* osiFileNameH */