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 : {
126 0 : close(so);
127 0 : return 0;
128 : }
129 :
130 0 : strcpy(ifr.ifr_name, ifname);
131 :
132 : /*
133 : * First, get the Interface-FLAGS
134 : */
135 :
136 0 : ret=ioctl(so, SIOCGIFFLAGS, &ifr) ;
137 :
138 0 : if ( ret < 0 )
139 : {
140 : OSL_TRACE( "SIOCGIFFLAGS: %s", strerror(errno) );
141 0 : close(so);
142 0 : return ret;
143 : }
144 :
145 :
146 : /*
147 : * If it is the loopback device, do not consider it any further
148 : */
149 :
150 0 : if (ifr.ifr_flags & IFF_LOOPBACK)
151 : {
152 : OSL_TRACE( "SIOCGIFFLAGS : is LOOPBACK : %s", strerror(errno) );
153 0 : close(so);
154 0 : return 0;
155 : }
156 :
157 :
158 : /*
159 : * And now, the real thing: the get address
160 : */
161 :
162 : #if defined(SIOCGIFHWADDR) && !defined(SOLARIS)
163 0 : ret=ioctl(so, SIOCGIFHWADDR, &ifr);
164 : #else
165 : ret=ioctl(so, SIOCGIFADDR, &ifr);
166 : #endif
167 :
168 0 : if (ret < 0) {
169 : OSL_TRACE( "SIOCGIFADDR: %s", strerror(errno) );
170 0 : memset(hard_addr, 0, 32);
171 0 : close(so);
172 0 : return ret;
173 : }
174 :
175 0 : close(so);
176 :
177 : #if defined(SIOCGIFHWADDR) && !defined(SOLARIS)
178 0 : memcpy(hard_addr,ifr.ifr_hwaddr.sa_data,8);
179 : #else
180 : memcpy(hard_addr,ifr.ifr_ifru.ifru_addr.sa_data,8);
181 : #endif
182 :
183 :
184 : /*
185 : * Check, if no real, i.e. 00:00:00:00:00:00, address was retrieved.
186 : * The Linux dummy device has this kind of behaviour
187 : */
188 :
189 0 : ret=osl_checkAddr(hard_addr);
190 :
191 0 : if (ret < 0) {
192 : OSL_TRACE( "SIOCGIFADDR got '00:00:00:00:00:00'" );
193 0 : return ret;
194 : }
195 :
196 0 : return 1;
197 : }
198 :
199 :
200 : /*****************************************************************************/
201 : /* osl_checkAddr */
202 : /*****************************************************************************/
203 :
204 0 : static int osl_checkAddr(const char* addr)
205 : {
206 0 : if (addr[0]==0 && addr[1]==0 &&
207 0 : addr[2]==0 && addr[3]==0 &&
208 0 : addr[4]==0 && addr[5]==0)
209 : {
210 0 : return -1;
211 : }
212 0 : return 0;
213 : }
214 :
215 :
216 : #if defined (SPARC)
217 :
218 : #if defined (SOLARIS) && !defined(__sparcv8plus) && !defined(__sparcv9)
219 : #include <sys/types.h>
220 : #include <sys/processor.h>
221 :
222 : /*****************************************************************************/
223 : /* osl_InitSparcV9 */
224 : /*****************************************************************************/
225 :
226 : void osl_InterlockedCountSetV9(sal_Bool bV9);
227 :
228 : /*
229 : * osl_InitSparcV9() should be executed as early as possible. We place it in the
230 : * .init section of sal
231 : */
232 : #if defined ( __SUNPRO_C ) || defined ( __SUNPRO_CC )
233 : void osl_InitSparcV9(void);
234 : #pragma init (osl_InitSparcV9)
235 : #elif defined ( __GNUC__ )
236 : void osl_InitSparcV9(void) __attribute__((constructor));
237 : #endif
238 :
239 : void osl_InitSparcV9(void)
240 : {
241 : /* processor_info() identifies SPARCV8 (ie sun4c machines) simply as "sparc"
242 : * and SPARCV9 (ie ultra sparcs, sun4u) as "sparcv9". Since we know that we
243 : * run at least on a SPARCV8 architecture or better, any processor type != "sparc"
244 : * and != "i386" is considered to be SPARCV9 or better
245 : *
246 : * This way we are certain that this will still work if someone names SPARCV10
247 : * "foobar"
248 : */
249 : processor_info_t aInfo;
250 : int rc;
251 :
252 : rc = processor_info(0, &aInfo);
253 :
254 : if ( rc != -1 ) {
255 : if ( !strcmp( "sparc", aInfo.pi_processor_type ) /* SPARCV8 */
256 : || !strcmp( "i386", aInfo.pi_processor_type ) ) /* can't happen, but ... */
257 : return;
258 : /* we are reasonably certain to be on sparcv9/sparcv8plus or better */
259 : osl_InterlockedCountSetV9(sal_True);
260 : }
261 : }
262 :
263 : #endif /* SOLARIS */
264 :
265 : #if defined(NETBSD) && defined(__GNUC__) && !defined(__sparcv9) && !defined(__sparc_v9__)
266 :
267 : #include <sys/param.h>
268 : #include <sys/sysctl.h>
269 : void osl_InitSparcV9(void) __attribute__((constructor));
270 : void osl_InterlockedCountSetV9(sal_Bool bV9);
271 :
272 : /* Determine which processor we are running on (sparc v8 or v9)
273 : * The approach is very similar to Solaris.
274 : */
275 :
276 : void osl_InitSparcV9(void)
277 : {
278 : int mib[2]={CTL_HW,HW_MACHINE};
279 : char processorname[256];
280 : size_t len=256;
281 :
282 : /* get the machine name */
283 : sysctl(mib, 2, processorname, &len, NULL, 0);
284 : if (!strncmp("sparc64",processorname, len)) {
285 : osl_InterlockedCountSetV9(sal_True);
286 : }
287 : }
288 :
289 : #endif /* NETBSD */
290 :
291 : #endif /* SPARC */
292 :
293 : #if defined ( LINUX ) && defined ( SPARC )
294 : #include <sys/utsname.h>
295 : void osl_InitSparcV9(void) __attribute__((constructor));
296 : void osl_InterlockedCountSetV9(sal_Bool bV9);
297 : /* Determine which processor we are running on (sparc v8 or v9)
298 : * The approach is very similar to Solaris.
299 : */
300 : void osl_InitSparcV9(void)
301 : {
302 : struct utsname name;
303 : int rc;
304 : rc = uname(&name);
305 : if ( rc != -1 ) {
306 : if ( !strcmp( "sparc", name.machine ))
307 : return;
308 : osl_InterlockedCountSetV9(sal_True);
309 : }
310 : }
311 : #endif
312 :
313 : #if ( defined(__GNUC__) && (defined(X86) || defined(X86_64)) )\
314 : || ( defined(SOLARIS) && defined(__i386) )
315 :
316 : /* Safe default */
317 : int osl_isSingleCPU = 0;
318 :
319 : /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system
320 : *
321 : * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount()
322 : * comes with a cost and is especially expensive on pre HT x86 single processor
323 : * systems, where it isn't needed at all.
324 : *
325 : * This should be run as early as possible, thus it's placed in the init section
326 : */
327 : #if defined(_SC_NPROCESSORS_CONF) /* i.e. MACOSX for Intel doesn't have this */
328 : #if defined(__GNUC__)
329 : void osl_interlockedCountCheckForSingleCPU(void) __attribute__((constructor));
330 : #elif defined(__SUNPRO_C)
331 : void osl_interlockedCountCheckForSingleCPU(void);
332 : #pragma init (osl_interlockedCountCheckForSingleCPU)
333 : #endif
334 :
335 1788 : void osl_interlockedCountCheckForSingleCPU(void)
336 : {
337 : /* In case sysconfig fails be on the safe side,
338 : * consider it a multiprocessor/multicore/HT system */
339 1788 : if ( sysconf(_SC_NPROCESSORS_CONF) == 1 ) {
340 0 : osl_isSingleCPU = 1;
341 : }
342 1788 : }
343 : #endif /* defined(_SC_NPROCESSORS_CONF) */
344 : #endif
345 :
346 : //might be useful on other platforms, but doesn't compiler under MACOSX anyway
347 : #if defined(__GNUC__) && defined(LINUX)
348 : //force the __data_start symbol to exist in any executables that link against
349 : //libuno_sal so that dlopening of the libgcj provided libjvm.so on some
350 : //platforms where it needs that symbol will succeed. e.g. Debian mips/lenny
351 : //with gcc 4.3. With this in place the smoketest succeeds with libgcj provided
352 : //java. Quite possibly also required/helpful for s390x/s390 and maybe some
353 : //others. Without it the dlopen of libjvm.so will fail with __data_start
354 : //not found
355 : extern int __data_start[] __attribute__((weak));
356 : extern int data_start[] __attribute__((weak));
357 : extern int _end[] __attribute__((weak));
358 : static void *dummy[] __attribute__((used)) = {__data_start, data_start, _end};
359 : #endif
360 :
361 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|