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