4 * Copyright (C) 2010, Broadcom Corporation
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: wlu_server_linux.c,v 1.6 2010-02-03 13:09:13 Exp $
15 /* Revision History:Linux port of Remote wl server
17 * Date Author Description
19 * 27-Dec-2007 Suganthi Version 0.1
31 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
39 #include <sys/ioctl.h>
41 #ifndef TARGETENV_android
42 typedef u_int64_t u64
;
43 typedef u_int32_t u32
;
44 typedef u_int16_t u16
;
46 typedef u_int64_t __u64
;
47 typedef u_int32_t __u32
;
48 typedef u_int16_t __u16
;
49 typedef u_int8_t __u8
;
52 #include <linux/sockios.h>
53 #include <linux/ethtool.h>
58 #include <proto/ethernet.h>
59 #include <bcmendian.h>
62 #include <proto/802.11.h>
63 #include "wlu_remote.h"
66 #define DEV_TYPE_LEN 3 /* length for devtype 'wl'/'et' */
67 #define IOCTL_ERROR -2
68 #define BUF_LENGTH 1000
76 const char *rwl_server_name
;
78 unsigned short defined_debug
= DEBUG_ERR
| DEBUG_INFO
;
79 extern int remote_server_exec(int argc
, char **argv
, void *ifr
);
81 /* Global to have the PID of the current sync command
82 * This is required in case the sync command fails to respond,
83 * the alarm handler shall kill the PID upon a timeout
86 unsigned char g_return_stat
= 0;
91 fprintf(stderr
, "%s: ", rwl_server_name
);
95 /* The handler for DHD commands */
97 dhd_ioctl(void *dhd
, int cmd
, void *buf
, int len
, bool set
)
99 struct ifreq
*ifr
= (struct ifreq
*) dhd
;
104 /* open socket to kernel */
105 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
113 ioc
.driver
= DHD_IOCTL_MAGIC
;
114 ifr
->ifr_data
= (caddr_t
) &ioc
;
115 if ((ret
= ioctl(s
, SIOCDEVPRIVATE
, ifr
)) < 0) {
116 if (cmd
!= DHD_GET_MAGIC
) {
126 wl_ioctl(void *wl
, int cmd
, void *buf
, int len
, bool set
)
128 struct ifreq
*ifr
= (struct ifreq
*) wl
;
133 /* open socket to kernel */
134 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
142 ifr
->ifr_data
= (caddr_t
) &ioc
;
143 if ((ret
= ioctl(s
, SIOCDEVPRIVATE
, ifr
)) < 0) {
144 if (cmd
!= WLC_GET_MAGIC
) {
153 /* Functions copied from wlu.c to check for the driver adapter in the server machine */
160 if ((ret
= wl_ioctl(wl
, WLC_GET_MAGIC
, &val
, sizeof(int), FALSE
) < 0))
163 /* Detect if IOCTL swapping is necessary */
164 if (val
== (int)bcmswap32(WLC_IOCTL_MAGIC
))
166 val
= bcmswap32(val
);
170 if (val
!= WLC_IOCTL_MAGIC
)
172 if ((ret
= wl_ioctl(wl
, WLC_GET_VERSION
, &val
, sizeof(int), FALSE
) < 0))
176 if (val
> WLC_IOCTL_VERSION
) {
177 fprintf(stderr
, "Version mismatch, please upgrade\n");
184 wl_get_dev_type(char *name
, void *buf
, int len
)
189 struct ethtool_drvinfo info
;
191 /* open socket to kernel */
192 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
195 /* get device type */
196 memset(&info
, 0, sizeof(info
));
197 info
.cmd
= ETHTOOL_GDRVINFO
;
198 ifr
.ifr_data
= (caddr_t
)&info
;
199 strncpy(ifr
.ifr_name
, name
, IFNAMSIZ
);
200 if ((ret
= ioctl(s
, SIOCETHTOOL
, &ifr
)) < 0) {
201 /* print a good diagnostic if not superuser */
203 syserr("wl_get_dev_type");
206 strncpy(buf
, info
.driver
, len
);
213 wl_find_adapter(struct ifreq
*ifr
)
215 char proc_net_dev
[] = "/proc/net/dev";
217 char buf
[BUF_LENGTH
], *c
, *name
;
218 char dev_type
[DEV_TYPE_LEN
];
220 ifr
->ifr_name
[0] = '\0';
222 if (!(fp
= fopen(proc_net_dev
, "r")))
225 /* eat first two lines */
226 if (!fgets(buf
, sizeof(buf
), fp
) ||
227 !fgets(buf
, sizeof(buf
), fp
)) {
232 while (fgets(buf
, sizeof(buf
), fp
)) {
236 if (!(name
= strsep(&c
, ":")))
238 strncpy(ifr
->ifr_name
, name
, IFNAMSIZ
);
239 if (wl_get_dev_type(name
, dev_type
, DEV_TYPE_LEN
) >= 0 &&
240 !strncmp(dev_type
, "wl", 2))
241 if (wl_check((void *) ifr
) == 0)
243 ifr
->ifr_name
[0] = '\0';
250 wl_get(void *wl
, int cmd
, void *buf
, int len
)
254 error
= wl_ioctl(wl
, cmd
, buf
, len
, FALSE
);
260 wl_set(void *wl
, int cmd
, void *buf
, int len
)
264 error
= wl_ioctl(wl
, cmd
, buf
, len
, TRUE
);
269 extern int set_ctrlc
;
270 void handle_ctrlc(int unused
)
272 UNUSED_PARAMETER(unused
);
277 volatile sig_atomic_t g_sig_chld
= 1;
278 void rwl_chld_handler(int num
)
282 UNUSED_PARAMETER(num
);
283 /* g_return_stat is being set with the return status of sh commands */
284 waitpid(g_shellsync_pid
, &child_status
, WNOHANG
);
285 if (WIFEXITED(child_status
))
286 g_return_stat
= WEXITSTATUS(child_status
);
287 else if (g_rem_ptr
->msg
.flags
== (unsigned)CTRLC_FLAG
)
294 /* Alarm handler called after SHELL_TIMEOUT value
295 * This handler kills the non-responsive shell process
296 * with the PID value g_shellsync_pid
299 sigalrm_handler(int s
)
303 if (g_shellsync_pid
) {
304 kill(g_shellsync_pid
, SIGINT
);
315 kill(g_shellsync_pid
, SIGKILL
);
323 kill(g_shellsync_pid
, SIGKILL
);
327 main(int argc
, char **argv
)
332 rwl_server_name
= argv
[0];
334 if ((ifr
= malloc(sizeof(struct ifreq
))) == NULL
)
336 DPRINT_ERR(ERR
, "wl_server: Unable to allocate memory for handle\n");
339 memset(ifr
, 0, sizeof(ifr
));
341 /* use default interface */
342 if (!ifr
->ifr_name
[0])
343 wl_find_adapter(ifr
);
344 /* validate the interface */
345 if (!ifr
->ifr_name
[0] || wl_check((void *)ifr
)) {
346 DPRINT_INFO(OUTPUT
, "wl_server: wl driver adapter not found\n");
350 /* Register signal handlers */
351 signal(SIGCHLD
, rwl_chld_handler
);
352 signal(SIGALRM
, sigalrm_handler
);
353 signal(SIGTERM
, def_handler
);
354 signal(SIGPIPE
, pipe_handler
);
355 signal(SIGABRT
, def_handler
);
357 signal(SIGINT
, handle_ctrlc
);
359 /* Main server process for all transport types */
360 err
= remote_server_exec(argc
, argv
, ifr
);
366 * Funtion to store old interface.
369 store_old_interface(void *wl
, char *old_intf_name
)
371 strcpy(old_intf_name
, ((struct ifreq
*)wl
)->ifr_name
);
375 * Function to set interface.
378 set_interface(void *wl
, char *intf_name
)
380 struct ifreq
*ifr
= (struct ifreq
*)wl
;
382 if (strlen(intf_name
) != 0) {
383 strncpy(ifr
->ifr_name
, intf_name
, strlen(intf_name
) + 1);
387 DPRINT_DBG(OUTPUT
, "Default Interface will be used ... \n");