1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 #include <unistd.h> 30 #include <errno.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <sys/ioctl.h> 34 #include <sys/socket.h> 35 #include <net/if.h> 36 37 #ifdef SOLARIS 38 #include <sys/sockio.h> 39 #endif 40 41 #include "osl/util.h" 42 43 44 45 /*****************************************************************************/ 46 /* Static Module Functions */ 47 /*****************************************************************************/ 48 49 static int osl_getHWAddr(const char *ifname, char* hard_addr); 50 static int osl_checkAddr(const char* addr); 51 52 53 /*****************************************************************************/ 54 /* osl_getEthernetAddress */ 55 /*****************************************************************************/ 56 57 sal_Bool SAL_CALL osl_getEthernetAddress( sal_uInt8 * pAddr ) 58 { 59 char buff[1024]; 60 char hard_addr[64]; 61 struct ifconf ifc; 62 struct ifreq *ifr; 63 int i; 64 int so; 65 66 #ifdef SOLARIS 67 /** algorithm doesn't work on solaris */ 68 return sal_False; 69 #else 70 71 if ( pAddr == 0 ) 72 { 73 return sal_False; 74 } 75 76 77 /* 78 * All we need is ... a network file descriptor. 79 * Normally, this is a very socket. 80 */ 81 82 so = socket(AF_INET, SOCK_DGRAM, 0); 83 84 85 /* 86 * The first thing we have to do, get the interface configuration. 87 * It is a list of attached/configured interfaces 88 */ 89 90 ifc.ifc_len = sizeof(buff); 91 ifc.ifc_buf = buff; 92 if ( ioctl(so, SIOCGIFCONF, &ifc) < 0 ) 93 { 94 /* fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));*/ 95 close(so); 96 return sal_False; 97 } 98 99 close(so); 100 101 /* 102 * For each of the interfaces in the interface list, 103 * try to get the hardware address 104 */ 105 106 ifr = ifc.ifc_req; 107 for ( i = ifc.ifc_len / sizeof(struct ifreq) ; --i >= 0 ; ifr++ ) 108 { 109 int nRet=0; 110 nRet = osl_getHWAddr(ifr->ifr_name,hard_addr); 111 if ( nRet > 0 ) 112 { 113 memcpy( pAddr , hard_addr, 6 ); 114 return sal_True; 115 } 116 } 117 118 return sal_False; 119 #endif 120 } 121 122 123 /*****************************************************************************/ 124 /* osl_getHWAddr */ 125 /*****************************************************************************/ 126 127 static int osl_getHWAddr(const char *ifname, char* hard_addr) 128 { 129 int ret=0; 130 struct ifreq ifr; 131 int so = socket(AF_INET, SOCK_DGRAM, 0); 132 133 strcpy(ifr.ifr_name, ifname); 134 135 /* 136 * First, get the Interface-FLAGS 137 */ 138 139 ret=ioctl(so, SIOCGIFFLAGS, &ifr) ; 140 141 if ( ret < 0 ) 142 { 143 /* fprintf(stderr, "SIOCGIFFLAGS: %s\n", strerror(errno)); */ 144 close(so); 145 return ret; 146 } 147 148 149 /* 150 * If it is the loopback device, do not consider it any further 151 */ 152 153 if (ifr.ifr_flags & IFF_LOOPBACK) 154 { 155 /* fprintf(stderr, "SIOCGIFFLAGS : is LOOPBACK : %s\n", strerror(errno));*/ 156 close(so); 157 return 0; 158 } 159 160 161 /* 162 * And now, the real thing: the get address 163 */ 164 165 #if defined(SIOCGIFHWADDR) && !defined(SOLARIS) 166 ret=ioctl(so, SIOCGIFHWADDR, &ifr); 167 #else 168 ret=ioctl(so, SIOCGIFADDR, &ifr); 169 #endif 170 171 if (ret < 0) { 172 /* fprintf(stderr, "SIOCGIFADDR: %s\n", strerror(errno));*/ 173 memset(hard_addr, 0, 32); 174 close(so); 175 return ret; 176 } 177 178 close(so); 179 180 #if defined(SIOCGIFHWADDR) && !defined(SOLARIS) 181 memcpy(hard_addr,ifr.ifr_hwaddr.sa_data,8); 182 #else 183 memcpy(hard_addr,ifr.ifr_ifru.ifru_addr.sa_data,8); 184 #endif 185 186 187 /* 188 * Check, if no real, i.e. 00:00:00:00:00:00, address was retrieved. 189 * The Linux dummy device has this kind of behaviour 190 */ 191 192 ret=osl_checkAddr(hard_addr); 193 194 if (ret < 0) { 195 /* fprintf(stderr, "SIOCGIFADDR got '00:00:00:00:00:00'\n"); */ 196 return ret; 197 } 198 199 /* fprintf(stderr,"interface : %s -- ",ifname);*/ 200 /* fprintf(stderr,"HWaddr : %s\n", print_ether(hard_addr));*/ 201 202 return 1; 203 } 204 205 206 /*****************************************************************************/ 207 /* osl_checkAddr */ 208 /*****************************************************************************/ 209 210 static int osl_checkAddr(const char* addr) 211 { 212 if (addr[0]==0 && addr[1]==0 && 213 addr[2]==0 && addr[3]==0 && 214 addr[4]==0 && addr[5]==0) 215 { 216 return -1; 217 } 218 return 0; 219 } 220 221 222 #if defined (SPARC) 223 224 #if defined (SOLARIS) && !defined(__sparcv8plus) && !defined(__sparcv9) 225 #include <sys/types.h> 226 #include <sys/processor.h> 227 228 /*****************************************************************************/ 229 /* osl_InitSparcV9 */ 230 /*****************************************************************************/ 231 232 void osl_InterlockedCountSetV9(sal_Bool bV9); 233 234 /* 235 * osl_InitSparcV9() should be executed as early as possible. We place it in the 236 * .init section of sal 237 */ 238 #if defined ( __SUNPRO_C ) || defined ( __SUNPRO_CC ) 239 void osl_InitSparcV9(void); 240 #pragma init (osl_InitSparcV9) 241 #elif defined ( __GNUC__ ) 242 void osl_InitSparcV9(void) __attribute__((constructor)); 243 #endif 244 245 void osl_InitSparcV9(void) 246 { 247 /* processor_info() identifies SPARCV8 (ie sun4c machines) simply as "sparc" 248 * and SPARCV9 (ie ultra sparcs, sun4u) as "sparcv9". Since we know that we 249 * run at least on a SPARCV8 architecture or better, any processor type != "sparc" 250 * and != "i386" is considered to be SPARCV9 or better 251 * 252 * This way we are certain that this will still work if someone names SPARCV10 253 * "foobar" 254 */ 255 processor_info_t aInfo; 256 int rc; 257 258 rc = processor_info(0, &aInfo); 259 260 if ( rc != -1 ) { 261 if ( !strcmp( "sparc", aInfo.pi_processor_type ) /* SPARCV8 */ 262 || !strcmp( "i386", aInfo.pi_processor_type ) ) /* can't happen, but ... */ 263 return; 264 /* we are reasonably certain to be on sparcv9/sparcv8plus or better */ 265 osl_InterlockedCountSetV9(sal_True); 266 } 267 } 268 269 #endif /* SOLARIS */ 270 271 #if defined(NETBSD) && defined(GCC) && !defined(__sparcv9) && !defined(__sparc_v9__) 272 273 #include <sys/param.h> 274 #include <sys/sysctl.h> 275 void osl_InitSparcV9(void) __attribute__((constructor)); 276 void osl_InterlockedCountSetV9(sal_Bool bV9); 277 278 /* Determine which processor we are running on (sparc v8 or v9) 279 * The approach is very similar to Solaris. 280 */ 281 282 void osl_InitSparcV9(void) 283 { 284 int mib[2]={CTL_HW,HW_MACHINE}; 285 char processorname[256]; 286 size_t len=256; 287 288 /* get the machine name */ 289 sysctl(mib, 2, processorname, &len, NULL, 0); 290 if (!strncmp("sparc64",processorname, len)) { 291 osl_InterlockedCountSetV9(sal_True); 292 } 293 } 294 295 #endif /* NETBSD */ 296 297 #endif /* SPARC */ 298 299 #if defined ( LINUX ) && defined ( SPARC ) 300 #include <sys/utsname.h> 301 void osl_InitSparcV9(void) __attribute__((constructor)); 302 void osl_InterlockedCountSetV9(sal_Bool bV9); 303 /* Determine which processor we are running on (sparc v8 or v9) 304 * The approach is very similar to Solaris. 305 */ 306 void osl_InitSparcV9(void) 307 { 308 struct utsname name; 309 int rc; 310 rc = uname(&name); 311 if ( rc != -1 ) { 312 if ( !strcmp( "sparc", name.machine )) 313 return; 314 osl_InterlockedCountSetV9(sal_True); 315 } 316 } 317 #endif 318 319 #if ( defined(__GNUC__) && (defined(X86) || defined(X86_64)) )\ 320 || ( defined(SOLARIS) && defined (__SUNPRO_C) && defined(__i386) ) 321 322 /* Safe default */ 323 int osl_isSingleCPU = 0; 324 325 /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system 326 * 327 * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount() 328 * comes with a cost and is especially expensive on pre HT x86 single processor 329 * systems, where it isn't needed at all. 330 * 331 * This should be run as early as possible, thus it's placed in the init section 332 */ 333 #if defined(_SC_NPROCESSORS_CONF) /* i.e. MACOSX for Intel doesn't have this */ 334 #if defined(__GNUC__) 335 void osl_interlockedCountCheckForSingleCPU(void) __attribute__((constructor)); 336 #elif defined(__SUNPRO_C) 337 void osl_interlockedCountCheckForSingleCPU(void); 338 #pragma init (osl_interlockedCountCheckForSingleCPU) 339 #endif 340 341 void osl_interlockedCountCheckForSingleCPU(void) 342 { 343 /* In case sysconfig fails be on the safe side, 344 * consider it a multiprocessor/multicore/HT system */ 345 if ( sysconf(_SC_NPROCESSORS_CONF) == 1 ) { 346 osl_isSingleCPU = 1; 347 } 348 } 349 #endif /* defined(_SC_NPROCESSORS_CONF) */ 350 #endif 351