Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <unistd.h>
22 : #include <errno.h>
23 : #include <stdio.h>
24 : #include <string.h>
25 : #include <sys/ioctl.h>
26 : #include <sys/socket.h>
27 : #include <net/if.h>
28 :
29 : #ifdef SOLARIS
30 : #include <sys/sockio.h>
31 : #endif
32 :
33 : #include "osl/util.h"
34 : #include "osl/diagnose.h"
35 :
36 :
37 : /*****************************************************************************/
38 : /* Static Module Functions */
39 : /*****************************************************************************/
40 :
41 : static int osl_getHWAddr(const char *ifname, char* hard_addr);
42 : static int osl_checkAddr(const char* addr);
43 :
44 :
45 : /*****************************************************************************/
46 : /* osl_getEthernetAddress */
47 : /*****************************************************************************/
48 :
49 0 : sal_Bool SAL_CALL osl_getEthernetAddress( sal_uInt8 * pAddr )
50 : {
51 : #ifdef SOLARIS
52 : /** algorithm doesn't work on solaris */
53 : return sal_False;
54 : #else
55 : char buff[1024];
56 : char hard_addr[64];
57 : struct ifconf ifc;
58 : struct ifreq *ifr;
59 : int i;
60 : int so;
61 :
62 0 : if ( pAddr == 0 )
63 : {
64 0 : return sal_False;
65 : }
66 :
67 :
68 : /*
69 : * All we need is ... a network file descriptor.
70 : * Normally, this is a very socket.
71 : */
72 :
73 0 : so = socket(AF_INET, SOCK_DGRAM, 0);
74 :
75 :
76 : /*
77 : * The first thing we have to do, get the interface configuration.
78 : * It is a list of attached/configured interfaces
79 : */
80 :
81 0 : ifc.ifc_len = sizeof(buff);
82 0 : ifc.ifc_buf = buff;
83 0 : if ( ioctl(so, SIOCGIFCONF, &ifc) < 0 )
84 : {
85 : OSL_TRACE( "SIOCGIFCONF: %s", strerror(errno) );
86 0 : close(so);
87 0 : return sal_False;
88 : }
89 :
90 0 : close(so);
91 :
92 : /*
93 : * For each of the interfaces in the interface list,
94 : * try to get the hardware address
95 : */
96 :
97 0 : ifr = ifc.ifc_req;
98 0 : for ( i = ifc.ifc_len / sizeof(struct ifreq) ; --i >= 0 ; ifr++ )
99 : {
100 0 : int nRet=0;
101 0 : nRet = osl_getHWAddr(ifr->ifr_name,hard_addr);
102 0 : if ( nRet > 0 )
103 : {
104 0 : memcpy( pAddr , hard_addr, 6 );
105 0 : return sal_True;
106 : }
107 : }
108 :
109 0 : return sal_False;
110 : #endif
111 : }
112 :
113 :
114 : /*****************************************************************************/
115 : /* osl_getHWAddr */
116 : /*****************************************************************************/
117 :
118 0 : static int osl_getHWAddr(const char *ifname, char* hard_addr)
119 : {
120 0 : int ret=0;
121 : struct ifreq ifr;
122 0 : int so = socket(AF_INET, SOCK_DGRAM, 0);
123 :
124 0 : if (strlen(ifname) >= sizeof(ifr.ifr_name))
125 0 : return 0;
126 :
127 0 : strcpy(ifr.ifr_name, ifname);
128 :
129 : /*
130 : * First, get the Interface-FLAGS
131 : */
132 :
133 0 : ret=ioctl(so, SIOCGIFFLAGS, &ifr) ;
134 :
135 0 : if ( ret < 0 )
136 : {
137 : OSL_TRACE( "SIOCGIFFLAGS: %s", strerror(errno) );
138 0 : close(so);
139 0 : return ret;
140 : }
141 :
142 :
143 : /*
144 : * If it is the loopback device, do not consider it any further
145 : */
146 :
147 0 : if (ifr.ifr_flags & IFF_LOOPBACK)
148 : {
149 : OSL_TRACE( "SIOCGIFFLAGS : is LOOPBACK : %s", strerror(errno) );
150 0 : close(so);
151 0 : return 0;
152 : }
153 :
154 :
155 : /*
156 : * And now, the real thing: the get address
157 : */
158 :
159 : #if defined(SIOCGIFHWADDR) && !defined(SOLARIS)
160 0 : ret=ioctl(so, SIOCGIFHWADDR, &ifr);
161 : #else
162 : ret=ioctl(so, SIOCGIFADDR, &ifr);
163 : #endif
164 :
165 0 : if (ret < 0) {
166 : OSL_TRACE( "SIOCGIFADDR: %s", strerror(errno) );
167 0 : memset(hard_addr, 0, 32);
168 0 : close(so);
169 0 : return ret;
170 : }
171 :
172 0 : close(so);
173 :
174 : #if defined(SIOCGIFHWADDR) && !defined(SOLARIS)
175 0 : memcpy(hard_addr,ifr.ifr_hwaddr.sa_data,8);
176 : #else
177 : memcpy(hard_addr,ifr.ifr_ifru.ifru_addr.sa_data,8);
178 : #endif
179 :
180 :
181 : /*
182 : * Check, if no real, i.e. 00:00:00:00:00:00, address was retrieved.
183 : * The Linux dummy device has this kind of behaviour
184 : */
185 :
186 0 : ret=osl_checkAddr(hard_addr);
187 :
188 0 : if (ret < 0) {
189 : OSL_TRACE( "SIOCGIFADDR got '00:00:00:00:00:00'" );
190 0 : return ret;
191 : }
192 :
193 0 : return 1;
194 : }
195 :
196 :
197 : /*****************************************************************************/
198 : /* osl_checkAddr */
199 : /*****************************************************************************/
200 :
201 0 : static int osl_checkAddr(const char* addr)
202 : {
203 0 : if (addr[0]==0 && addr[1]==0 &&
204 0 : addr[2]==0 && addr[3]==0 &&
205 0 : addr[4]==0 && addr[5]==0)
206 : {
207 0 : return -1;
208 : }
209 0 : return 0;
210 : }
211 :
212 :
213 : #if defined (SPARC)
214 :
215 : #if defined (SOLARIS) && !defined(__sparcv8plus) && !defined(__sparcv9)
216 : #include <sys/types.h>
217 : #include <sys/processor.h>
218 :
219 : /*****************************************************************************/
220 : /* osl_InitSparcV9 */
221 : /*****************************************************************************/
222 :
223 : void osl_InterlockedCountSetV9(sal_Bool bV9);
224 :
225 : /*
226 : * osl_InitSparcV9() should be executed as early as possible. We place it in the
227 : * .init section of sal
228 : */
229 : #if defined ( __SUNPRO_C ) || defined ( __SUNPRO_CC )
230 : void osl_InitSparcV9(void);
231 : #pragma init (osl_InitSparcV9)
232 : #elif defined ( __GNUC__ )
233 : void osl_InitSparcV9(void) __attribute__((constructor));
234 : #endif
235 :
236 : void osl_InitSparcV9(void)
237 : {
238 : /* processor_info() identifies SPARCV8 (ie sun4c machines) simply as "sparc"
239 : * and SPARCV9 (ie ultra sparcs, sun4u) as "sparcv9". Since we know that we
240 : * run at least on a SPARCV8 architecture or better, any processor type != "sparc"
241 : * and != "i386" is considered to be SPARCV9 or better
242 : *
243 : * This way we are certain that this will still work if someone names SPARCV10
244 : * "foobar"
245 : */
246 : processor_info_t aInfo;
247 : int rc;
248 :
249 : rc = processor_info(0, &aInfo);
250 :
251 : if ( rc != -1 ) {
252 : if ( !strcmp( "sparc", aInfo.pi_processor_type ) /* SPARCV8 */
253 : || !strcmp( "i386", aInfo.pi_processor_type ) ) /* can't happen, but ... */
254 : return;
255 : /* we are reasonably certain to be on sparcv9/sparcv8plus or better */
256 : osl_InterlockedCountSetV9(sal_True);
257 : }
258 : }
259 :
260 : #endif /* SOLARIS */
261 :
262 : #if defined(NETBSD) && defined(GCC) && !defined(__sparcv9) && !defined(__sparc_v9__)
263 :
264 : #include <sys/param.h>
265 : #include <sys/sysctl.h>
266 : void osl_InitSparcV9(void) __attribute__((constructor));
267 : void osl_InterlockedCountSetV9(sal_Bool bV9);
268 :
269 : /* Determine which processor we are running on (sparc v8 or v9)
270 : * The approach is very similar to Solaris.
271 : */
272 :
273 : void osl_InitSparcV9(void)
274 : {
275 : int mib[2]={CTL_HW,HW_MACHINE};
276 : char processorname[256];
277 : size_t len=256;
278 :
279 : /* get the machine name */
280 : sysctl(mib, 2, processorname, &len, NULL, 0);
281 : if (!strncmp("sparc64",processorname, len)) {
282 : osl_InterlockedCountSetV9(sal_True);
283 : }
284 : }
285 :
286 : #endif /* NETBSD */
287 :
288 : #endif /* SPARC */
289 :
290 : #if defined ( LINUX ) && defined ( SPARC )
291 : #include <sys/utsname.h>
292 : void osl_InitSparcV9(void) __attribute__((constructor));
293 : void osl_InterlockedCountSetV9(sal_Bool bV9);
294 : /* Determine which processor we are running on (sparc v8 or v9)
295 : * The approach is very similar to Solaris.
296 : */
297 : void osl_InitSparcV9(void)
298 : {
299 : struct utsname name;
300 : int rc;
301 : rc = uname(&name);
302 : if ( rc != -1 ) {
303 : if ( !strcmp( "sparc", name.machine ))
304 : return;
305 : osl_InterlockedCountSetV9(sal_True);
306 : }
307 : }
308 : #endif
309 :
310 : #if ( defined(__GNUC__) && (defined(X86) || defined(X86_64)) )\
311 : || ( defined(SOLARIS) && defined(__i386) )
312 :
313 : /* Safe default */
314 : int osl_isSingleCPU = 0;
315 :
316 : /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system
317 : *
318 : * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount()
319 : * comes with a cost and is especially expensive on pre HT x86 single processor
320 : * systems, where it isn't needed at all.
321 : *
322 : * This should be run as early as possible, thus it's placed in the init section
323 : */
324 : #if defined(_SC_NPROCESSORS_CONF) /* i.e. MACOSX for Intel doesn't have this */
325 : #if defined(__GNUC__)
326 : void osl_interlockedCountCheckForSingleCPU(void) __attribute__((constructor));
327 : #elif defined(__SUNPRO_C)
328 : void osl_interlockedCountCheckForSingleCPU(void);
329 : #pragma init (osl_interlockedCountCheckForSingleCPU)
330 : #endif
331 :
332 1277 : void osl_interlockedCountCheckForSingleCPU(void)
333 : {
334 : /* In case sysconfig fails be on the safe side,
335 : * consider it a multiprocessor/multicore/HT system */
336 1277 : if ( sysconf(_SC_NPROCESSORS_CONF) == 1 ) {
337 0 : osl_isSingleCPU = 1;
338 : }
339 1277 : }
340 : #endif /* defined(_SC_NPROCESSORS_CONF) */
341 : #endif
342 :
343 : //might be useful on other platforms, but doesn't compiler under MACOSX anyway
344 : #if defined(__GNUC__) && defined(LINUX)
345 : //force the __data_start symbol to exist in any executables that link against
346 : //libuno_sal so that dlopening of the libgcj provided libjvm.so on some
347 : //platforms where it needs that symbol will succeed. e.g. Debian mips/lenny
348 : //with gcc 4.3. With this in place the smoketest succeeds with libgcj provided
349 : //java. Quite possibly also required/helpful for s390x/s390 and maybe some
350 : //others. Without it the dlopen of libjvm.so will fail with __data_start
351 : //not found
352 : extern int __data_start[] __attribute__((weak));
353 : extern int data_start[] __attribute__((weak));
354 : extern int _end[] __attribute__((weak));
355 : static void *dummy[] __attribute__((used)) = {__data_start, data_start, _end};
356 : #endif
357 :
358 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|