wland.c

来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 588 行

C
588
字号
/* src/wland/wland.c** wireless lan daemon** Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.* --------------------------------------------------------------------** linux-wlan**   The contents of this file are subject to the Mozilla Public*   License Version 1.1 (the "License"); you may not use this file*   except in compliance with the License. You may obtain a copy of*   the License at http://www.mozilla.org/MPL/**   Software distributed under the License is distributed on an "AS*   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or*   implied. See the License for the specific language governing*   rights and limitations under the License.**   Alternatively, the contents of this file may be used under the*   terms of the GNU Public License version 2 (the "GPL"), in which*   case the provisions of the GPL are applicable instead of the*   above.  If you wish to allow the use of your version of this file*   only under the terms of the GPL and not to allow others to use*   your version of this file under the MPL, indicate your decision*   by deleting the provisions above and replace them with the notice*   and other provisions required by the GPL.  If you do not delete*   the provisions above, a recipient may use your version of this*   file under either the MPL or the GPL.** --------------------------------------------------------------------** Inquiries regarding the linux-wlan Open Source project can be* made directly to:** AbsoluteValue Systems Inc.* info@linux-wlan.com* http://www.linux-wlan.com** --------------------------------------------------------------------** Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development.** --------------------------------------------------------------------*/#if 0#ifndef __linux__#include <pcmcia/u_compat.h>#endif#endif#include <stdio.h>#include <stdlib.h>#include <string.h>/* Ugly hack for LinuxPPC R4, don't have time to figure it out right now */#if defined(__WLAN_PPC__)#undef __GLIBC__#endif#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <syslog.h>#include <getopt.h>#include <signal.h>#include <sys/time.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/utsname.h>#include <sys/file.h>#include <sys/param.h>#include <asm/types.h>#include <linux/netlink.h>#include <wlan/wlan_compat.h>#include <wlan/version.h>#include <wlan/p80211types.h>#include <wlan/p80211meta.h>#include <wlan/p80211metamsg.h>#include <wlan/p80211metamib.h>#include <wlan/p80211msg.h>#include <wlan/p80211ioctl.h>/*----------------------------------------------------------------*	Function Prototyes----------------------------------------------------------------*/static int	daemon_init(void);static int	execute_as_daemon(char *cmd);static int	execute_as_user(char *cmd);static int	msg2command( UINT8 *msg, UINT8 *cmd, UINT32 msgcode );static int	netlink_init(void);static void	process_messages(void);static void	signal_handler( int signo );static void	usage(char *prog_name);/*----------------------------------------------------------------*	Global Variables----------------------------------------------------------------*/static	FILE		*msgfp;static	int		nlfd;static	int		user_process;static	char		*wland_path = "/etc/wlan";/*----------------------------------------------------------------* main** wland entry point.** Arguments:*	argc	number of command line arguments*	argv	array of argument strings** Returns: *	0	- success *	~0	- failure----------------------------------------------------------------*/int main(int argc, char *argv[]){	int errflg;	int optch;	errflg = 0;	/* Set Globals */	msgfp = NULL;	nlfd = -1;	user_process = 0;	while ((optch = getopt(argc, argv, "Vvd:u")) != -1) {		switch (optch) {		case 'V':		case 'v':			fprintf(stderr, "wland version %s\n", WLAN_RELEASE);			return 0;			break;		case 'd':			wland_path = strdup(optarg);			break;		case 'u':			user_process = 1;			break;		default:			errflg = 1; break;		}	}	if (errflg || (optind < argc)) {		usage(argv[0]);		exit(1);	}	if ( chdir(wland_path) < 0 ) {		fprintf(stderr, "wland: ERROR changing to directory %s\n",			wland_path);		exit(1);	}	if ( !user_process ) {		if ( !(daemon_init()) ) {			exit(1);		}	}	if ( !(netlink_init()) ) {		exit(1);	}	process_messages();	return 0;}/*----------------------------------------------------------------* daemon_init** This function performs the necessary steps to make the program* behave as a daemon.** Arguments:*	none** Returns: *	!0 - success*	0 - no success*----------------------------------------------------------------*/static int daemon_init(void){	int ret;	int retval;	retval = 1;	if ((ret = fork()) > 0) {		return 0;	}	openlog("wland", LOG_PID, LOG_USER );	if (ret < 0) {		syslog(LOG_ERR, "forking: %m");		retval = 0;	}	if (setsid() < 0) {		syslog(LOG_ERR, "detaching from tty: %m");		retval = 0;	}	umask(0);	syslog(LOG_INFO, "wland daemon init successful");	return retval;} /*----------------------------------------------------------------* usage** This function prints the proper syntax for executing the program.** Arguments:*	none** Returns: *	nothing*----------------------------------------------------------------*/static void usage(char *prog_name){	fprintf(stderr, "usage: %s [-V|-v] [-d wlandpath] [-u]\n",		prog_name);}/*----------------------------------------------------------------* process_messages** This function sits in a loop receiving messages from the Linux* WLAN driver indicating an event has happened.  The appropriate* program is called based on the message code (i.e. the* event/indication) received from the Linux WLAN driver.** Arguments:*	none** Returns: *	nothing*----------------------------------------------------------------*/static void process_messages(void){	UINT8		msgbuf[MSG_BUFF_LEN];	UINT8		cmdbuf[MSG_BUFF_LEN];	int		recvlen;	int		m2c;	if ( user_process ) {		if ( (msgfp = fopen("wlandmsg.out", "w")) == NULL ) {			fprintf(stderr, "Could not open message output file\n");			return;		}	}	/* loop forever receiving and processing messages */	for(;;) {		if ((recvlen = recv( nlfd, msgbuf, sizeof(msgbuf), 0 ))			> -1 ) {			m2c = msg2command(msgbuf, cmdbuf,					((p80211msg_t *)msgbuf)->msgcode);			if ( !user_process ) {				if ( m2c ) {					execute_as_daemon( cmdbuf );				} else {					syslog( LOG_ERR, 						"process_message: %s", cmdbuf);				}			} else {				fprintf(msgfp,"%s\n", cmdbuf);				execute_as_user( cmdbuf );				fflush(msgfp);			}		} else {			if ( !user_process ) {				syslog( LOG_ERR, "recv: %m");			} else {				fprintf( msgfp,					"ERROR receiving msg from socket\n");				fflush(msgfp);			}		}	}}/*----------------------------------------------------------------* netlink_init** This function establishes the ability to allow the Linux WLAN* driver to notify the daemon of events.** Arguments:*	none** Returns: *	!0 - success*	0 - no success*----------------------------------------------------------------*/static int netlink_init(void){	int			i;	int			retval;	struct sockaddr_nl	nlskaddr;	/* set up the signal handler */	for ( i = 1; i < _NSIG; i++) {		signal( i, signal_handler);	}	retval = 1;	/* open the netlink socket */	if ( (nlfd = socket( PF_NETLINK, SOCK_RAW, P80211_NL_SOCK_IND ))		!= -1 ) {		memset ( &nlskaddr, 0 , sizeof( nlskaddr ));		nlskaddr.nl_family = (sa_family_t)PF_NETLINK;		nlskaddr.nl_pid = (__u32)getpid();		nlskaddr.nl_groups = P80211_NL_MCAST_GRP_MLME;		/* bind the netlink socket */		if ((bind( nlfd, (struct sockaddr*)&nlskaddr,			sizeof(nlskaddr))) != -1 ) {			syslog(LOG_INFO,			"netlink socket opened and bound successfully");		} else {			syslog(LOG_ERR, "bind: %m");			retval = 0;		}	} else {		syslog(LOG_ERR, "netlink socket: %m");		retval = 0;	}	return retval;}/*----------------------------------------------------------------* msg2command** Traverse the message and build a command to be executed.** Arguments:*	msg	buffer containing a complete msg*	cmd	buffer containing a complete command*	msgcode	integer identifying the msg** Returns: *	!0	- success *	0	- no success----------------------------------------------------------------*/static int msg2command( UINT8 *msg, UINT8 *cmd, UINT32 msgcode ){	UINT8			tmpitem[MSG_BUFF_LEN];	UINT8			*msgptr;	UINT8			*start;	INT			i;	INT			retval;	grplistitem_t		*grp;	catlistitem_t		*cat;	UINT32			narg;	UINT32			offset;	UINT32			tmpdid;	p80211meta_t		*alist;	retval = 1;	msgptr = msg;	/* acquire the msg argument metadata list */	if ( (cat = p80211_did2cat(msg_catlist, msgcode)) != NULL ) {		if ( (grp = p80211_did2grp(msg_catlist, msgcode)) != NULL ) {			alist = grp->itemlist;			narg = GETMETASIZE(alist);		} else {			sprintf( cmd,				"msg2command: Invalid grp in msgcode %lu\n",				msgcode);			return 0;		}	} else {		sprintf( cmd,			"msg2command: Invalid cat in msgcode %lu\n",			msgcode);		return 0;	}	sprintf( cmd, "%s_%s %s", cat->name, grp->name,		((p80211msg_t *)msg)->devname);	start =  msg + sizeof(p80211msg_t);	for ( i = 1; i < narg; i++ ) {		tmpdid = msgcode | P80211DID_MKITEM(i) | alist[i].did;		offset =p80211item_getoffset(msg_catlist, tmpdid);		msgptr = start + offset;				/* pass tmpdid since the 'totext' functions */		/* expect a non-zero did */		if ( ((p80211item_t *)msgptr)->status ==			P80211ENUM_msgitem_status_data_ok ) {			if ( alist[i].totextptr != NULL ) {				(*(alist[i].totextptr))					( msg_catlist, tmpdid, msgptr, tmpitem);				strcat( cmd, " ");				strcat( cmd, tmpitem);			} else {				p80211_error2text(				P80211ENUM_msgitem_status_missing_print_func,					tmpitem);				strcat( cmd, tmpitem);				retval = 0;			}		} else {			p80211_error2text( ((p80211item_t *)msgptr)->status,				tmpitem);			strcat( cmd, tmpitem);			retval = 0;		}	} /* for each argument in the metadata */	return retval;}/*----------------------------------------------------------------* execute_as_daemon** This function comes directly from David Hind's cardmgr.c in* his pcmcia code (with only a few minor modifications).** Arguments:*	cmd	buffer containing a complete shell command** Returns: *	!(-1)	- success *	-1	- no success----------------------------------------------------------------*/static int execute_as_daemon(char *cmd){	int	msglen;	int	ret;	FILE	*f;	char	line[MSG_BUFF_LEN];	char	msg[82];	msglen = (strchr( cmd, ' ' )) - cmd;	strncpy( msg, cmd, msglen);	msg[msglen] = '\0';	syslog(LOG_INFO, "executing: '%s'", msg);	strcat(cmd, " 2>&1");	f = popen(cmd, "r");	while (fgets(line, MSG_BUFF_LEN - 1, f)) {		line[strlen(line)-1] = '\0';		syslog(LOG_INFO, "%s: %s", msg, line);	}	ret = pclose(f);	if (WIFEXITED(ret)) {		if (WEXITSTATUS(ret)) {			syslog(LOG_INFO, "%s exited with status %d",				msg, WEXITSTATUS(ret));		}		return WEXITSTATUS(ret);	} else {		syslog(LOG_INFO, "%s exited on signal %d",			msg, WTERMSIG(ret));	}	return -1;}/*----------------------------------------------------------------* execute_as_user** This function comes directly from David Hind's cardmgr.c in* his pcmcia code (with only a few minor modifications).** Arguments:*	cmd	buffer containing a complete shell command** Returns: *	!(-1)	- success *	-1	- no success----------------------------------------------------------------*/static int execute_as_user(char *cmd){	int	msglen;	int	ret;	FILE	*f;	char	line[MSG_BUFF_LEN];	char	msg[82];	msglen = (strchr( cmd, ' ' )) - cmd;	strncpy( msg, cmd, msglen);	msg[msglen] = '\0';	fprintf(msgfp, "executing: '%s'\n", msg);	strcat(cmd, " 2>&1");	f = popen(cmd, "r");	while (fgets(line, MSG_BUFF_LEN - 1, f)) {		line[strlen(line)-1] = '\0';		fprintf(msgfp, "%s: %s\n", msg, line);	}	ret = pclose(f);	if (WIFEXITED(ret)) {		if (WEXITSTATUS(ret)) {			fprintf(msgfp, "%s exited with status %d",				msg, WEXITSTATUS(ret));		}		return WEXITSTATUS(ret);	} else {		fprintf(msgfp, "%s exited on signal %d",			msg, WTERMSIG(ret));	}	return -1;}/*----------------------------------------------------------------* signal_handler** This function is called when a signal is generated and sent* to the program.** Arguments:*	signo	signal number** Returns: *	Nothing*----------------------------------------------------------------*/static void signal_handler( int signo ){	if ( signo != SIGCHLD ) {		if ( msgfp == NULL ) { 			syslog(LOG_ERR,				"signal: Terminating with signal %d", signo);		} else {			fprintf( msgfp,				"signal: Terminating with signal %d\n", signo);			fflush( msgfp );			fclose( msgfp );		}		close( nlfd );		exit( 0 );	}	return;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?