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