/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include #include #include #include #include #include #include #ifdef SOLARIS #include #endif #include "osl/util.h" /*****************************************************************************/ /* Static Module Functions */ /*****************************************************************************/ static int osl_getHWAddr(const char *ifname, char* hard_addr); static int osl_checkAddr(const char* addr); /*****************************************************************************/ /* osl_getEthernetAddress */ /*****************************************************************************/ sal_Bool SAL_CALL osl_getEthernetAddress( sal_uInt8 * pAddr ) { char buff[1024]; char hard_addr[64]; struct ifconf ifc; struct ifreq *ifr; int i; int so; #ifdef SOLARIS /** algorithm doesn't work on solaris */ return sal_False; #else if ( pAddr == NULL ) { return sal_False; } /* * All we need is ... a network file descriptor. * Normally, this is a very socket. */ so = socket(AF_INET, SOCK_DGRAM, 0); /* * The first thing we have to do, get the interface configuration. * It is a list of attached/configured interfaces */ ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if ( ioctl(so, SIOCGIFCONF, &ifc) < 0 ) { /* fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));*/ close(so); return sal_False; } close(so); /* * For each of the interfaces in the interface list, * try to get the hardware address */ ifr = ifc.ifc_req; for ( i = ifc.ifc_len / sizeof(struct ifreq) ; --i >= 0 ; ifr++ ) { int nRet=0; nRet = osl_getHWAddr(ifr->ifr_name,hard_addr); if ( nRet > 0 ) { memcpy( pAddr , hard_addr, 6 ); return sal_True; } } return sal_False; #endif } /*****************************************************************************/ /* osl_getHWAddr */ /*****************************************************************************/ static int osl_getHWAddr(const char *ifname, char* hard_addr) { int ret=0; struct ifreq ifr; int so = socket(AF_INET, SOCK_DGRAM, 0); strcpy(ifr.ifr_name, ifname); /* * First, get the Interface-FLAGS */ ret=ioctl(so, SIOCGIFFLAGS, &ifr) ; if ( ret < 0 ) { /* fprintf(stderr, "SIOCGIFFLAGS: %s\n", strerror(errno)); */ close(so); return ret; } /* * If it is the loopback device, do not consider it any further */ if (ifr.ifr_flags & IFF_LOOPBACK) { /* fprintf(stderr, "SIOCGIFFLAGS : is LOOPBACK : %s\n", strerror(errno));*/ close(so); return 0; } /* * And now, the real thing: the get address */ #if defined(SIOCGIFHWADDR) && !defined(SOLARIS) ret=ioctl(so, SIOCGIFHWADDR, &ifr); #else ret=ioctl(so, SIOCGIFADDR, &ifr); #endif if (ret < 0) { /* fprintf(stderr, "SIOCGIFADDR: %s\n", strerror(errno));*/ memset(hard_addr, 0, 32); close(so); return ret; } close(so); #if defined(SIOCGIFHWADDR) && !defined(SOLARIS) memcpy(hard_addr,ifr.ifr_hwaddr.sa_data,8); #else memcpy(hard_addr,ifr.ifr_ifru.ifru_addr.sa_data,8); #endif /* * Check, if no real, i.e. 00:00:00:00:00:00, address was retrieved. * The Linux dummy device has this kind of behaviour */ ret=osl_checkAddr(hard_addr); if (ret < 0) { /* fprintf(stderr, "SIOCGIFADDR got '00:00:00:00:00:00'\n"); */ return ret; } /* fprintf(stderr,"interface : %s -- ",ifname);*/ /* fprintf(stderr,"HWaddr : %s\n", print_ether(hard_addr));*/ return 1; } /*****************************************************************************/ /* osl_checkAddr */ /*****************************************************************************/ static int osl_checkAddr(const char* addr) { if (addr[0]==0 && addr[1]==0 && addr[2]==0 && addr[3]==0 && addr[4]==0 && addr[5]==0) { return -1; } return 0; } #if defined (SPARC) #if defined (SOLARIS) && !defined(__sparcv8plus) && !defined(__sparcv9) #include #include /*****************************************************************************/ /* osl_InitSparcV9 */ /*****************************************************************************/ void osl_InterlockedCountSetV9(sal_Bool bV9); /* * osl_InitSparcV9() should be executed as early as possible. We place it in the * .init section of sal */ #if defined ( __SUNPRO_C ) || defined ( __SUNPRO_CC ) void osl_InitSparcV9(void); #pragma init (osl_InitSparcV9) #elif defined ( __GNUC__ ) void osl_InitSparcV9(void) __attribute__((constructor)); #endif void osl_InitSparcV9(void) { /* processor_info() identifies SPARCV8 (ie sun4c machines) simply as "sparc" * and SPARCV9 (ie ultra sparcs, sun4u) as "sparcv9". Since we know that we * run at least on a SPARCV8 architecture or better, any processor type != "sparc" * and != "i386" is considered to be SPARCV9 or better * * This way we are certain that this will still work if someone names SPARCV10 * "foobar" */ processor_info_t aInfo; int rc; rc = processor_info(0, &aInfo); if ( rc != -1 ) { if ( !strcmp( "sparc", aInfo.pi_processor_type ) /* SPARCV8 */ || !strcmp( "i386", aInfo.pi_processor_type ) ) /* can't happen, but ... */ return; /* we are reasonably certain to be on sparcv9/sparcv8plus or better */ osl_InterlockedCountSetV9(sal_True); } } #endif /* SOLARIS */ #if defined(NETBSD) && defined(GCC) && !defined(__sparcv9) && !defined(__sparc_v9__) #include #include void osl_InitSparcV9(void) __attribute__((constructor)); void osl_InterlockedCountSetV9(sal_Bool bV9); /* Determine which processor we are running on (sparc v8 or v9) * The approach is very similar to Solaris. */ void osl_InitSparcV9(void) { int mib[2]={CTL_HW,HW_MACHINE}; char processorname[256]; size_t len=256; /* get the machine name */ sysctl(mib, 2, processorname, &len, NULL, 0); if (!strncmp("sparc64",processorname, len)) { osl_InterlockedCountSetV9(sal_True); } } #endif /* NETBSD */ #endif /* SPARC */ #if defined ( LINUX ) && defined ( SPARC ) #include void osl_InitSparcV9(void) __attribute__((constructor)); void osl_InterlockedCountSetV9(sal_Bool bV9); /* Determine which processor we are running on (sparc v8 or v9) * The approach is very similar to Solaris. */ void osl_InitSparcV9(void) { struct utsname name; int rc; rc = uname(&name); if ( rc != -1 ) { if ( !strcmp( "sparc", name.machine )) return; osl_InterlockedCountSetV9(sal_True); } } #endif #if ( defined(__GNUC__) && (defined(X86) || defined(X86_64)) )\ || ( defined(SOLARIS) && defined(__i386) ) /* Safe default */ int osl_isSingleCPU = 0; /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system * * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount() * comes with a cost and is especially expensive on pre HT x86 single processor * systems, where it isn't needed at all. * * This should be run as early as possible, thus it's placed in the init section */ #if defined(_SC_NPROCESSORS_CONF) /* i.e. MACOSX for Intel doesn't have this */ #if defined(__GNUC__) void osl_interlockedCountCheckForSingleCPU(void) __attribute__((constructor)); #elif defined(__SUNPRO_C) void osl_interlockedCountCheckForSingleCPU(void); #pragma init (osl_interlockedCountCheckForSingleCPU) #endif void osl_interlockedCountCheckForSingleCPU(void) { /* In case sysconfig fails be on the safe side, * consider it a multiprocessor/multicore/HT system */ if ( sysconf(_SC_NPROCESSORS_CONF) == 1 ) { osl_isSingleCPU = 1; } } #endif /* defined(_SC_NPROCESSORS_CONF) */ #endif