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 + -
显示快捷键?