1 /*
2  * Linux port of dhd command line utility, hacked from wl utility.
3  *
4  * Copyright (C) 1999-2013, Broadcom Corporation
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * $Id: dhdu_linux.c 378962 2013-01-15 13:18:28Z $
19  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <ctype.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <sys/socket.h>
30 #include <proto/ethernet.h>
31 #include <proto/bcmip.h>
32 #include <arpa/inet.h>
33 #include <sys/ioctl.h>
34 #include <net/if.h>
35 #include <fcntl.h>
36 #include <sys/ioctl.h>
37 #include <unistd.h>
38 
39 #ifndef TARGETENV_android
40 #include <error.h>
41 typedef u_int64_t u64;
42 typedef u_int32_t u32;
43 typedef u_int16_t u16;
44 typedef u_int8_t u8;
45 #endif /* TARGETENV_android */
46 #include <linux/sockios.h>
47 #include <linux/types.h>
48 #include <linux/ethtool.h>
49 
50 #include <typedefs.h>
51 #include <signal.h>
52 #include <dhdioctl.h>
53 #include <wlioctl.h>
54 #include <bcmcdc.h>
55 #include <bcmutils.h>
56 
57 #if defined(RWL_WIFI) || defined(RWL_SOCKET) ||defined(RWL_SERIAL)
58 #define RWL_ENABLE
59 #endif
60 
61 #include "dhdu.h"
62 #ifdef RWL_ENABLE
63 #include "wlu_remote.h"
64 #include "wlu_client_shared.h"
65 #include "wlu_pipe.h"
66 #endif /* RWL_ENABLE */
67 #include <netdb.h>
68 #include <netinet/in.h>
69 #include <dhdioctl.h>
70 #include "dhdu_common.h"
71 #include "dhdu_nl80211.h"
72 
73 char *av0;
74 static int rwl_os_type = LINUX_OS;
75 /* Search the dhd_cmds table for a matching command name.
76  * Return the matching command or NULL if no match found.
77  */
78 static cmd_t *
dhd_find_cmd(char * name)79 dhd_find_cmd(char* name)
80 {
81 	cmd_t *cmd = NULL;
82 	/* search the dhd_cmds for a matching name */
83 	for (cmd = dhd_cmds; cmd->name && strcmp(cmd->name, name); cmd++);
84 	if (cmd->name == NULL)
85 		cmd = NULL;
86 	return cmd;
87 }
88 
89 static void
syserr(const char * s)90 syserr(const char *s)
91 {
92 	fprintf(stderr, "%s: ", av0);
93 	perror(s);
94 	exit(errno);
95 }
96 
97 #ifdef NL80211
__dhd_driver_io(void * dhd,dhd_ioctl_t * ioc)98 static int __dhd_driver_io(void *dhd, dhd_ioctl_t *ioc)
99 {
100 	struct dhd_netlink_info dhd_nli;
101 	struct ifreq *ifr = (struct ifreq *)dhd;
102 	int ret = 0;
103 
104 	dhd_nli.ifidx = if_nametoindex(ifr->ifr_name);
105 	if (!dhd_nli.ifidx) {
106 		fprintf(stderr, "invalid device %s\n", ifr->ifr_name);
107 		return BCME_IOCTL_ERROR;
108 	}
109 
110 	if (dhd_nl_sock_connect(&dhd_nli) < 0)
111 		syserr("socket");
112 
113 	ret = dhd_nl_do_testmode(&dhd_nli, ioc);
114 	dhd_nl_sock_disconnect(&dhd_nli);
115 	return ret;
116 }
117 #else
__dhd_driver_io(void * dhd,dhd_ioctl_t * ioc)118 static int __dhd_driver_io(void *dhd, dhd_ioctl_t *ioc)
119 {
120 	struct ifreq *ifr = (struct ifreq *)dhd;
121 	int s;
122 	int ret = 0;
123 
124 	/* pass ioctl data */
125 	ifr->ifr_data = (caddr_t)ioc;
126 
127 	/* open socket to kernel */
128 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
129 		syserr("socket");
130 
131 	ret = ioctl(s, SIOCDEVPRIVATE, ifr);
132 	if (ret < 0 && errno != EAGAIN)
133 		syserr(__FUNCTION__);
134 
135 	/* cleanup */
136 	close(s);
137 	return ret;
138 }
139 #endif /* NL80211 */
140 
141 /* This function is called by ioctl_setinformation_fe or ioctl_queryinformation_fe
142  * for executing  remote commands or local commands
143  */
144 static int
dhd_ioctl(void * dhd,int cmd,void * buf,int len,bool set)145 dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set)
146 {
147 	dhd_ioctl_t ioc;
148 	int ret = 0;
149 
150 	/* By default try to execute wl commands */
151 	int driver_magic = WLC_IOCTL_MAGIC;
152 	int get_magic = WLC_GET_MAGIC;
153 
154 	/* For local dhd commands execute dhd. For wifi transport we still
155 	 * execute wl commands.
156 	 */
157 	if (remote_type == NO_REMOTE && strncmp (buf, RWL_WIFI_ACTION_CMD,
158 		strlen(RWL_WIFI_ACTION_CMD)) && strncmp(buf, RWL_WIFI_GET_ACTION_CMD,
159 		strlen(RWL_WIFI_GET_ACTION_CMD))) {
160 		driver_magic = DHD_IOCTL_MAGIC;
161 		get_magic = DHD_GET_MAGIC;
162 	}
163 
164 	/* do it */
165 	ioc.cmd = cmd;
166 	ioc.buf = buf;
167 	ioc.len = len;
168 	ioc.set = set;
169 	ioc.driver = driver_magic;
170 
171 	ret = __dhd_driver_io(dhd, &ioc);
172 	if (ret < 0 && cmd != get_magic)
173 		ret = BCME_IOCTL_ERROR;
174 	return ret;
175 }
176 
177 /* This function is called in wlu_pipe.c remote_wifi_ser_init() to execute
178  * the initial set of wl commands for wifi transport (e.g slow_timer, fast_timer etc)
179  */
wl_ioctl(void * wl,int cmd,void * buf,int len,bool set)180 int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set)
181 {
182 	return dhd_ioctl(wl, cmd, buf, len, set); /* Call actual wl_ioctl here: Shubhro */
183 }
184 
185 /* Search if dhd adapter or wl adapter is present
186  * This is called by dhd_find to check if it supports wl or dhd
187  * The reason for checking wl adapter is that we can still send remote dhd commands over
188  * wifi transport.
189  */
190 static int
dhd_get_dev_type(char * name,void * buf,char * type)191 dhd_get_dev_type(char *name, void *buf, char *type)
192 {
193 	int s;
194 	int ret;
195 	struct ifreq ifr;
196 	struct ethtool_drvinfo info;
197 
198 	/* open socket to kernel */
199 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
200 		syserr("socket");
201 
202 	/* get device type */
203 	memset(&info, 0, sizeof(info));
204 	info.cmd = ETHTOOL_GDRVINFO;
205 	strcpy(info.driver, "?");
206 	strcat(info.driver, type);
207 	ifr.ifr_data = (caddr_t)&info;
208 	strncpy(ifr.ifr_name, name, IFNAMSIZ);
209 	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
210 
211 		if (errno != EAGAIN)
212 			syserr(__FUNCTION__);
213 
214 		*(char *)buf = '\0';
215 	}
216 	else
217 		strcpy(buf, info.driver);
218 
219 	close(s);
220 	return ret;
221 }
222 
223 /* dhd_get/dhd_set is called by several functions in dhdu.c. This used to call dhd_ioctl
224  * directly. However now we need to execute the dhd commands remotely.
225  * So we make use of wl pipes to execute this.
226  * wl_get or wl_set functions also check if it is a local command hence they in turn
227  * call dhd_ioctl if required. Name wl_get/wl_set is retained because these functions are
228  * also called by wlu_pipe.c wlu_client_shared.c
229  */
230 int
dhd_get(void * dhd,int cmd,void * buf,int len)231 dhd_get(void *dhd, int cmd, void *buf, int len)
232 {
233 	return wl_get(dhd, cmd, buf, len);
234 }
235 
236 /*
237  * To use /dev/node interface:
238  *   1.  mknod /dev/hnd0 c 248 0
239  *   2.  chmod 777 /dev/hnd0
240  */
241 #define NODE "/dev/hnd0"
242 
243 int
dhd_set(void * dhd,int cmd,void * buf,int len)244 dhd_set(void *dhd, int cmd, void *buf, int len)
245 {
246 	static int dnode = -1;
247 
248 	switch (cmd) {
249 	case DHD_DLDN_ST:
250 		if (dnode == -1)
251 			dnode = open(NODE, O_RDWR);
252 		else
253 			fprintf(stderr, "devnode already opened!\n");
254 
255 		return dnode;
256 		break;
257 	case DHD_DLDN_WRITE:
258 		if (dnode > 0)
259 			return write(dnode, buf, len);
260 		break;
261 	case DHD_DLDN_END:
262 		if (dnode > 0)
263 			return close(dnode);
264 		break;
265 	default:
266 		return wl_set(dhd, cmd, buf, len);
267 
268 	}
269 
270 	return -1;
271 }
272 
273 /* Verify the wl adapter found.
274  * This is called by dhd_find to check if it supports wl
275  * The reason for checking wl adapter is that we can still send remote dhd commands over
276  * wifi transport. The function is copied from wlu.c.
277  */
278 int
wl_check(void * wl)279 wl_check(void *wl)
280 {
281 	int ret;
282 	int val = 0;
283 
284 	if (!dhd_check (wl))
285 		return 0;
286 
287 	/*
288 	 *  If dhd_check() fails then go for a regular wl driver verification
289 	 */
290 	if ((ret = wl_get(wl, WLC_GET_MAGIC, &val, sizeof(int))) < 0)
291 		return ret;
292 	if (val != WLC_IOCTL_MAGIC)
293 		return BCME_ERROR;
294 	if ((ret = wl_get(wl, WLC_GET_VERSION, &val, sizeof(int))) < 0)
295 		return ret;
296 	if (val > WLC_IOCTL_VERSION) {
297 		fprintf(stderr, "Version mismatch, please upgrade\n");
298 		return BCME_ERROR;
299 	}
300 	return 0;
301 }
302 /* Search and verify the request type of adapter (wl or dhd)
303  * This is called by main before executing local dhd commands
304  * or sending remote dhd commands over wifi transport
305  */
306 void
dhd_find(struct ifreq * ifr,char * type)307 dhd_find(struct ifreq *ifr, char *type)
308 {
309 	char proc_net_dev[] = "/proc/net/dev";
310 	FILE *fp;
311 	static char buf[400];
312 	char *c, *name;
313 	char dev_type[32];
314 
315 	ifr->ifr_name[0] = '\0';
316 	/* eat first two lines */
317 	if (!(fp = fopen(proc_net_dev, "r")) ||
318 	    !fgets(buf, sizeof(buf), fp) ||
319 	    !fgets(buf, sizeof(buf), fp))
320 		return;
321 
322 	while (fgets(buf, sizeof(buf), fp)) {
323 		c = buf;
324 		while (isspace(*c))
325 			c++;
326 		if (!(name = strsep(&c, ":")))
327 			continue;
328 		strncpy(ifr->ifr_name, name, IFNAMSIZ);
329 		if (dhd_get_dev_type(name, dev_type, type) >= 0 &&
330 			!strncmp(dev_type, type, strlen(dev_type) - 1))
331 		{
332 			if (!wl_check((void*)ifr))
333 				break;
334 		}
335 		ifr->ifr_name[0] = '\0';
336 	}
337 
338 	fclose(fp);
339 }
340 /* This function is called by wl_get to execute either local dhd command
341  * or send a dhd command over wl transport
342  */
343 static int
ioctl_queryinformation_fe(void * wl,int cmd,void * input_buf,int * input_len)344 ioctl_queryinformation_fe(void *wl, int cmd, void* input_buf, int *input_len)
345 {
346 	if (remote_type == NO_REMOTE) {
347 		return dhd_ioctl(wl, cmd, input_buf, *input_len, FALSE);
348 	}
349 #ifdef RWL_ENABLE
350 	else {
351 		return rwl_queryinformation_fe(wl, cmd, input_buf,
352 			(unsigned long*)input_len, 0, RDHD_GET_IOCTL);
353 	}
354 #else /* RWL_ENABLE */
355 	return BCME_IOCTL_ERROR;
356 #endif /* RWL_ENABLE */
357 }
358 
359 /* This function is called by wl_set to execute either local dhd command
360  * or send a dhd command over wl transport
361  */
362 static int
ioctl_setinformation_fe(void * wl,int cmd,void * buf,int * len)363 ioctl_setinformation_fe(void *wl, int cmd, void* buf, int *len)
364 {
365 	if (remote_type == NO_REMOTE) {
366 		return dhd_ioctl(wl,  cmd, buf, *len, TRUE);
367 	}
368 #ifdef RWL_ENABLE
369 	else {
370 		return rwl_setinformation_fe(wl, cmd, buf, (unsigned long*)len, 0, RDHD_SET_IOCTL);
371 
372 	}
373 #else /* RWL_ENABLE */
374 	return BCME_IOCTL_ERROR;
375 #endif /* RWL_ENABLE */
376 }
377 
378 /* The function is replica of wl_get in wlu_linux.c. Optimize when we have some
379  * common code between wlu_linux.c and dhdu_linux.c
380  */
381 int
wl_get(void * wl,int cmd,void * buf,int len)382 wl_get(void *wl, int cmd, void *buf, int len)
383 {
384 	int error = BCME_OK;
385 	/* For RWL: When interfacing to a Windows client, need t add in OID_BASE */
386 	if ((rwl_os_type == WIN32_OS) && (remote_type != NO_REMOTE)) {
387 		error = (int)ioctl_queryinformation_fe(wl, WL_OID_BASE + cmd, buf, &len);
388 	} else {
389 		error = (int)ioctl_queryinformation_fe(wl, cmd, buf, &len);
390 	}
391 	if (error == BCME_SERIAL_PORT_ERR)
392 		return BCME_SERIAL_PORT_ERR;
393 
394 	if (error != 0)
395 		return BCME_IOCTL_ERROR;
396 
397 	return error;
398 }
399 
400 /* The function is replica of wl_set in wlu_linux.c. Optimize when we have some
401  * common code between wlu_linux.c and dhdu_linux.c
402  */
403 int
wl_set(void * wl,int cmd,void * buf,int len)404 wl_set(void *wl, int cmd, void *buf, int len)
405 {
406 	int error = BCME_OK;
407 
408 	/* For RWL: When interfacing to a Windows client, need t add in OID_BASE */
409 	if ((rwl_os_type == WIN32_OS) && (remote_type != NO_REMOTE)) {
410 		error = (int)ioctl_setinformation_fe(wl, WL_OID_BASE + cmd, buf, &len);
411 	} else {
412 		error = (int)ioctl_setinformation_fe(wl, cmd, buf, &len);
413 	}
414 
415 	if (error == BCME_SERIAL_PORT_ERR)
416 		return BCME_SERIAL_PORT_ERR;
417 
418 	if (error != 0) {
419 		return BCME_IOCTL_ERROR;
420 	}
421 	return error;
422 }
423 
424 int
wl_validatedev(void * dev_handle)425 wl_validatedev(void *dev_handle)
426 {
427 	int retval = 1;
428 	struct ifreq *ifr = (struct ifreq *)dev_handle;
429 	/* validate the interface */
430 	if (!ifr->ifr_name || wl_check((void *)ifr)) {
431 		retval = 0;
432 	}
433 	return retval;
434 }
435 
436 /* Main client function
437  * The code is mostly from wlu_linux.c. This function takes care of executing remote dhd commands
438  * along with the local dhd commands now.
439  */
440 int
main(int argc,char ** argv)441 main(int argc, char **argv)
442 {
443 	struct ifreq ifr;
444 	char *ifname = NULL;
445 	int err = 0;
446 	int help = 0;
447 	int status = CMD_DHD;
448 #ifdef RWL_SOCKET
449 	struct ipv4_addr temp;
450 #endif /* RWL_SOCKET */
451 
452 	UNUSED_PARAMETER(argc);
453 
454 	av0 = argv[0];
455 	memset(&ifr, 0, sizeof(ifr));
456 	argv++;
457 
458 	if ((status = dhd_option(&argv, &ifname, &help)) == CMD_OPT) {
459 		if (ifname)
460 			strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
461 	}
462 	/* Linux client looking for a Win32 server */
463 	if (*argv && strncmp (*argv, "--wince", strlen(*argv)) == 0) {
464 		rwl_os_type = WIN32_OS;
465 		argv++;
466 	}
467 
468 	/* RWL socket transport Usage: --socket ipaddr [port num] */
469 	if (*argv && strncmp (*argv, "--socket", strlen(*argv)) == 0) {
470 		argv++;
471 
472 		remote_type = REMOTE_SOCKET;
473 #ifdef RWL_SOCKET
474 		if (!(*argv)) {
475 			rwl_usage(remote_type);
476 			return err;
477 		}
478 
479 		if (!dhd_atoip(*argv, &temp)) {
480 			rwl_usage(remote_type);
481 			return err;
482 		}
483 		g_rwl_servIP = *argv;
484 		argv++;
485 
486 		g_rwl_servport = DEFAULT_SERVER_PORT;
487 		if ((*argv) && isdigit(**argv)) {
488 			g_rwl_servport = atoi(*argv);
489 			argv++;
490 		}
491 #endif /* RWL_SOCKET */
492 	}
493 
494 	/* RWL from system serial port on client to uart dongle port on server */
495 	/* Usage: --dongle /dev/ttyS0 */
496 	if (*argv && strncmp (*argv, "--dongle", strlen(*argv)) == 0) {
497 		argv++;
498 		remote_type = REMOTE_DONGLE;
499 	}
500 
501 	/* RWL over wifi.  Usage: --wifi mac_address */
502 	if (*argv && strncmp (*argv, "--wifi", strlen(*argv)) == 0) {
503 		argv++;
504 #ifdef RWL_WIFI
505 		remote_type = NO_REMOTE;
506 		if (!ifr.ifr_name[0])
507 		{
508 			dhd_find(&ifr, "wl");
509 		}
510 		/* validate the interface */
511 		if (!ifr.ifr_name[0] || wl_check((void*)&ifr)) {
512 			fprintf(stderr, "%s: wl driver adapter not found\n", av0);
513 			exit(1);
514 		}
515 		remote_type = REMOTE_WIFI;
516 
517 		if (argc < 4) {
518 			rwl_usage(remote_type);
519 			return err;
520 		}
521 		/* copy server mac address to local buffer for later use by findserver cmd */
522 		if (!dhd_ether_atoe(*argv, (struct ether_addr *)g_rwl_buf_mac)) {
523 			fprintf(stderr,
524 			        "could not parse as an ethernet MAC address\n");
525 			return FAIL;
526 		}
527 		argv++;
528 #else /* RWL_WIFI */
529 		remote_type = REMOTE_WIFI;
530 #endif /* RWL_WIFI */
531 	}
532 
533 	/* Process for local dhd */
534 	if (remote_type == NO_REMOTE) {
535 		err = process_args(&ifr, argv);
536 		return err;
537 	}
538 
539 #ifdef RWL_ENABLE
540 	if (*argv) {
541 		err = process_args(&ifr, argv);
542 		if ((err == BCME_SERIAL_PORT_ERR) && (remote_type == REMOTE_DONGLE)) {
543 			DPRINT_ERR(ERR, "\n Retry again\n");
544 			err = process_args((struct ifreq*)&ifr, argv);
545 		}
546 		return err;
547 	}
548 	rwl_usage(remote_type);
549 #endif /* RWL_ENABLE */
550 
551 	return err;
552 }
553 /*
554  * Function called for  'local' execution and for 'remote' non-interactive session
555  * (shell cmd, wl cmd) .The code is mostly from wlu_linux.c. This code can be
556  * common to wlu_linux.c and dhdu_linux.c
557  */
558 static int
process_args(struct ifreq * ifr,char ** argv)559 process_args(struct ifreq* ifr, char **argv)
560 {
561 	char *ifname = NULL;
562 	int help = 0;
563 	int status = 0;
564 	int err = BCME_OK;
565 	cmd_t *cmd = NULL;
566 	while (*argv) {
567 #ifdef RWL_ENABLE
568 		if ((strcmp (*argv, "sh") == 0) && (remote_type != NO_REMOTE)) {
569 			argv++; /* Get the shell command */
570 			if (*argv) {
571 				/* Register handler in case of shell command only */
572 				signal(SIGINT, ctrlc_handler);
573 				err = rwl_shell_cmd_proc((void*)ifr, argv, SHELL_CMD);
574 			} else {
575 				DPRINT_ERR(ERR,
576 				"Enter the shell command (e.g ls(Linux) or dir(Win CE) \n");
577 				err = BCME_ERROR;
578 			}
579 			return err;
580 		}
581 #endif /* RWL_ENABLE */
582 		if ((status = dhd_option(&argv, &ifname, &help)) == CMD_OPT) {
583 			if (help)
584 				break;
585 			if (ifname)
586 				strncpy(ifr->ifr_name, ifname, IFNAMSIZ);
587 			continue;
588 		}
589 		/* parse error */
590 		else if (status == CMD_ERR)
591 		    break;
592 
593 		if (remote_type == NO_REMOTE) {
594 			int ret;
595 
596 			/* use default interface */
597 			if (!ifr->ifr_name[0])
598 				dhd_find(ifr, "dhd");
599 			/* validate the interface */
600 			if (!ifr->ifr_name[0]) {
601 				if (strcmp("dldn", *argv) != 0) {
602 					exit(ENXIO);
603 					syserr("interface");
604 				}
605 			}
606 			if ((ret = dhd_check((void *)ifr)) != 0) {
607 				if (strcmp("dldn", *argv) != 0) {
608 					errno = -ret;
609 					syserr("dhd_check");
610 				}
611 			}
612 		}
613 		/* search for command */
614 		cmd = dhd_find_cmd(*argv);
615 		/* if not found, use default set_var and get_var commands */
616 		if (!cmd) {
617 			cmd = &dhd_varcmd;
618 		}
619 
620 		/* do command */
621 		err = (*cmd->func)((void *) ifr, cmd, argv);
622 		break;
623 	} /* while loop end */
624 
625 	/* provide for help on a particular command */
626 	if (help && *argv) {
627 		cmd = dhd_find_cmd(*argv);
628 		if (cmd) {
629 			dhd_cmd_usage(cmd);
630 		} else {
631 			DPRINT_ERR(ERR, "%s: Unrecognized command \"%s\", type -h for help\n",
632 			           av0, *argv);
633 		}
634 	} else if (!cmd)
635 		dhd_usage(NULL);
636 	else if (err == BCME_USAGE_ERROR)
637 		dhd_cmd_usage(cmd);
638 	else if (err == BCME_IOCTL_ERROR)
639 		dhd_printlasterror((void *) ifr);
640 
641 	return err;
642 }
643 
644 int
rwl_shell_createproc(void * wl)645 rwl_shell_createproc(void *wl)
646 {
647 	UNUSED_PARAMETER(wl);
648 	return fork();
649 }
650 
651 void
rwl_shell_killproc(int pid)652 rwl_shell_killproc(int pid)
653 {
654 	kill(pid, SIGKILL);
655 }
656 
657 #ifdef RWL_SOCKET
658 /* validate hostname/ip given by the client */
659 int
validate_server_address()660 validate_server_address()
661 {
662 	struct hostent *he;
663 	struct ipv4_addr temp;
664 
665 	if (!dhd_atoip(g_rwl_servIP, &temp)) {
666 	/* Wrong IP address format check for hostname */
667 		if ((he = gethostbyname(g_rwl_servIP)) != NULL) {
668 			if (!dhd_atoip(*he->h_addr_list, &temp)) {
669 				g_rwl_servIP = inet_ntoa(*(struct in_addr *)*he->h_addr_list);
670 				if (g_rwl_servIP == NULL) {
671 					DPRINT_ERR(ERR, "Error at inet_ntoa \n");
672 					return FAIL;
673 				}
674 			} else {
675 				DPRINT_ERR(ERR, "Error in IP address \n");
676 				return FAIL;
677 			}
678 		} else {
679 			DPRINT_ERR(ERR, "Enter correct IP address/hostname format\n");
680 			return FAIL;
681 		}
682 	}
683 	return SUCCESS;
684 }
685 #endif /* RWL_SOCKET */
686