Diff for /embedtools/src/dwds.c between versions 1.1 and 1.2

version 1.1, 2010/10/27 13:10:40 version 1.2, 2011/06/08 12:45:41
Line 0 Line 1
   #include "global.h"
   #include "dwds.h"
   
   
   sl_config cfg;
   int Verbose, Kill, nif;
   char **ifs, szConfig[MAXPATHLEN] = DWDS_CONFIG;
   extern char compiled[], compiledby[], compilehost[];
   
   
   static void
   Usage()
   {
           printf( "-= dWDS =- WiFi dynamic WDS service managment for VAP\n"
                   "=== %s === %s@%s ===\n\n"
                   "  Syntax: dwds [options] <interface|any> [interface [ath0, ...]]\n"
                   "\n"
                   "\t-v\t\tVerbose ...\n"
                   "\t-f\t\tForeground, not demonize process ...\n"
                   "\t-c <config>\tConfig file [default=/etc/dwds.conf]\n"
                   "\n", compiled, compiledby, compilehost);
   }
   
   static void
   sigHandler(int sig)
   {
           int stat;
           const u_char *v;
           char szStr[STRSIZ];
   
           switch (sig) {
                   case SIGHUP:
                           UnloadConfig(&cfg);
                           if (LoadConfig(szConfig, &cfg)) {
                                   printf("Error:: can`t load config %s ...\n", szConfig);
                                   Kill++;
                           } else {
                                   closelog();
   
                                   cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), CFG(szStr), STRSIZ, DWDS_NAME);
                                   openlog(szStr, LOG_PID | LOG_CONS, LOG_DAEMON);
                                   v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("syslog_upto"));
                                   setlogmask(v ? strtol((char*) v, NULL, 0) : 0);
                           }
                           break;
                   case SIGTERM:
                           Kill++;
                           break;
                   case SIGCHLD:
                           while (waitpid(-1, &stat, WNOHANG) > 0);
                           break;
           }
   }
   
   static int
   RtMsg(struct dwds_if **wds, struct rt_msghdr *msg, size_t len)
   {
           struct if_announcemsghdr *ifan;
           const u_char *v;
           struct ether_addr bssid;
           char szStr[STRSIZ] = { 0 }, szCmd[MAXPATHLEN] = { 0 }, szIdent[STRSIZ] = { 0 }, 
                szName[IFNAMSIZ] = { 0 };
           int f, stat;
   
           assert(wds);
           assert(msg);
   
           if (msg->rtm_version != RTM_VERSION) {
                   syslog(LOG_ERR, "Error:: routing message version %d not understood!\n", msg->rtm_version);
                   return -1;
           }
   
           switch (msg->rtm_type) {
                   case RTM_IFANNOUNCE:
                           ifan = (struct if_announcemsghdr*) msg;
                           switch (ifan->ifan_what) {
                                   case IFAN_ARRIVAL:
                                           VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: arrival\n", 
                                                           ifan->ifan_index);
                                           break;
                                   case IFAN_DEPARTURE:
                                           VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: departure\n", 
                                                           ifan->ifan_index);
                                           wifi_destroyWDS(ifan->ifan_name, wds);
                                           break;
                           }
                           break;
                   case RTM_IEEE80211:
   #define V(type) ((struct type *)(&ifan[1]))
                           ifan = (struct if_announcemsghdr*) msg;
                           switch (ifan->ifan_what) {
                                   case RTM_IEEE80211_DISASSOC:
                                           v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("discover_on_join"));
                                           if (!v || !strtol((char*) v, NULL, 0))
                                                   break;
                                           /* fall thru ... */
                                   case RTM_IEEE80211_LEAVE:
                                           if (!wifi_chkIface(ifan->ifan_name, ifs, nif))
                                                   break;
                                           memcpy(&bssid, V(ieee80211_leave_event)->iev_addr, ETHER_ADDR_LEN);
                                           VERB(1) syslog(LOG_INFO, "BSSID:%s Station leave\n", ether_ntoa(&bssid));
                                           if (!wifi_leaveWDS(bssid, wds, szName, IFNAMSIZ)) {
                                                   cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), 
                                                                   CFG(szIdent), STRSIZ, DWDS_NAME);
                                                   /* delete state file ... */
                                                   v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("state_dir"));
                                                   if (v) {
                                                           memset(szCmd, 0, STRSIZ);
                                                           snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v, 
                                                                           szName, ether_ntoa(&bssid), szIdent);
                                                           unlink(szCmd);
                                                           VERB(2) syslog(LOG_DEBUG, "Debug:: delete session name %s\n", szCmd);
                                                   }
   
                                                   /* Launch script ... */
                                                   cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("disassoc_event"), 
                                                                   CFG(szStr), STRSIZ, NULL);
                                                   if (*szStr) {
                                                           cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), 
                                                                           CFG(szIdent), STRSIZ, DWDS_NAME);
                                                           memset(szCmd, 0, MAXPATHLEN);
                                                           snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", szStr, 
                                                                           szName, ether_ntoa(&bssid), szIdent);
                                                           VERB(3) syslog(LOG_DEBUG, "Debug:: Command line: %s\n", szCmd);
   
                                                           if ((stat = system(szCmd)))
                                                                   syslog(LOG_ERR, "VAP down script %s exited "
                                                                                   "with status %d\n", szStr, stat);
                                                   }
                                           }
                                           break;
   
                                   case RTM_IEEE80211_JOIN:
                                   case RTM_IEEE80211_REJOIN:
                                   case RTM_IEEE80211_ASSOC:
                                   case RTM_IEEE80211_REASSOC:
                                           v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("discover_on_join"));
                                           if (!v || !strtol((char*) v, NULL, 0))
                                                   break;
                                           /* fall thru ... */
                                   case RTM_IEEE80211_WDS:
                                           memcpy(&bssid, V(ieee80211_leave_event)->iev_addr, ETHER_ADDR_LEN);
                                           VERB(1) syslog(LOG_INFO, "BSSID:%s WDS discovery\n", ether_ntoa(&bssid));
                                           if (!wifi_chkIface(ifan->ifan_name, ifs, nif))
                                                   break;
                                           if (!wifi_createWDS(ifan->ifan_name, bssid, wds)) {
                                                   cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), 
                                                                   CFG(szIdent), STRSIZ, DWDS_NAME);
                                                   /* create state file ... */
                                                   v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("state_dir"));
                                                   if (v) {
                                                           memset(szCmd, 0, MAXPATHLEN);
                                                           snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v, 
                                                                           (*wds)->if_name, ether_ntoa(&bssid), szIdent);
                                                           f = open(szCmd, O_WRONLY | O_CREAT, 0644);
                                                           if (f != -1)
                                                                   close(f);
                                                           VERB(2) syslog(LOG_DEBUG, "Debug:: create session name %s\n", szCmd);
                                                   }
   
                                                   /* Launch script ... */
                                                   cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("assoc_event"), 
                                                                   CFG(szStr), STRSIZ, NULL);
                                                   if (*szStr) {
                                                           memset(szCmd, 0, MAXPATHLEN);
                                                           snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", szStr, 
                                                                           (*wds)->if_name, ether_ntoa(&bssid), szIdent);
                                                           VERB(3) syslog(LOG_DEBUG, "Debug:: Command line: %s\n", szCmd);
   
                                                           if ((stat = system(szCmd)))
                                                                   syslog(LOG_ERR, "VAP up script %s exited "
                                                                                   "with status %d\n", szStr, stat);
                                                   }
                                           }
                                           break;
                           }
   #undef V
                           break;
           }
   
           return 0;
   }
   
   // ---------------------------------------------------------------
   
   int
   main(int argc, char **argv)
   {
           char ch, szStr[STRSIZ], fg = 0;
           const u_char *v, msg[2048];
           int s;
           struct sigaction sa;
           size_t len;
           struct dwds_if *wds = NULL;
   
           while ((ch = getopt(argc, argv, "hvfc:")) != -1)
                   switch (ch) {
                           case 'v':
                                   Verbose++;
                                   break;
                           case 'f':
                                   fg = 1;
                                   break;
                           case 'c':
                                   strlcpy(szConfig, optarg, MAXPATHLEN);
                                   break;
                           case 'h':
                           default:
                                   Usage();
                                   return 1;
                   }
           argc -= optind;
           argv += optind;
           if (!argc) {
                   printf("Error:: not specified interface for use ...\n");
                   Usage();
                   return 1;
           } else {
                   nif = argc;
                   ifs = argv;
           }
           if (LoadConfig(szConfig, &cfg)) {
                   printf("Error:: can`t load config %s ...\n", szConfig);
                   return 1;
           }
   
           if (!fg)
                   switch (fork()) {
                           case -1:
                                   printf("Error:: when fork() #%d - %s\n", errno, strerror(errno));
                                   UnloadConfig(&cfg);
                                   return 2;
                           case 0 :
                                   VERB(1) printf("Going to shadow land ...\n");
   
                                   setsid();
   
                                   memset(&sa, 0, sizeof sa);
                                   sa.sa_handler = sigHandler;
                                   sigemptyset(&sa.sa_mask);
                                   sigaction(SIGHUP, &sa, NULL);
                                   sigaction(SIGTERM, &sa, NULL);
                                   sigaction(SIGCHLD, &sa, NULL);
                                   break;
                           default:
                                   goto end;
                   }
   
           cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), CFG(szStr), STRSIZ, DWDS_NAME);
           openlog(szStr, LOG_PID | LOG_CONS, LOG_DAEMON);
           v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("syslog_upto"));
           setlogmask(v ? strtol((char*) v, NULL, 0) : 0);
   
           s = socket(PF_ROUTE, SOCK_RAW, 0);
           if (s == -1) {
                   syslog(LOG_ERR, "Error:: socket() #%d - %s\n", errno, strerror(errno));
                   goto end;
           }
   
           if (!(wds = wifi_buildWDS(s, ifs, nif))) {
                   syslog(LOG_ERR, "Error:: Go to dead ...\n");
                   goto end;
           }
   
           while (!Kill) {
                   len = read(s, (void*) msg, sizeof msg);
                   if (len == -1) {
                           VERB(5) syslog(LOG_ERR, "Error:: read() #%d - %s\n", errno, strerror(errno));
                           Kill++;
                   } else
                           RtMsg(&wds, (struct rt_msghdr*) msg, len);
           }
   
           close(s);
   end:
           closelog();
           UnloadConfig(&cfg);
           return 0;
   }

Removed from v.1.1  
changed lines
  Added in v.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>