| /************************************************************** |
| * |
| * 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 <unistd.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <sys/ioctl.h> |
| #include <sys/socket.h> |
| #include <net/if.h> |
| |
| #ifdef SOLARIS |
| #include <sys/sockio.h> |
| #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 == 0 ) |
| { |
| 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 <sys/types.h> |
| #include <sys/processor.h> |
| |
| /*****************************************************************************/ |
| /* 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 <sys/param.h> |
| #include <sys/sysctl.h> |
| 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 <sys/utsname.h> |
| 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 |