Advertisement
Guest User

Untitled

a guest
Jan 24th, 2018
498
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 227.29 KB | None | 0 0
  1. /* -*- mode: c; c-basic-offset: 2 -*- */
  2. /*
  3.  * Copyright (C) 2007-2013 David Bird (Coova Technologies) <support@coova.com>
  4.  * Copyright (C) 2003-2005 Mondru AB.,
  5.  *
  6.  * This program is free software: you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation, either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */
  20.  
  21. #include "chilli.h"
  22. #include "bstrlib.h"
  23. #ifdef ENABLE_MODULES
  24. #include "chilli_module.h"
  25. #endif
  26.  
  27. struct tun_t *tun;                /* TUN instance            */
  28. struct ippool_t *ippool;          /* Pool of IP addresses */
  29. struct radius_t *radius;          /* Radius client instance */
  30. struct dhcp_t *dhcp = NULL;       /* DHCP instance */
  31. struct redir_t *redir = NULL;     /* Redir instance */
  32.  
  33. #ifdef ENABLE_MULTIROUTE
  34. #include "rtmon.h"
  35. struct rtmon_t _rtmon;
  36. #endif
  37.  
  38. static int connections=0;
  39. struct app_conn_t *firstfreeconn=0; /* First free in linked list */
  40. struct app_conn_t *lastfreeconn=0;  /* Last free in linked list */
  41. struct app_conn_t *firstusedconn=0; /* First used in linked list */
  42. struct app_conn_t *lastusedconn=0;  /* Last used in linked list */
  43. struct app_conn_t admin_session;
  44.  
  45. struct timespec mainclock;
  46. time_t checktime;
  47. time_t rereadtime;
  48.  
  49. static int *p_keep_going = 0;
  50. static int *p_reload_config = 0;
  51. /*static int do_timeouts = 1;*/
  52. static int do_interval = 0;
  53.  
  54. #ifdef ENABLE_UAMANYIP
  55. /* some IPv4LL/APIPA(rfc 3927) specific stuff for uamanyip */
  56. struct in_addr ipv4ll_ip;
  57. struct in_addr ipv4ll_mask;
  58. #endif
  59. #ifdef ENABLE_SSDP
  60. #define SSDP_MCAST_ADDR ("239.255.255.250")
  61. #define SSDP_PORT 1900
  62. struct in_addr ssdp;
  63. #endif
  64.  
  65. static int acct_req(acct_type type,
  66.             struct app_conn_t *conn,
  67.             uint8_t status_type);
  68.  
  69. static pid_t chilli_pid = 0;
  70.  
  71. #ifdef ENABLE_CHILLIPROXY
  72. static pid_t proxy_pid = 0;
  73. #endif
  74.  
  75. #ifdef ENABLE_CHILLIRADSEC
  76. static pid_t radsec_pid = 0;
  77. #endif
  78.  
  79. #ifdef ENABLE_CHILLIREDIR
  80. static pid_t redir_pid = 0;
  81. #endif
  82.  
  83. typedef struct child {
  84.   pid_t pid;
  85.   uint8_t type;
  86.   time_t started;
  87.   char *name;
  88.   struct child *next;
  89. } CHILD;
  90.  
  91. static unsigned long child_count_tot = 0;
  92. static int child_count = 0;
  93. CHILD * children = 0;
  94.  
  95. CHILD *child_create(uint8_t type, pid_t pid, char *name) {
  96.   CHILD *node;
  97.   if (!(node=malloc(sizeof(CHILD)))) return 0;
  98.   node->started = mainclock_now();
  99.   node->type = type;
  100.   node->pid = pid;
  101.   node->name = name;
  102.   node->next = 0;
  103.   return node;
  104. }
  105.  
  106. CHILD *child_insert_head(CHILD *list, uint8_t type, pid_t pid, char *name) {
  107.   CHILD *newnode = child_create(type, pid, name);
  108.   if (!newnode) return 0;
  109.   newnode->next = list;
  110.   return newnode;
  111. }
  112.  
  113. int child_add_pid(uint8_t type, pid_t pid, char *name) {
  114.   if (!children) {
  115.     /* Create the list head, the main process */
  116.     children = child_create(CHILLI_PROC, getpid(), "[chilli]");
  117.     if (!children) return -1;
  118.   }
  119.   children->next = child_insert_head(children->next, type, pid, name);
  120.   if (!children->next) return -1;
  121.   return 0;
  122. }
  123.  
  124. int child_remove_pid(pid_t pid) {
  125.   /* Will never be the head "children"-
  126.      which is the main process pid */
  127.   CHILD *list, *node;
  128.   if (children) {
  129.     list = children;
  130.     while (list->next && list->next->pid != pid)
  131.       list = list->next;
  132.  
  133.     if (list->next) {
  134.       node = list->next;
  135.       list->next = node->next;
  136. #if(_debug_)
  137.       if (_options.debug)
  138.         syslog(LOG_DEBUG, "%s(%d): Freed child process %d [%s]", __FUNCTION__, __LINE__, node->pid, node->name);
  139. #endif
  140.       free(node);
  141.       return 0;
  142.     }
  143.   }
  144.   return -1;
  145. }
  146.  
  147. #if defined(ENABLE_CHILLIREDIR) || defined(ENABLE_CHILLIPROXY) || defined(ENABLE_CHILLIRADSEC)
  148. static pid_t launch_daemon(char *name, char *path) {
  149.   pid_t cpid = getpid();
  150.   pid_t p = chilli_fork(CHILLI_PROC_DAEMON, name);
  151.  
  152.   if (p < 0) {
  153.  
  154.     syslog(LOG_ERR, "%s: fork failed", strerror(errno));
  155.  
  156.   } else if (p == 0) {
  157.  
  158.     char *newargs[16];
  159.     char file[128];
  160.     int i=0;
  161.  
  162.     chilli_binconfig(file, sizeof(file), cpid);
  163.  
  164.     newargs[i++] = name;
  165.     newargs[i++] = "-b";
  166.     newargs[i++] = file;
  167.     newargs[i++] = NULL;
  168.  
  169.     if (execv(path, newargs) != 0) {
  170.       syslog(LOG_ERR, "%s: execl() did not return 0!", strerror(errno));
  171.       exit(0);
  172.     }
  173.  
  174.   } else {
  175.  
  176.     return p;
  177.  
  178.   }
  179.  
  180.   return 0;
  181. }
  182. #endif
  183.  
  184. #ifdef ENABLE_CHILLIPROXY
  185. static void launch_chilliproxy() {
  186.   proxy_pid = launch_daemon("[chilli_proxy]", SBINDIR "/chilli_proxy");
  187. }
  188. #endif
  189.  
  190. #ifdef ENABLE_CHILLIREDIR
  191. static void launch_chilliredir() {
  192.   redir_pid = launch_daemon("[chilli_redir]", SBINDIR "/chilli_redir");
  193. }
  194. #endif
  195.  
  196. #ifdef ENABLE_CHILLIRADSEC
  197. static void launch_chilliradsec() {
  198.   radsec_pid = launch_daemon("[chilli_radsec]", SBINDIR "/chilli_radsec");
  199. }
  200. #endif
  201.  
  202. static int proc_status(char *name, pid_t pid) {
  203.   char buffer[128];
  204.   char * line = 0;
  205.   size_t len = 0;
  206.   int ret = 0;
  207.   ssize_t read;
  208.   FILE* fp;
  209.  
  210.   snprintf(buffer, sizeof(buffer), "/proc/%i/status", pid);
  211.   fp = fopen(buffer, "r");
  212.   if (!fp) return -1;
  213.  
  214.   while ((read = getline(&line, &len, fp)) != -1) {
  215.     if (!memcmp(line, name, strlen(name))) {
  216.       int i;
  217.       if (sscanf(line+strlen(name)+1, "%d %s", &i, buffer) == 2) {
  218.     ret = i;
  219.     if (buffer[0] == 'm') ret *= 1000;
  220.     else if (buffer[0] == 'g') ret *= 1000000;
  221.       }
  222.     }
  223.   }
  224.  
  225.   if (line)
  226.     free(line);
  227.  
  228.   fclose(fp);
  229.   return ret;
  230. }
  231.  
  232. static int proc_countfds(pid_t pid) {
  233.   char buffer[128];
  234.   int ret = 0;
  235.   DIR *dir;
  236.  
  237.   struct dirent * d = 0;
  238.  
  239.   snprintf(buffer, sizeof(buffer), "/proc/%i/fd", pid);
  240.   dir = opendir(buffer);
  241.   if (!dir) return -1;
  242.  
  243.   while ((d = readdir(dir)))
  244.     if (d->d_name[0] != '.')
  245.       ret++;
  246.  
  247.   closedir(dir);
  248.   return ret;
  249. }
  250.  
  251. void child_print(bstring s) {
  252.   time_t now = mainclock_now();
  253.   CHILD *node = children;
  254.   char line[256];
  255.  
  256.   snprintf(line, sizeof(line), "Children %d Max %d Total %ld\n",
  257.                 child_count, _options.childmax, child_count_tot);
  258.  
  259.   bcatcstr(s, line);
  260.  
  261.   while (node) {
  262.     char *n = "";
  263.     switch (node->type) {
  264.       case CHILLI_PROC:        n = "Main";     break;
  265.       case CHILLI_PROC_DAEMON: n = "Daemon";   break;
  266.       case CHILLI_PROC_REDIR:  n = "Redirect"; break;
  267.       case CHILLI_PROC_SCRIPT: n = "Script";   break;
  268.     }
  269.     snprintf(line, sizeof(line)-1,
  270.           "PID %8d %-8s %-20s up %d [Vm Size: %d RSS: %d FDs: %d]\n",
  271.           node->pid, n, node->name,
  272.           (int)(now - node->started),
  273.           proc_status("VmSize:", node->pid),
  274.           proc_status("VmRSS:", node->pid),
  275.           proc_countfds(node->pid));
  276.     bcatcstr(s, line);
  277.     node = node->next;
  278.   }
  279. }
  280.  
  281. void child_killall(int sig) {
  282.   CHILD *node = children;
  283.   while (node) {
  284.     kill(node->pid, sig);
  285.     if (_options.debug)
  286.       syslog(LOG_DEBUG, "%s(%d): pid %d killed %d", __FUNCTION__, __LINE__, getpid(), node->pid);
  287.     node = node->next;
  288.   }
  289. }
  290.  
  291. pid_t chilli_fork(uint8_t type, char *name) {
  292.   pid_t pid;
  293.  
  294.   if (child_count == _options.childmax) {
  295.     return -1;
  296.   }
  297.  
  298.   pid = fork();
  299.  
  300.   if (pid > 0) {
  301.     if (child_add_pid(type, pid, name) == 0) {
  302.       ++child_count;
  303.       ++child_count_tot;
  304.     }
  305.   }
  306.  
  307.   return pid;
  308. }
  309.  
  310. static void _sigchld(int signum) {
  311.   pid_t pid;
  312.   int stat;
  313.   while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
  314. #if(_debug_)
  315.     if (_options.debug)
  316.       syslog(LOG_DEBUG, "%s(%d): child %d terminated", __FUNCTION__, __LINE__, pid);
  317. #endif
  318. #ifdef ENABLE_CHILLIRADSEC
  319.     if (!_options.debug && radsec_pid > 0 && radsec_pid == pid) {
  320.       syslog(LOG_ERR, "Having to re-launch chilli_radsec... PID %d exited", pid);
  321.       launch_chilliradsec();
  322.     }
  323. #endif
  324. #ifdef ENABLE_CHILLIPROXY
  325.     if (!_options.debug && proxy_pid > 0 && proxy_pid == pid) {
  326.       syslog(LOG_ERR, "Having to re-launch chilli_proxy... PID %d exited", pid);
  327.       launch_chilliproxy();
  328.     }
  329. #endif
  330. #ifdef ENABLE_CHILLIREDIR
  331.     if (!_options.debug && redir_pid > 0 && redir_pid == pid) {
  332.       syslog(LOG_ERR, "Having to re-launch chilli_redir... PID %d exited", pid);
  333.       launch_chilliredir();
  334.     }
  335. #endif
  336.     if (child_remove_pid(pid) == 0)
  337.       child_count--;
  338.   }
  339. }
  340.  
  341. static void _sigterm(int signum) {
  342.   syslog(LOG_DEBUG, "%s(%d): SIGTERM: shutdown", __FUNCTION__, __LINE__);
  343.   if (p_keep_going)
  344.     *p_keep_going = 0;
  345. }
  346.  
  347. static void _sigvoid(int signum) {
  348. #if(_debug_)
  349.   syslog(LOG_DEBUG, "%s(%d): received %d signal", __FUNCTION__, __LINE__, signum);
  350. #endif
  351. }
  352.  
  353. static void _sigusr1(int signum) {
  354.   syslog(LOG_DEBUG, "%s(%d): SIGUSR1: reloading configuration", __FUNCTION__, __LINE__);
  355.  
  356.   if (p_reload_config)
  357.     *p_reload_config = 1;
  358.  
  359. #ifdef ENABLE_CHILLIREDIR
  360.   if (redir_pid)
  361.     kill(redir_pid, SIGUSR1);
  362. #endif
  363.  
  364. #ifdef ENABLE_CHILLIPROXY
  365.   if (proxy_pid)
  366.     kill(proxy_pid, SIGUSR1);
  367. #endif
  368.  
  369. #ifdef ENABLE_CHILLIRADSEC
  370.   if (radsec_pid)
  371.     kill(radsec_pid, SIGUSR1);
  372. #endif
  373.  
  374. }
  375.  
  376. static void _sighup(int signum) {
  377.   syslog(LOG_DEBUG, "%s(%d): SIGHUP: rereading configuration", __FUNCTION__, __LINE__);
  378.  
  379.   do_interval = 1;
  380. }
  381.  
  382. int chilli_handle_signal(void *ctx, int fd) {
  383.   int signo = selfpipe_read();
  384. #if(_debug_)
  385.   if (_options.debug)
  386.     syslog(LOG_DEBUG, "%s(%d): caught %d via selfpipe", __FUNCTION__, __LINE__,  signo);
  387. #endif
  388.   switch (signo) {
  389.     case SIGCHLD: _sigchld(signo); break;
  390.     case SIGPIPE: _sigvoid(signo); break;
  391.     case SIGHUP:  _sighup(signo);  break;
  392.     case SIGUSR1: _sigusr1(signo); break;
  393.     case SIGTERM:
  394.     case SIGINT:  _sigterm(signo); break;
  395.     default: return signo;
  396.   }
  397.   return 0;
  398. }
  399.  
  400. void chilli_signals(int *with_term, int *with_hup) {
  401.   selfpipe_trap(SIGCHLD);
  402.   selfpipe_trap(SIGPIPE);
  403.  
  404.   if (with_hup) {
  405.     p_reload_config = with_hup;
  406.     selfpipe_trap(SIGHUP);
  407.     selfpipe_trap(SIGUSR1);
  408.   }
  409.  
  410.   if (with_term) {
  411.     p_keep_going = with_term;
  412.     selfpipe_trap(SIGTERM);
  413.     selfpipe_trap(SIGINT);
  414.   }
  415. }
  416.  
  417. int chilli_binconfig(char *file, size_t flen, pid_t pid) {
  418.   if (pid == 0) {
  419.     char * bc = _options.binconfig;
  420.     if (bc) {
  421.       snprintf(file, flen, "%s", bc);
  422.       return 0;
  423.     } else {
  424.       pid = chilli_pid;
  425.       if (pid == 0)
  426.     pid = getpid();
  427.     }
  428.   }
  429.   snprintf(file, flen, DEFSTATEDIR "/chilli.%d.cfg.bin", pid);
  430.   return 0;
  431. }
  432.  
  433. int chilli_appconn_run(int (*cb)(struct app_conn_t *, void *), void *d) {
  434.   struct app_conn_t *appconn = firstusedconn;
  435.   while (appconn) {
  436.     if (cb(appconn, d))
  437.       return 1;
  438.     appconn = appconn->next;
  439.   }
  440.   return 0;
  441. }
  442.  
  443. #ifdef HAVE_LIBRT
  444. static struct timespec startup_real;
  445. static struct timespec startup_mono;
  446. #endif
  447.  
  448. static time_t start_tick = 0;
  449.  
  450. time_t mainclock_towall(time_t t) {
  451. #ifdef HAVE_LIBRT
  452.   if (startup_real.tv_sec)
  453.     return startup_real.tv_sec + (t - start_tick);
  454. #endif
  455.   return mainclock.tv_sec;
  456. }
  457.  
  458. time_t mainclock_wall() {
  459.   return mainclock_towall(mainclock.tv_sec);
  460. }
  461.  
  462. time_t mainclock_tick() {
  463. #ifdef HAVE_LIBRT
  464.   struct timespec ts;
  465. #if defined(CLOCK_MONOTONIC)
  466.   clockid_t cid = CLOCK_MONOTONIC;
  467. #else
  468.   clockid_t cid = CLOCK_REALTIME;
  469. #endif
  470.   int res = clock_gettime(cid, &ts);
  471.   if (res == -1 && errno == EINVAL) {
  472.     cid = CLOCK_REALTIME;
  473.     res = clock_gettime(cid, &ts);
  474.   }
  475.   if (res == -1) {
  476.     syslog(LOG_ERR, "%s: clock_gettime()", strerror(errno));
  477.     /* drop through to old time() */
  478.   } else {
  479.     mainclock.tv_sec = ts.tv_sec;
  480.     mainclock.tv_nsec = ts.tv_nsec;
  481.     return mainclock.tv_sec;
  482.   }
  483. #endif
  484.   if (time(&mainclock.tv_sec) == (time_t)-1) {
  485.     syslog(LOG_ERR, "%s: time()", strerror(errno));
  486.   }
  487.   return mainclock.tv_sec;
  488. }
  489.  
  490. time_t mainclock_now() {
  491.   return mainclock.tv_sec;
  492. }
  493.  
  494. time_t mainclock_rt() {
  495.   time_t rt = 0;
  496. #ifdef HAVE_LIBRT
  497.   struct timespec ts;
  498.   clockid_t cid = CLOCK_REALTIME;
  499.   if (clock_gettime(cid, &ts) < 0) {
  500.     syslog(LOG_ERR, "%s: clock_gettime()", strerror(errno));
  501.     /* drop through to old time() */
  502.   } else {
  503.     rt = ts.tv_sec;
  504.     return rt;
  505.   }
  506. #endif
  507.   if (time(&rt) == (time_t)-1) {
  508.     syslog(LOG_ERR, "%s: time()", strerror(errno));
  509.   }
  510.   return rt;
  511. }
  512.  
  513. int mainclock_rtdiff(time_t past) {
  514.   time_t rt = mainclock_rt();
  515.   return (int) difftime(rt, past);
  516. }
  517.  
  518. int mainclock_diff(time_t past) {
  519.   return (int) (mainclock.tv_sec - past);
  520. }
  521.  
  522. uint32_t mainclock_diffu(time_t past) {
  523.   int i = mainclock_diff(past);
  524.   if (i > 0) return (uint32_t) i;
  525.   return 0;
  526. }
  527.  
  528. void mainclock_tsdiff(struct timespec *out,
  529.               struct timespec *start,
  530.               struct timespec *end) {
  531.   if ((end->tv_nsec - start->tv_nsec) < 0) {
  532.     out->tv_sec = end->tv_sec - start->tv_sec-1;
  533.     out->tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec;
  534.   } else {
  535.     out->tv_sec = end->tv_sec - start->tv_sec;
  536.     out->tv_nsec = end->tv_nsec - start->tv_nsec;
  537.   }
  538. }
  539.  
  540. double mainclock_diffd(struct timespec * past) {
  541.   double d = 0;
  542.   struct timespec tsd;
  543.   mainclock_tsdiff(&tsd, past, &mainclock);
  544.   d  = tsd.tv_nsec;
  545.   d /= 1000000000.0;
  546.   d += tsd.tv_sec;
  547.   return d;
  548. }
  549.  
  550. uint8_t* chilli_called_station(struct session_state *state) {
  551. #ifdef ENABLE_LOCATION
  552.   if (_options.location_copy_called && state->redir.calledlen) {
  553.     return state->redir.called;
  554.   }
  555. #endif
  556.   return dhcp_nexthop(dhcp);
  557. }
  558.  
  559. static void set_sessionid(struct app_conn_t *appconn, char full) {
  560.   appconn->rt = (int) mainclock_rt();
  561.  
  562.   snprintf(appconn->s_state.sessionid,
  563.         sizeof(appconn->s_state.sessionid),
  564.         "%.8lx%.8x", appconn->rt, appconn->unit);
  565.  
  566.   appconn->s_state.redir.classlen = 0;
  567.   appconn->s_state.redir.statelen = 0;
  568.  
  569. #ifdef ENABLE_SESSIONID
  570.   if (full) {
  571.     uint8_t * his = appconn->hismac;
  572.     uint8_t * called = dhcp_nexthop(dhcp);
  573.     snprintf(appconn->s_state.chilli_sessionid,
  574.           sizeof(appconn->s_state.chilli_sessionid),
  575.           "SES-"
  576.           "%.2X%.2X%.2X%.2X%.2X%.2X-"
  577.           "%.2X%.2X%.2X%.2X%.2X%.2X-"
  578.           "%.8lx%.8x",
  579.           MAC_ARG(his), MAC_ARG(called),
  580.           appconn->rt, appconn->unit);
  581.   }
  582. #endif
  583. }
  584.  
  585. /* Used to write process ID to file. Assume someone else will delete */
  586. static void log_pid(char *pidfile) {
  587.   FILE *file;
  588.   mode_t oldmask;
  589.  
  590.   oldmask = umask(022);
  591.   file = fopen(pidfile, "w");
  592.   umask(oldmask);
  593.   if(!file) return;
  594.   fprintf(file, "%d\n", getpid());
  595.   fclose(file);
  596. }
  597.  
  598. #ifdef ENABLE_LEAKYBUCKET
  599. static inline void leaky_bucket_init(struct app_conn_t *conn) {
  600.  
  601.   if (_options.bwbucketupsize) {
  602.     conn->s_state.bucketupsize = _options.bwbucketupsize;
  603.   } else {
  604. #ifdef BUCKET_SIZE
  605.     conn->s_state.bucketupsize = BUCKET_SIZE;
  606. #else
  607.  
  608.     conn->s_state.bucketupsize =
  609.         conn->s_params.bandwidthmaxup / 8 * BUCKET_TIME;
  610.  
  611.     if (conn->s_state.bucketupsize < BUCKET_SIZE_MIN)
  612.       conn->s_state.bucketupsize = BUCKET_SIZE_MIN;
  613. #endif
  614.   }
  615.  
  616.   if (_options.bwbucketdnsize) {
  617.     conn->s_state.bucketdownsize = _options.bwbucketdnsize;
  618.   } else {
  619. #ifdef BUCKET_SIZE
  620.     conn->s_state.bucketdownsize = BUCKET_SIZE;
  621. #else
  622.  
  623.     conn->s_state.bucketdownsize =
  624.         conn->s_params.bandwidthmaxdown / 8 * BUCKET_TIME;
  625.  
  626.     if (conn->s_state.bucketdownsize < BUCKET_SIZE_MIN)
  627.       conn->s_state.bucketdownsize = BUCKET_SIZE_MIN;
  628. #endif
  629.   }
  630.  
  631.   if (_options.bwbucketminsize > 0) {
  632.     if (conn->s_state.bucketupsize < _options.bwbucketminsize)
  633.       conn->s_state.bucketupsize = _options.bwbucketminsize;
  634.     if (conn->s_state.bucketdownsize < _options.bwbucketminsize)
  635.       conn->s_state.bucketdownsize = _options.bwbucketminsize;
  636.   }
  637. }
  638.  
  639. /* Perform leaky bucket on up- and downlink traffic */
  640. static inline int
  641. leaky_bucket(struct app_conn_t *conn,
  642.          uint64_t octetsup, uint64_t octetsdown) {
  643.   int result = 0;
  644.   uint64_t upbytes=0, dnbytes=0;
  645.   long double timediff;
  646.  
  647.   timediff = mainclock_diffd(&conn->s_state.last_bw_time);
  648.  
  649.   if (conn->s_params.bandwidthmaxup) {
  650.     upbytes = (uint64_t) ((timediff * conn->s_params.bandwidthmaxup) / 8);
  651.  
  652.     if (!conn->s_state.bucketupsize) {
  653.       leaky_bucket_init(conn);
  654.     }
  655.  
  656.     if (conn->s_state.bucketup > upbytes) {
  657.       conn->s_state.bucketup -= upbytes;
  658.     }
  659.     else {
  660.       conn->s_state.bucketup = 0;
  661.     }
  662.  
  663.     if ((conn->s_state.bucketup + octetsup) >
  664.     conn->s_state.bucketupsize) {
  665.       if (_options.debug)
  666.     syslog(LOG_DEBUG, "%s(%d): Leaky bucket dropping upload overflow from "MAC_FMT, __FUNCTION__, __LINE__,
  667.                MAC_ARG(conn->hismac));
  668.       result = -1;
  669.     }
  670.     else {
  671.       conn->s_state.bucketup += octetsup;
  672.     }
  673.   }
  674.  
  675.   if (conn->s_params.bandwidthmaxdown) {
  676.     dnbytes = (uint64_t) ((timediff * conn->s_params.bandwidthmaxdown) / 8);
  677.  
  678.     if (!conn->s_state.bucketdownsize) {
  679.       leaky_bucket_init(conn);
  680.     }
  681.  
  682.     if (conn->s_state.bucketdown > dnbytes) {
  683.       conn->s_state.bucketdown -= dnbytes;
  684.     }
  685.     else {
  686.       conn->s_state.bucketdown = 0;
  687.     }
  688.  
  689.     if ((conn->s_state.bucketdown + octetsdown) >
  690.     conn->s_state.bucketdownsize) {
  691.       if (_options.debug)
  692.     syslog(LOG_DEBUG, "%s(%d): Leaky bucket dropping download overflow to "MAC_FMT, __FUNCTION__, __LINE__,
  693.                MAC_ARG(conn->hismac));
  694.       result = -1;
  695.     }
  696.     else {
  697.       conn->s_state.bucketdown += octetsdown;
  698.     }
  699.   }
  700.  
  701. #if(0)
  702.   if (_options.debug &&
  703.       (conn->s_params.bandwidthmaxup || conn->s_params.bandwidthmaxdown))
  704.     if (_options.debug)
  705.       syslog(LOG_DEBUG, "%s(%d): Leaky bucket: bucketup: %lld/%lld, " __FUNCTION__, __LINE__,
  706.              "bucketdown: %lld/%lld, up: %lld/(%lld), down: %lld/(%lld)",
  707.              conn->s_state.bucketup, conn->s_state.bucketupsize,
  708.              conn->s_state.bucketdown, conn->s_state.bucketdownsize,
  709.              octetsup, upbytes, octetsdown, dnbytes);
  710. #endif
  711.  
  712.   conn->s_state.last_bw_time.tv_sec = mainclock.tv_sec;
  713.   conn->s_state.last_bw_time.tv_nsec = mainclock.tv_nsec;
  714.  
  715.   return result;
  716. }
  717. #endif
  718.  
  719. void set_env(char *name, char type, void *value, int len) {
  720.   char *v=0;
  721.   char s[1024];
  722.  
  723.   memset(s,0,sizeof(s));
  724.  
  725.   switch(type) {
  726.  
  727.     case VAL_IN_ADDR:
  728.       strlcpy(s, inet_ntoa(*(struct in_addr *)value), sizeof(s));
  729.       v = s;
  730.       break;
  731.  
  732.     case VAL_MAC_ADDR:
  733.       {
  734.         uint8_t * mac = (uint8_t*)value;
  735.         snprintf(s, sizeof(s), MAC_FMT, MAC_ARG(mac));
  736.         v = s;
  737.       }
  738.       break;
  739.  
  740.     case VAL_ULONG:
  741.       snprintf(s, sizeof(s), "%ld", (long int)*(uint32_t *)value);
  742.       v = s;
  743.       break;
  744.  
  745.     case VAL_ULONG64:
  746.       snprintf(s, sizeof(s), "%ld", (long int)*(uint64_t *)value);
  747.       v = s;
  748.       break;
  749.  
  750.     case VAL_USHORT:
  751.       snprintf(s, sizeof(s), "%d", (int)(*(uint16_t *)value));
  752.       v = s;
  753.       break;
  754.  
  755.     case VAL_STRING:
  756.       if (len > 0) {
  757.         if (len > sizeof(s) - 1)
  758.           len = sizeof(s) - 1;
  759.         memcpy(s, (char*)value, len);
  760.         s[len]=0;
  761.         v = s;
  762.       } else {
  763.         v = (char*)value;
  764.       }
  765.       break;
  766.   }
  767.  
  768.   if (name != NULL && v != NULL) {
  769.     if (setenv(name, v, 1) != 0) {
  770.       syslog(LOG_ERR, "%s: setenv(%s, %s, 1) did not return 0!", strerror(errno), name, v);
  771.     }
  772.   }
  773. }
  774.  
  775. int runscript(struct app_conn_t *appconn, char* script,
  776.           char *loc, char *oloc) {
  777.   int status;
  778.   uint32_t sessiontime;
  779.  
  780.   if ((status = chilli_fork(CHILLI_PROC_SCRIPT, script)) < 0) {
  781.     syslog(LOG_ERR, "%s: forking %s", strerror(errno), script);
  782.     return 0;
  783.   }
  784.  
  785.   if (status > 0) { /* Parent */
  786.     return 0;
  787.   }
  788.  
  789. #ifdef ENABLE_LAYER3
  790.   if (_options.layer3)
  791.     set_env("LAYER3", VAL_STRING, "1", 0);
  792. #endif
  793.   set_env("DEV", VAL_STRING, tun(tun, 0).devname, 0);
  794.   set_env("NET", VAL_IN_ADDR, &appconn->net, 0);
  795.   set_env("MASK", VAL_IN_ADDR, &appconn->mask, 0);
  796.   set_env("ADDR", VAL_IN_ADDR, &appconn->ourip, 0);
  797.   set_env("USER_NAME", VAL_STRING, appconn->s_state.redir.username, 0);
  798.   set_env("NAS_IP_ADDRESS", VAL_IN_ADDR,&_options.radiuslisten, 0);
  799.   set_env("SERVICE_TYPE", VAL_STRING, "1", 0);
  800.   set_env("FRAMED_IP_ADDRESS", VAL_IN_ADDR, &appconn->hisip, 0);
  801.   set_env("FILTER_ID", VAL_STRING, appconn->s_params.filteridbuf, 0);
  802.   set_env("STATE", VAL_STRING, appconn->s_state.redir.statebuf, appconn->s_state.redir.statelen);
  803.   set_env("CLASS", VAL_STRING, appconn->s_state.redir.classbuf, appconn->s_state.redir.classlen);
  804.   set_env("CUI", VAL_STRING, appconn->s_state.redir.cuibuf, appconn->s_state.redir.cuilen);
  805.   set_env("SESSION_TIMEOUT", VAL_ULONG64, &appconn->s_params.sessiontimeout, 0);
  806.   set_env("IDLE_TIMEOUT", VAL_ULONG, &appconn->s_params.idletimeout, 0);
  807.   set_env("CALLING_STATION_ID", VAL_MAC_ADDR, appconn->hismac, 0);
  808.   set_env("CALLED_STATION_ID", VAL_MAC_ADDR, chilli_called_station(&appconn->s_state), 0);
  809.   set_env("NAS_ID", VAL_STRING, _options.radiusnasid, 0);
  810.   set_env("NAS_PORT_TYPE", VAL_STRING, "19", 0);
  811.   set_env("ACCT_SESSION_ID", VAL_STRING, appconn->s_state.sessionid, 0);
  812.   set_env("ACCT_INTERIM_INTERVAL", VAL_USHORT, &appconn->s_params.interim_interval, 0);
  813.   set_env("WISPR_LOCATION_ID", VAL_STRING, _options.radiuslocationid, 0);
  814.   set_env("WISPR_LOCATION_NAME", VAL_STRING, _options.radiuslocationname, 0);
  815.   set_env("WISPR_BANDWIDTH_MAX_UP", VAL_ULONG, &appconn->s_params.bandwidthmaxup, 0);
  816.   set_env("WISPR_BANDWIDTH_MAX_DOWN", VAL_ULONG, &appconn->s_params.bandwidthmaxdown, 0);
  817.   /*set_env("WISPR-SESSION_TERMINATE_TIME", VAL_USHORT, &appconn->sessionterminatetime, 0);*/
  818.   set_env("COOVACHILLI_MAX_INPUT_OCTETS", VAL_ULONG64, &appconn->s_params.maxinputoctets, 0);
  819.   set_env("COOVACHILLI_MAX_OUTPUT_OCTETS", VAL_ULONG64, &appconn->s_params.maxoutputoctets, 0);
  820.   set_env("COOVACHILLI_MAX_TOTAL_OCTETS", VAL_ULONG64, &appconn->s_params.maxtotaloctets, 0);
  821.   set_env("INPUT_OCTETS", VAL_ULONG64, &appconn->s_state.input_octets, 0);
  822.   set_env("OUTPUT_OCTETS", VAL_ULONG64, &appconn->s_state.output_octets, 0);
  823.   set_env("INPUT_PACKETS", VAL_ULONG64, &appconn->s_state.input_packets, 0);
  824.   set_env("OUTPUT_PACKETS", VAL_ULONG64, &appconn->s_state.output_packets, 0);
  825.   sessiontime = mainclock_diffu(appconn->s_state.start_time);
  826.   set_env("SESSION_TIME", VAL_ULONG, &sessiontime, 0);
  827.   sessiontime = mainclock_diffu(appconn->s_state.last_up_time);
  828.   set_env("IDLE_TIME", VAL_ULONG, &sessiontime, 0);
  829.  
  830.   if (loc) {
  831.     set_env("LOCATION", VAL_STRING, loc, 0);
  832.   }
  833.   if (oloc) {
  834.     set_env("OLD_LOCATION", VAL_STRING, oloc, 0);
  835.   }
  836.  
  837.   if (appconn->s_state.terminate_cause)
  838.     set_env("TERMINATE_CAUSE", VAL_ULONG,
  839.         &appconn->s_state.terminate_cause, 0);
  840.  
  841.   if (execl(
  842. #ifdef ENABLE_CHILLISCRIPT
  843.           SBINDIR "/chilli_script", SBINDIR "/chilli_script", _options.binconfig,
  844. #else
  845.           script,
  846. #endif
  847.           script, (char *) 0) != 0) {
  848.     syslog(LOG_ERR, "%s: exec %s failed", strerror(errno), script);
  849.   }
  850.  
  851.   exit(0);
  852. }
  853.  
  854. /***********************************************************
  855.  *
  856.  * Functions handling uplink protocol authentication.
  857.  * Called in response to radius access request response.
  858.  *
  859.  ***********************************************************/
  860.  
  861. static int newip(struct ippoolm_t **ipm, struct in_addr *hisip, uint8_t *hismac) {
  862.  
  863. #ifdef ENABLE_UAMANYIP
  864.   struct in_addr tmpip;
  865.  
  866.   if (_options.autostatip && hismac) {
  867.     if (!hisip) hisip = &tmpip;
  868.     hisip->s_addr = htonl((_options.autostatip % 255) * 0x1000000 +
  869.               hismac[3] * 0x10000 +
  870.               hismac[4] * 0x100 +
  871.               hismac[5]);
  872.   }
  873. #endif
  874.  
  875.   if (_options.debug)
  876.     syslog(LOG_DEBUG, "%s(%d): newip %s", __FUNCTION__, __LINE__,  inet_ntoa(*hisip));
  877.  
  878.   if (ippool_newip(ippool, ipm, hisip, 1)) {
  879.     if (ippool_newip(ippool, ipm, hisip, 0)) {
  880.       syslog(LOG_ERR, "Failed to allocate either static or dynamic IP address");
  881.       return -1;
  882.     }
  883.   }
  884.  
  885.   return 0;
  886. }
  887.  
  888.  
  889. /*
  890.  * A few functions to manage connections
  891.  */
  892.  
  893. static int initconn() {
  894.   checktime = rereadtime = mainclock.tv_sec;
  895.   return 0;
  896. }
  897.  
  898. int chilli_new_conn(struct app_conn_t **conn) {
  899.   int n;
  900.  
  901.   if (!firstfreeconn) {
  902.  
  903.     if (connections == _options.max_clients) {
  904.       syslog(LOG_ERR, "reached max connections %d!", _options.max_clients);
  905.       return -1;
  906.     }
  907.  
  908.     n = ++connections;
  909.  
  910.     if (!(*conn = calloc(1, sizeof(struct app_conn_t)))) {
  911.       syslog(LOG_ERR, "Out of memory!");
  912.       connections--;
  913.       return -1;
  914.     }
  915.  
  916.   } else {
  917.  
  918.     *conn = firstfreeconn;
  919.     n = (*conn)->unit;
  920.  
  921.     /* Remove from link of free */
  922.     if (firstfreeconn->next) {
  923.       firstfreeconn->next->prev = NULL;
  924.       firstfreeconn = firstfreeconn->next;
  925.     }
  926.     else { /* Took the last one */
  927.       firstfreeconn = NULL;
  928.       lastfreeconn = NULL;
  929.     }
  930.  
  931.     /* Initialise structures */
  932.     memset(*conn, 0, sizeof(struct app_conn_t));
  933.   }
  934.  
  935.   /* Initalise connection with default options */
  936.   session_param_defaults(&(*conn)->s_params);
  937.  
  938.   /* Insert into link of used */
  939.   if (firstusedconn) {
  940.     firstusedconn->prev = *conn;
  941.     (*conn)->next = firstusedconn;
  942.   }
  943.   else { /* First insert */
  944.     lastusedconn = *conn;
  945.   }
  946.  
  947.   firstusedconn = *conn;
  948.  
  949.   (*conn)->inuse = 1;
  950.   (*conn)->unit = n;
  951.  
  952.   return 0; /* Success */
  953. }
  954.  
  955. int static freeconn(struct app_conn_t *conn) {
  956.   int n = conn->unit;
  957.  
  958. #ifdef ENABLE_GARDENACCOUNTING
  959.   if (_options.uamgardendata) {
  960.     acct_req(ACCT_GARDEN, conn, RADIUS_STATUS_TYPE_STOP);
  961.   }
  962. #endif
  963.  
  964. #ifdef WITH_PATRICIA
  965.   if (conn->ptree)
  966.     patricia_destroy (conn->ptree, free);
  967. #endif
  968.  
  969. #if defined(ENABLE_LOCATION) && defined(HAVE_AVL)
  970.   /*remove from location list (if we have a location/are in list) !!??*/
  971.   if (conn->loc_search_node!=NULL) location_close_conn(conn,1);
  972. #endif
  973.  
  974.   /* Remove from link of used */
  975.   if ((conn->next) && (conn->prev)) {
  976.     conn->next->prev = conn->prev;
  977.     conn->prev->next = conn->next;
  978.   }
  979.   else if (conn->next) { /* && prev == 0 */
  980.     conn->next->prev = NULL;
  981.     firstusedconn = conn->next;
  982.   }
  983.   else if (conn->prev) { /* && next == 0 */
  984.     conn->prev->next = NULL;
  985.     lastusedconn = conn->prev;
  986.   }
  987.   else { /* if ((next == 0) && (prev == 0)) */
  988.     firstusedconn = NULL;
  989.     lastusedconn = NULL;
  990.   }
  991.  
  992.   /* Initialise structures */
  993.   memset(conn, 0, sizeof(struct app_conn_t));
  994.   conn->unit = n;
  995.  
  996.   /* Insert into link of free */
  997.   if (firstfreeconn) {
  998.     firstfreeconn->prev = conn;
  999.   }
  1000.   else { /* First insert */
  1001.     lastfreeconn = conn;
  1002.   }
  1003.  
  1004.   conn->next = firstfreeconn;
  1005.   firstfreeconn = conn;
  1006.  
  1007.   return 0;
  1008. }
  1009.  
  1010. int chilli_getconn(struct app_conn_t **conn, uint32_t ip,
  1011.            uint32_t nasip, uint32_t nasport) {
  1012.  
  1013.   struct app_conn_t *appconn = firstusedconn;
  1014.  
  1015.   while (appconn) {
  1016.  
  1017.     if (!appconn->inuse) {
  1018.       syslog(LOG_ERR, "Connection with inuse == 0!");
  1019.     }
  1020.  
  1021.     if (ip && appconn->hisip.s_addr == ip) {
  1022.       *conn = appconn;
  1023.       return 0;
  1024.     }
  1025.  
  1026.     if (nasip && nasport &&
  1027.     (appconn->nasip == nasip) && (appconn->nasport == nasport)) {
  1028.       *conn = appconn;
  1029.       return 0;
  1030.     }
  1031.  
  1032.     appconn = appconn->next;
  1033.   }
  1034.  
  1035.   return -1; /* Not found */
  1036. }
  1037.  
  1038. static int dnprot_terminate(struct app_conn_t *appconn) {
  1039.   appconn->s_state.authenticated = 0;
  1040. #ifdef ENABLE_SESSIONSTATE
  1041.   appconn->s_state.session_state = 0;
  1042. #endif
  1043.   if (appconn->s_params.url[0] &&
  1044.       appconn->s_params.flags & UAM_CLEAR_URL) {
  1045.     appconn->s_params.flags &= ~UAM_CLEAR_URL;
  1046.     appconn->s_params.url[0] = 0;
  1047.   }
  1048. #ifdef ENABLE_LEAKYBUCKET
  1049.   appconn->s_state.bucketup = 0;
  1050.   appconn->s_state.bucketdown = 0;
  1051.   appconn->s_state.bucketupsize = 0;
  1052.   appconn->s_state.bucketdownsize = 0;
  1053. #endif
  1054. #ifdef HAVE_NETFILTER_COOVA
  1055.   if (_options.kname) {
  1056.     kmod_coova_update(appconn);
  1057.   }
  1058. #endif
  1059. #ifdef ENABLE_LAYER3
  1060.   if (!_options.layer3)
  1061. #endif
  1062.     switch (appconn->dnprot) {
  1063.       case DNPROT_WPA:
  1064. #ifdef ENABLE_EAPOL
  1065.       case DNPROT_EAPOL:
  1066. #endif
  1067.         if (appconn->dnlink)
  1068.           ((struct dhcp_conn_t*) appconn->dnlink)->authstate = DHCP_AUTH_NONE;
  1069.         break;
  1070.       case DNPROT_MAC:
  1071.       case DNPROT_UAM:
  1072.       case DNPROT_DHCP_NONE:
  1073.       case DNPROT_NULL:
  1074.         if (appconn->dnlink)
  1075.           ((struct dhcp_conn_t*) appconn->dnlink)->authstate = DHCP_AUTH_DNAT;
  1076.         break;
  1077. #ifdef ENABLE_LAYER3
  1078.       case DNPROT_LAYER3:
  1079.         break;
  1080. #endif
  1081.       default:
  1082.         syslog(LOG_ERR, "Unknown downlink protocol");
  1083.         break;
  1084.     }
  1085.   return 0;
  1086. }
  1087.  
  1088.  
  1089.  
  1090. /* Check for:
  1091.  * - Session-Timeout
  1092.  * - Idle-Timeout
  1093.  * - Interim-Interim accounting
  1094.  * - Reread configuration file and DNS entries
  1095.  */
  1096.  
  1097. void session_interval(struct app_conn_t *conn) {
  1098.   uint32_t sessiontime;
  1099.   uint32_t idletime;
  1100.   uint32_t interimtime;
  1101.  
  1102.   sessiontime = mainclock_diffu(conn->s_state.start_time);
  1103.   idletime    = mainclock_diffu(conn->s_state.last_up_time);
  1104.   interimtime = mainclock_diffu(conn->s_state.interim_time);
  1105.  
  1106.   if (conn->s_state.authenticated == 1) {
  1107.     if ((conn->s_params.sessiontimeout) &&
  1108.     (sessiontime > conn->s_params.sessiontimeout)) {
  1109. #ifdef ENABLE_SESSIONSTATE
  1110.       conn->s_state.session_state =
  1111.           RADIUS_VALUE_COOVACHILLI_SESSION_TIMEOUT_REACHED;
  1112. #endif
  1113.       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
  1114.     }
  1115.     else if ((conn->s_params.sessionterminatetime) &&
  1116.          (mainclock_rtdiff(conn->s_params.sessionterminatetime) > 0)) {
  1117. #ifdef ENABLE_SESSIONSTATE
  1118.       conn->s_state.session_state =
  1119.           RADIUS_VALUE_COOVACHILLI_SESSION_LOGOUT_TIME_REACHED;
  1120. #endif
  1121.       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
  1122.     }
  1123.     else if ((conn->s_params.idletimeout) &&
  1124.          (idletime > conn->s_params.idletimeout)) {
  1125. #ifdef ENABLE_SESSIONSTATE
  1126.       conn->s_state.session_state =
  1127.           RADIUS_VALUE_COOVACHILLI_SESSION_IDLE_TIMEOUT_REACHED;
  1128. #endif
  1129.       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_IDLE_TIMEOUT);
  1130.     }
  1131.     else if ((conn->s_params.maxinputoctets) &&
  1132.          (conn->s_state.input_octets > conn->s_params.maxinputoctets)) {
  1133. #ifdef ENABLE_SESSIONSTATE
  1134.       conn->s_state.session_state =
  1135.           RADIUS_VALUE_COOVACHILLI_SESSION_IN_DATALIMIT_REACHED;
  1136. #endif
  1137.       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
  1138.     }
  1139.     else if ((conn->s_params.maxoutputoctets) &&
  1140.          (conn->s_state.output_octets > conn->s_params.maxoutputoctets)) {
  1141. #ifdef ENABLE_SESSIONSTATE
  1142.       conn->s_state.session_state =
  1143.           RADIUS_VALUE_COOVACHILLI_SESSION_OUT_DATALIMIT_REACHED;
  1144. #endif
  1145.       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
  1146.     }
  1147.     else if ((conn->s_params.maxtotaloctets) &&
  1148.          ((conn->s_state.input_octets + conn->s_state.output_octets) >
  1149.           conn->s_params.maxtotaloctets)) {
  1150. #ifdef ENABLE_SESSIONSTATE
  1151.       conn->s_state.session_state =
  1152.           RADIUS_VALUE_COOVACHILLI_SESSION_TOTAL_DATALIMIT_REACHED;
  1153. #endif
  1154.       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
  1155.     }
  1156.     else if ((conn->s_params.interim_interval) &&
  1157.          (interimtime >= conn->s_params.interim_interval)) {
  1158.  
  1159. #ifdef ENABLE_MODULES
  1160.       { int i;
  1161.     for (i=0; i < MAX_MODULES; i++) {
  1162.       if (!_options.modules[i].name[0]) break;
  1163.       if (_options.modules[i].ctx) {
  1164.         struct chilli_module *m =
  1165.                 (struct chilli_module *)_options.modules[i].ctx;
  1166.         if (m->session_update)
  1167.               m->session_update(conn);
  1168.       }
  1169.     }
  1170.       }
  1171. #endif
  1172.  
  1173.       acct_req(ACCT_USER, conn, RADIUS_STATUS_TYPE_INTERIM_UPDATE);
  1174.     }
  1175.   }
  1176. #ifdef ENABLE_GARDENACCOUNTING
  1177.   interimtime = mainclock_diffu(conn->s_state.garden_interim_time);
  1178.   if (_options.uamgardendata &&
  1179.       _options.definteriminterval &&
  1180.       interimtime >= _options.definteriminterval) {
  1181.     acct_req(ACCT_GARDEN, conn, RADIUS_STATUS_TYPE_INTERIM_UPDATE);
  1182.   }
  1183. #endif
  1184. }
  1185.  
  1186. static int checkconn() {
  1187.   struct app_conn_t *conn;
  1188.   struct dhcp_conn_t* dhcpconn;
  1189.   uint32_t checkdiff;
  1190.   uint32_t rereaddiff;
  1191.  
  1192. #ifdef HAVE_NETFILTER_COOVA
  1193.   if (_options.kname) {
  1194.     kmod_coova_sync();
  1195.   }
  1196. #endif
  1197.  
  1198.   checkdiff = mainclock_diffu(checktime);
  1199.  
  1200.   if (checkdiff < CHECK_INTERVAL)
  1201.     return 0;
  1202.  
  1203.   checktime = mainclock.tv_sec;
  1204.  
  1205.   if (admin_session.s_state.authenticated) {
  1206.     session_interval(&admin_session);
  1207.   }
  1208.  
  1209.   for (conn = firstusedconn; conn; conn=conn->next) {
  1210.     if (conn->inuse != 0) {
  1211.       if (
  1212. #ifdef ENABLE_LAYER3
  1213.               !_options.layer3 &&
  1214. #endif
  1215.               !(dhcpconn = (struct dhcp_conn_t *)conn->dnlink)) {
  1216.     syslog(LOG_WARNING, "No downlink protocol");
  1217.     continue;
  1218.       }
  1219.       session_interval(conn);
  1220.     }
  1221.   }
  1222.  
  1223.   /* Reread configuration file and recheck DNS */
  1224.   if (_options.interval) {
  1225.     rereaddiff = mainclock_diffu(rereadtime);
  1226.     if (rereaddiff >= _options.interval) {
  1227.       rereadtime = mainclock.tv_sec;
  1228.       do_interval = 1;
  1229.     }
  1230.   }
  1231.  
  1232.   return 0;
  1233. }
  1234.  
  1235. void chilli_freeconn() {
  1236.   struct app_conn_t *conn, *c;
  1237.   struct dhcp_conn_t *d = NULL;
  1238.  
  1239.   for (conn = firstusedconn; conn; ) {
  1240.     c = conn;
  1241.     conn = conn->next;
  1242.     d = (struct dhcp_conn_t *)c->dnlink;
  1243.     if (d) d->peer = NULL;
  1244.     free(c);
  1245.   }
  1246.  
  1247.   for (conn = firstfreeconn; conn; ) {
  1248.     c = conn;
  1249.     conn = conn->next;
  1250.     free(c);
  1251.   }
  1252. }
  1253.  
  1254. /* Kill all connections and send Radius Acct Stop */
  1255. int static killconn() {
  1256.   struct app_conn_t *conn;
  1257.  
  1258.   for (conn = firstusedconn; conn; conn = conn->next) {
  1259.     if ((conn->inuse != 0) && (conn->s_state.authenticated == 1)) {
  1260.       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_NAS_REBOOT);
  1261.     }
  1262.   }
  1263.  
  1264.   if (admin_session.s_state.authenticated) {
  1265.     admin_session.s_state.terminate_cause = RADIUS_TERMINATE_CAUSE_NAS_REBOOT;
  1266.     acct_req(ACCT_USER, &admin_session, RADIUS_STATUS_TYPE_STOP);
  1267.   }
  1268.  
  1269. #ifdef ENABLE_ACCOUNTING_ONOFF
  1270.   acct_req(ACCT_USER, &admin_session, RADIUS_STATUS_TYPE_ACCOUNTING_OFF);
  1271. #endif
  1272.  
  1273.   chilli_freeconn();
  1274.   return 0;
  1275. }
  1276.  
  1277. /* Compare a MAC address to the addresses given in the macallowed option */
  1278. int static maccmp(unsigned char *mac) {
  1279.   int i;
  1280.  
  1281.   for (i=0; i<_options.macoklen; i++)
  1282.     if (!memcmp(mac, _options.macok[i], PKT_ETH_ALEN))
  1283.       return 0;
  1284.  
  1285.   return -1;
  1286. }
  1287.  
  1288. int chilli_req_attrs(struct radius_t *radius,
  1289.              struct radius_packet_t *pack,
  1290.              acct_type type,
  1291.              uint32_t service_type,
  1292.              uint8_t status_type,
  1293.              uint32_t port,
  1294.              uint8_t *hismac,
  1295.              struct in_addr *hisip,
  1296.              struct session_state *state) {
  1297.   char *sessionid = state->sessionid;
  1298.   char mac[MACSTRLEN+1];
  1299.  
  1300.   switch(pack->code) {
  1301.     case RADIUS_CODE_ACCESS_REQUEST:
  1302.  
  1303.       if (_options.radiusoriginalurl) {
  1304.         if (state->redir.userurl[0])
  1305.           radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1306.                          RADIUS_VENDOR_COOVACHILLI,
  1307.                          RADIUS_ATTR_COOVACHILLI_ORIGINALURL,
  1308.                          0, (uint8_t *) state->redir.userurl,
  1309.                          strlen(state->redir.userurl));
  1310.  
  1311. #ifdef ENABLE_USERAGENT
  1312.         if (state->redir.useragent[0])
  1313.           radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1314.                          RADIUS_VENDOR_COOVACHILLI,
  1315.                          RADIUS_ATTR_COOVACHILLI_USER_AGENT,
  1316.                          0, (uint8_t *) state->redir.useragent,
  1317.                          strlen(state->redir.useragent));
  1318. #endif
  1319.  
  1320. #ifdef ENABLE_ACCEPTLANGUAGE
  1321.         if (state->redir.acceptlanguage[0])
  1322.           radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1323.                          RADIUS_VENDOR_COOVACHILLI,
  1324.                          RADIUS_ATTR_COOVACHILLI_ACCEPT_LANGUAGE,
  1325.                          0, (uint8_t *) state->redir.acceptlanguage,
  1326.                          strlen(state->redir.acceptlanguage));
  1327. #endif
  1328.       }
  1329.  
  1330.       break;
  1331.     default:
  1332.       break;
  1333.   }
  1334.  
  1335.   if (service_type)
  1336.     radius_addattr(radius, pack, RADIUS_ATTR_SERVICE_TYPE, 0, 0,
  1337.            service_type, NULL, 0);
  1338.  
  1339.   if (status_type)
  1340.     radius_addattr(radius, pack, RADIUS_ATTR_ACCT_STATUS_TYPE, 0, 0,
  1341.            status_type, NULL, 0);
  1342.  
  1343. #ifdef ENABLE_IEEE8021Q
  1344.   if (_options.ieee8021q && state->tag8021q) {
  1345.     radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1346.            RADIUS_VENDOR_COOVACHILLI, RADIUS_ATTR_COOVACHILLI_VLAN_ID,
  1347.            (uint32_t)ntohs(state->tag8021q & PKT_8021Q_MASK_VID), 0, 0);
  1348.   }
  1349. #endif
  1350.  
  1351. #ifdef ENABLE_GARDENACCOUNTING
  1352.   switch(type) {
  1353.     case ACCT_GARDEN:
  1354.       sessionid = state->garden_sessionid;
  1355.       break;
  1356.     case ACCT_USER:
  1357.     default:
  1358.       break;
  1359.   }
  1360. #endif
  1361.  
  1362.   if (*sessionid) {
  1363.     radius_addattr(radius, pack, RADIUS_ATTR_ACCT_SESSION_ID, 0, 0, 0,
  1364.            (uint8_t *)sessionid, strlen(sessionid));
  1365.   }
  1366.  
  1367. #ifdef ENABLE_SESSIONID
  1368.   if (state->chilli_sessionid[0]) {
  1369.     radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1370.            RADIUS_VENDOR_COOVACHILLI,
  1371.            RADIUS_ATTR_COOVACHILLI_SESSION_ID,
  1372.            0, (uint8_t *) state->chilli_sessionid,
  1373.            strlen(state->chilli_sessionid));
  1374.   }
  1375. #endif
  1376.  
  1377. #ifdef ENABLE_APSESSIONID
  1378.   if (state->ap_sessionid[0]) {
  1379.     radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1380.            RADIUS_VENDOR_COOVACHILLI,
  1381.            RADIUS_ATTR_COOVACHILLI_AP_SESSION_ID,
  1382.            0, (uint8_t *) state->ap_sessionid,
  1383.            strlen(state->ap_sessionid));
  1384.   }
  1385. #endif
  1386.  
  1387.   switch(type) {
  1388. #ifdef ENABLE_GARDENACCOUNTING
  1389.     case ACCT_GARDEN:
  1390.       break;
  1391. #endif
  1392.     case ACCT_USER:
  1393.       if (state->redir.classlen) {
  1394.         if (_options.debug)
  1395.           syslog(LOG_DEBUG, "%s(%d): RADIUS Request + Class(%zu)", __FUNCTION__, __LINE__,  state->redir.classlen);
  1396.         radius_addattr(radius, pack,
  1397.                        RADIUS_ATTR_CLASS, 0, 0, 0,
  1398.                        state->redir.classbuf,
  1399.                        state->redir.classlen);
  1400.       }
  1401.  
  1402.       if (state->redir.cuilen > 1) {
  1403.         if (_options.debug)
  1404.           syslog(LOG_DEBUG, "%s(%d): RADIUS Request + CUI(%zu)", __FUNCTION__, __LINE__, state->redir.cuilen);
  1405.         radius_addattr(radius, pack,
  1406.                        RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, 0, 0, 0,
  1407.                        state->redir.cuibuf,
  1408.                        state->redir.cuilen);
  1409.       }
  1410.  
  1411.       if (state->redir.statelen) {
  1412.         if (_options.debug)
  1413.           syslog(LOG_DEBUG, "%s(%d): RADIUS Request + State(%d)", __FUNCTION__, __LINE__, state->redir.statelen);
  1414.         radius_addattr(radius, pack,
  1415.                        RADIUS_ATTR_STATE, 0, 0, 0,
  1416.                        state->redir.statebuf,
  1417.                        state->redir.statelen);
  1418.       }
  1419.       break;
  1420.   }
  1421.  
  1422.   if (hisip && hisip->s_addr) {
  1423.     radius_addattr(radius, pack, RADIUS_ATTR_FRAMED_IP_ADDRESS, 0, 0,
  1424.            ntohl(hisip->s_addr), NULL, 0);
  1425.   }
  1426.  
  1427.   radius_addattr(radius, pack, RADIUS_ATTR_NAS_PORT_TYPE, 0, 0,
  1428.          _options.radiusnasporttype, NULL, 0);
  1429.  
  1430.   if (port) {
  1431.     char portid[16+1];
  1432.     snprintf(portid, sizeof(portid), "%.8d", port);
  1433.  
  1434.     radius_addattr(radius, pack, RADIUS_ATTR_NAS_PORT, 0, 0,
  1435.            port, NULL, 0);
  1436.  
  1437.     radius_addattr(radius, pack, RADIUS_ATTR_NAS_PORT_ID, 0, 0, 0,
  1438.            (uint8_t *) portid, strlen(portid));
  1439.   }
  1440.  
  1441.   /* Include his MAC address */
  1442.   if (hismac) {
  1443.     snprintf(mac, sizeof(mac), MAC_FMT, MAC_ARG(hismac));
  1444.  
  1445.     radius_addattr(radius, pack, RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0,
  1446.            (uint8_t*) mac, MACSTRLEN);
  1447.   }
  1448.  
  1449.   radius_addcalledstation(radius, pack, state);
  1450.  
  1451.   radius_addnasip(radius, pack);
  1452.  
  1453. #ifdef ENABLE_PROXYVSA
  1454.   radius_addvsa(pack, &state->redir);
  1455. #endif
  1456.  
  1457. #ifdef ENABLE_LOCATION
  1458.   if (state->location[0]) {
  1459.     radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1460.            RADIUS_VENDOR_COOVACHILLI,
  1461.            RADIUS_ATTR_COOVACHILLI_LOCATION,
  1462.            0, (uint8_t *) state->location,
  1463.            strlen(state->location));
  1464.     if (state->location_changes) {
  1465.       radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1466.              RADIUS_VENDOR_COOVACHILLI,
  1467.              RADIUS_ATTR_COOVACHILLI_LOCATION_CHANGE_COUNT,
  1468.              (uint32_t) state->location_changes, 0, 0);
  1469.     }
  1470.   }
  1471. #endif
  1472.  
  1473.   /* Include NAS-Identifier if given in configuration options */
  1474.   if (_options.radiusnasid) {
  1475.     radius_addattr(radius, pack, RADIUS_ATTR_NAS_IDENTIFIER, 0, 0, 0,
  1476.            (uint8_t*) _options.radiusnasid, strlen(_options.radiusnasid));
  1477.   }
  1478.  
  1479.   if (_options.radiuslocationid) {
  1480.     radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1481.            RADIUS_VENDOR_WISPR, RADIUS_ATTR_WISPR_LOCATION_ID, 0,
  1482.            (uint8_t*) _options.radiuslocationid,
  1483.            strlen(_options.radiuslocationid));
  1484.   }
  1485.  
  1486.   if (_options.radiuslocationname) {
  1487.     radius_addattr(radius, pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1488.            RADIUS_VENDOR_WISPR, RADIUS_ATTR_WISPR_LOCATION_NAME, 0,
  1489.            (uint8_t*) _options.radiuslocationname,
  1490.            strlen(_options.radiuslocationname));
  1491.   }
  1492.  
  1493. #ifdef ENABLE_MODULES
  1494.   { int i;
  1495.     for (i=0; i < MAX_MODULES; i++) {
  1496.       if (!_options.modules[i].name[0]) break;
  1497.       if (_options.modules[i].ctx) {
  1498.     struct chilli_module *m =
  1499.             (struct chilli_module *)_options.modules[i].ctx;
  1500.     if (m->radius_handler) {
  1501.       int res = m->radius_handler(radius, 0, pack, 0);
  1502.       switch (res) {
  1503.             case CHILLI_RADIUS_OK:
  1504.               break;
  1505.             default:
  1506.               return 0;
  1507.       }
  1508.     }
  1509.       }
  1510.     }
  1511.   }
  1512. #endif
  1513.  
  1514.   return 0;
  1515. }
  1516.  
  1517. int chilli_auth_radius(struct radius_t *radius) {
  1518.   struct radius_packet_t radius_pack;
  1519.   int ret = -1;
  1520.  
  1521.   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REQUEST)) {
  1522.     syslog(LOG_ERR, "radius_default_pack() failed");
  1523.     return ret;
  1524.   }
  1525.  
  1526.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
  1527.          (uint8_t *)_options.adminuser, strlen(_options.adminuser));
  1528.  
  1529.   if (_options.adminpasswd)
  1530.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0,
  1531.            (uint8_t *)_options.adminpasswd, strlen(_options.adminpasswd));
  1532.  
  1533.   chilli_req_attrs(radius, &radius_pack,
  1534.            ACCT_USER,
  1535.            RADIUS_SERVICE_TYPE_ADMIN_USER, 0,
  1536.            0, 0, 0,
  1537.            &admin_session.s_state);
  1538.  
  1539.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
  1540.          0, 0, 0, NULL, RADIUS_MD5LEN);
  1541.  
  1542.   return radius_req(radius, &radius_pack, &admin_session);
  1543. }
  1544.  
  1545. int static auth_radius(struct app_conn_t *appconn,
  1546.                char *username, char *password,
  1547.                uint8_t *dhcp_pkt, size_t dhcp_len) {
  1548.   struct dhcp_conn_t *dhcpconn = (struct dhcp_conn_t *)appconn->dnlink;
  1549.   struct radius_packet_t radius_pack;
  1550.   char mac[MACSTRLEN+1];
  1551.  
  1552.   uint32_t service_type = RADIUS_SERVICE_TYPE_LOGIN;
  1553.  
  1554.   if (!radius) return -1;
  1555.  
  1556.   if (_options.debug)
  1557.     syslog(LOG_DEBUG, "%s(%d): Starting radius authentication", __FUNCTION__, __LINE__);
  1558.  
  1559.   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REQUEST)) {
  1560.     syslog(LOG_ERR, "radius_default_pack() failed");
  1561.     return -1;
  1562.   }
  1563.  
  1564.   /* Include his MAC address */
  1565.   snprintf(mac, sizeof(mac), MAC_FMT, MAC_ARG(dhcpconn->hismac));
  1566.  
  1567.   if (!username) {
  1568.  
  1569.     service_type = RADIUS_SERVICE_TYPE_FRAMED;
  1570.  
  1571.     strlcpy(appconn->s_state.redir.username, mac, USERNAMESIZE);
  1572.  
  1573.     if (_options.macsuffix) {
  1574.       size_t ulen = strlen(appconn->s_state.redir.username);
  1575.       strlcpy(appconn->s_state.redir.username + ulen,
  1576.               _options.macsuffix, USERNAMESIZE - ulen);
  1577.     }
  1578.  
  1579.     username = appconn->s_state.redir.username;
  1580.  
  1581.   } else {
  1582.  
  1583.     strlcpy(appconn->s_state.redir.username, username, USERNAMESIZE);
  1584.  
  1585.   }
  1586.  
  1587.   if (!password) {
  1588.     password = _options.macpasswd;
  1589.     if (!password) {
  1590.       password = appconn->s_state.redir.username;
  1591.     }
  1592.   }
  1593.  
  1594.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
  1595.          (uint8_t *) username, strlen(username));
  1596.  
  1597.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0,
  1598.          (uint8_t *) password, strlen(password));
  1599.  
  1600.   appconn->authtype = PAP_PASSWORD;
  1601.  
  1602. #ifdef ENABLE_DHCPRADIUS
  1603.   if (_options.dhcpradius && dhcp_pkt) {
  1604.     struct dhcp_tag_t *tag = 0;
  1605.     struct pkt_udphdr_t *udph = pkt_udphdr(dhcp_pkt);
  1606.     struct dhcp_packet_t *dhcppkt = pkt_dhcppkt(dhcp_pkt);
  1607.  
  1608. #define maptag(OPT,VSA) tag=0;                                          \
  1609.     if (!dhcp_gettag(dhcppkt, ntohs(udph->len)-PKT_UDP_HLEN, &tag, OPT)) { \
  1610.       radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC, \
  1611.                      RADIUS_VENDOR_COOVACHILLI, VSA, 0,                 \
  1612.                      (uint8_t *) tag->v, tag->l); }
  1613.     /*
  1614.      *  Mapping of DHCP options to RADIUS Vendor Specific Attributes
  1615.      */
  1616.     maptag( DHCP_OPTION_PARAMETER_REQUEST_LIST,
  1617.         RADIUS_ATTR_COOVACHILLI_DHCP_PARAMETER_REQUEST_LIST );
  1618.     maptag( DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
  1619.         RADIUS_ATTR_COOVACHILLI_DHCP_VENDOR_CLASS_ID );
  1620.     maptag( DHCP_OPTION_CLIENT_IDENTIFIER,
  1621.         RADIUS_ATTR_COOVACHILLI_DHCP_CLIENT_ID );
  1622.     maptag( DHCP_OPTION_CLIENT_FQDN,
  1623.         RADIUS_ATTR_COOVACHILLI_DHCP_CLIENT_FQDN );
  1624.     maptag( DHCP_OPTION_HOSTNAME,
  1625.         RADIUS_ATTR_COOVACHILLI_DHCP_HOSTNAME );
  1626. #undef maptag
  1627.   }
  1628. #endif
  1629.  
  1630.   chilli_req_attrs(radius, &radius_pack,
  1631.            ACCT_USER, service_type, 0,
  1632.            appconn->unit, appconn->hismac,
  1633.            &appconn->hisip, &appconn->s_state);
  1634.  
  1635.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
  1636.          0, 0, 0, NULL, RADIUS_MD5LEN);
  1637.  
  1638.   return radius_req(radius, &radius_pack, appconn);
  1639. }
  1640.  
  1641.  
  1642. #ifdef ENABLE_RADPROXY
  1643. /*********************************************************
  1644.  * radius proxy functions
  1645.  * Used to send a response to a received radius request
  1646.  *********************************************************/
  1647.  
  1648. /* Reply with an access reject */
  1649. int static radius_access_reject(struct app_conn_t *conn) {
  1650.   struct radius_packet_t radius_pack;
  1651.  
  1652.   conn->radiuswait = 0;
  1653.  
  1654.   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REJECT)) {
  1655.     syslog(LOG_ERR, "radius_default_pack() failed");
  1656.     return -1;
  1657.   }
  1658.  
  1659.   radius_pack.id = conn->radiusid;
  1660.   radius_resp(radius, &radius_pack, &conn->radiuspeer, conn->authenticator);
  1661.   return 0;
  1662. }
  1663.  
  1664. /* Reply with an access challenge */
  1665. int static radius_access_challenge(struct app_conn_t *conn) {
  1666.   struct radius_packet_t radius_pack;
  1667.   size_t offset = 0;
  1668.   size_t eaplen = 0;
  1669.  
  1670.   if (_options.debug)
  1671.     syslog(LOG_DEBUG, "%s(%d): Sending RADIUS AccessChallenge to client", __FUNCTION__, __LINE__);
  1672.  
  1673.   conn->radiuswait = 0;
  1674.  
  1675.   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_CHALLENGE)) {
  1676.     syslog(LOG_ERR, "radius_default_pack() failed");
  1677.     return -1;
  1678.   }
  1679.  
  1680.   radius_pack.id = conn->radiusid;
  1681.  
  1682.   /* Include EAP */
  1683.   do {
  1684.     if ((conn->challen - offset) > RADIUS_ATTR_VLEN)
  1685.       eaplen = RADIUS_ATTR_VLEN;
  1686.     else
  1687.       eaplen = conn->challen - offset;
  1688.  
  1689.     if (radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
  1690.                conn->chal + offset, eaplen)) {
  1691.       syslog(LOG_ERR, "radius_default_pack() failed");
  1692.       return -1;
  1693.     }
  1694.     offset += eaplen;
  1695.   }
  1696.   while (offset < conn->challen);
  1697.  
  1698.   if (conn->s_state.redir.statelen) {
  1699.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_STATE, 0, 0, 0,
  1700.            conn->s_state.redir.statebuf,
  1701.            conn->s_state.redir.statelen);
  1702.   }
  1703.  
  1704.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
  1705.          0, 0, 0, NULL, RADIUS_MD5LEN);
  1706.  
  1707.   radius_resp(radius, &radius_pack, &conn->radiuspeer, conn->authenticator);
  1708.   return 0;
  1709. }
  1710.  
  1711. /* Send off an access accept */
  1712.  
  1713. int static radius_access_accept(struct app_conn_t *conn) {
  1714.   struct radius_packet_t radius_pack;
  1715.   size_t offset = 0;
  1716.   size_t eaplen = 0;
  1717.  
  1718.   uint8_t mppekey[RADIUS_ATTR_VLEN];
  1719.   size_t mppelen;
  1720.  
  1721.   conn->radiuswait = 0;
  1722.  
  1723.   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_ACCEPT)) {
  1724.     syslog(LOG_ERR, "radius_default_pack() failed");
  1725.     return -1;
  1726.   }
  1727.  
  1728.   radius_pack.id = conn->radiusid;
  1729.  
  1730.   /* Include EAP (if present) */
  1731.   offset = 0;
  1732.   while (offset < conn->challen) {
  1733.     if ((conn->challen - offset) > RADIUS_ATTR_VLEN)
  1734.       eaplen = RADIUS_ATTR_VLEN;
  1735.     else
  1736.       eaplen = conn->challen - offset;
  1737.  
  1738.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
  1739.            conn->chal + offset, eaplen);
  1740.  
  1741.     offset += eaplen;
  1742.   }
  1743.  
  1744.   if (conn->sendlen) {
  1745.     radius_keyencode(radius, mppekey, RADIUS_ATTR_VLEN,
  1746.              &mppelen, conn->sendkey,
  1747.              conn->sendlen, conn->authenticator,
  1748.              radius->proxysecret, radius->proxysecretlen);
  1749.  
  1750.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1751.            RADIUS_VENDOR_MS, RADIUS_ATTR_MS_MPPE_SEND_KEY, 0,
  1752.            (uint8_t *)mppekey, mppelen);
  1753.   }
  1754.  
  1755.   if (conn->recvlen) {
  1756.     radius_keyencode(radius, mppekey, RADIUS_ATTR_VLEN,
  1757.              &mppelen, conn->recvkey,
  1758.              conn->recvlen, conn->authenticator,
  1759.              radius->proxysecret, radius->proxysecretlen);
  1760.  
  1761.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1762.            RADIUS_VENDOR_MS, RADIUS_ATTR_MS_MPPE_RECV_KEY, 0,
  1763.            (uint8_t *)mppekey, mppelen);
  1764.   }
  1765.  
  1766.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
  1767.          0, 0, 0, NULL, RADIUS_MD5LEN);
  1768.  
  1769.   radius_resp(radius, &radius_pack, &conn->radiuspeer, conn->authenticator);
  1770.   return 0;
  1771. }
  1772. #endif
  1773.  
  1774. /*********************************************************
  1775.  * radius accounting functions
  1776.  * Used to send accounting request to radius server
  1777.  *********************************************************/
  1778.  
  1779. static int acct_req(acct_type type,
  1780.             struct app_conn_t *conn, uint8_t status_type)
  1781. {
  1782.   struct radius_packet_t radius_pack;
  1783.   uint32_t service_type = 0;
  1784.   uint32_t timediff;
  1785. #ifdef ENABLE_GARDENACCOUNTING
  1786.   char incl_garden = 0;
  1787. #endif
  1788.  
  1789.   switch(status_type) {
  1790.     case RADIUS_STATUS_TYPE_START:
  1791.     case RADIUS_STATUS_TYPE_ACCOUNTING_ON:
  1792.       conn->s_state.start_time = mainclock.tv_sec;
  1793.       conn->s_state.interim_time = mainclock.tv_sec;
  1794.       conn->s_state.last_time = mainclock.tv_sec;
  1795.       conn->s_state.last_up_time = mainclock.tv_sec;
  1796.       switch(type) {
  1797. #ifdef ENABLE_GARDENACCOUNTING
  1798.         case ACCT_GARDEN:
  1799.           snprintf(conn->s_state.garden_sessionid,
  1800.                         sizeof(conn->s_state.garden_sessionid),
  1801.                         "UAM-%s-%.8x%.8x", inet_ntoa(conn->hisip),
  1802.                         (int) mainclock_rt(), conn->unit);
  1803.           conn->s_state.garden_start_time = mainclock.tv_sec;
  1804.           conn->s_state.garden_interim_time = mainclock.tv_sec;
  1805.           conn->s_state.garden_input_octets = 0;
  1806.           conn->s_state.garden_output_octets = 0;
  1807.           conn->s_state.other_input_octets = 0;
  1808.           conn->s_state.other_output_octets = 0;
  1809.           break;
  1810. #endif
  1811.         case ACCT_USER:
  1812.           conn->s_state.input_packets = 0;
  1813.           conn->s_state.output_packets = 0;
  1814.           conn->s_state.input_octets = 0;
  1815.           conn->s_state.output_octets = 0;
  1816.           break;
  1817.       }
  1818.       break;
  1819.  
  1820.     case RADIUS_STATUS_TYPE_INTERIM_UPDATE:
  1821.       conn->s_state.interim_time = mainclock.tv_sec;
  1822.       /* drop through */
  1823.  
  1824.     case RADIUS_STATUS_TYPE_STOP:
  1825.       switch(type) {
  1826. #ifdef ENABLE_GARDENACCOUNTING
  1827.         case ACCT_GARDEN:
  1828.           conn->s_state.garden_interim_time = mainclock.tv_sec;
  1829.           if (!conn->s_state.garden_interim_time)
  1830.             return 0;
  1831. #endif
  1832.         case ACCT_USER:
  1833.           break;
  1834.       }
  1835.       break;
  1836.   }
  1837.  
  1838.   /*
  1839.    *  Return if there is no RADIUS accounting for this session.
  1840.    */
  1841.   if (conn->s_params.flags & NO_ACCOUNTING)
  1842.     return 0;
  1843.  
  1844.   /*
  1845.    *  Build and send RADIUS Accounting.
  1846.    */
  1847.   if (radius_default_pack(radius, &radius_pack,
  1848.               RADIUS_CODE_ACCOUNTING_REQUEST)) {
  1849.     syslog(LOG_ERR, "radius_default_pack() failed");
  1850.     return -1;
  1851.   }
  1852.  
  1853.   if (RADIUS_STATUS_TYPE_ACCOUNTING_ON  != status_type &&
  1854.       RADIUS_STATUS_TYPE_ACCOUNTING_OFF != status_type) {
  1855.  
  1856.     switch(type) {
  1857. #ifdef ENABLE_GARDENACCOUNTING
  1858.       case ACCT_GARDEN:
  1859.         break;
  1860. #endif
  1861.       case ACCT_USER:
  1862.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
  1863.                        (uint8_t*) conn->s_state.redir.username,
  1864.                        strlen(conn->s_state.redir.username));
  1865.         break;
  1866.     }
  1867.  
  1868.     if (conn->is_adminsession) {
  1869.  
  1870.       service_type = RADIUS_SERVICE_TYPE_ADMIN_USER;
  1871. #ifdef ENABLE_GARDENACCOUNTING
  1872.       incl_garden = 1;
  1873. #endif
  1874.  
  1875. #if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
  1876.       {
  1877.     struct sysinfo the_info;
  1878.  
  1879.     if (sysinfo(&the_info)) {
  1880.  
  1881.       syslog(LOG_ERR, "%s: sysinfo()", strerror(errno));
  1882.  
  1883.     } else {
  1884.       float shiftfloat;
  1885.       float fav[3];
  1886.       char b[128];
  1887.  
  1888.       shiftfloat = (float) (1<<SI_LOAD_SHIFT);
  1889.  
  1890.       fav[0]=((float)the_info.loads[0])/shiftfloat;
  1891.       fav[1]=((float)the_info.loads[1])/shiftfloat;
  1892.       fav[2]=((float)the_info.loads[2])/shiftfloat;
  1893.  
  1894.       radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1895.              RADIUS_VENDOR_COOVACHILLI, RADIUS_ATTR_COOVACHILLI_SYS_UPTIME,
  1896.              (uint32_t) the_info.uptime, NULL, 0);
  1897.  
  1898.       snprintf(b, sizeof(b), "%f %f %f",fav[0],fav[1],fav[2]);
  1899.  
  1900.       radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  1901.              RADIUS_VENDOR_COOVACHILLI, RADIUS_ATTR_COOVACHILLI_SYS_LOADAVG,
  1902.              0, (uint8_t *) b, strlen(b));
  1903.  
  1904.       snprintf(b, sizeof(b), "%ld %ld %ld %ld",
  1905.                         the_info.totalram,
  1906.                         the_info.freeram,
  1907.                         the_info.sharedram,
  1908.                         the_info.bufferram);
  1909.  
  1910.       radius_addattr(radius, &radius_pack,
  1911.              RADIUS_ATTR_VENDOR_SPECIFIC,
  1912.              RADIUS_VENDOR_COOVACHILLI,
  1913.              RADIUS_ATTR_COOVACHILLI_SYS_MEMORY,
  1914.              0, (uint8_t *) b, strlen(b));
  1915.     }
  1916.       }
  1917. #endif
  1918.     }
  1919.   }
  1920.  
  1921.   if (status_type == RADIUS_STATUS_TYPE_STOP ||
  1922.       status_type == RADIUS_STATUS_TYPE_INTERIM_UPDATE) {
  1923.  
  1924.     switch(type) {
  1925. #ifdef ENABLE_GARDENACCOUNTING
  1926.       case ACCT_GARDEN:
  1927.         incl_garden = 1;
  1928.         if (!conn->s_state.garden_start_time) {
  1929.           if (_options.debug)
  1930.             syslog(LOG_DEBUG, "%s(%d): session hasn't started yet", __FUNCTION__, __LINE__);
  1931.           return 0;
  1932.         }
  1933.         timediff = mainclock_diffu(conn->s_state.garden_start_time);
  1934.  
  1935.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_SESSION_TIME, 0, 0,
  1936.                        timediff, NULL, 0);
  1937.         break;
  1938. #endif
  1939.       case ACCT_USER:
  1940.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_INPUT_OCTETS, 0, 0,
  1941.                        (uint32_t) conn->s_state.input_octets, NULL, 0);
  1942.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_OUTPUT_OCTETS, 0, 0,
  1943.                        (uint32_t) conn->s_state.output_octets, NULL, 0);
  1944.  
  1945.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
  1946.                        0, 0, (uint32_t) (conn->s_state.input_octets >> 32), NULL, 0);
  1947.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
  1948.                        0, 0, (uint32_t) (conn->s_state.output_octets >> 32), NULL, 0);
  1949.  
  1950.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_INPUT_PACKETS, 0, 0,
  1951.                        conn->s_state.input_packets, NULL, 0);
  1952.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_OUTPUT_PACKETS, 0, 0,
  1953.                        conn->s_state.output_packets, NULL, 0);
  1954.  
  1955.         timediff = mainclock_diffu(conn->s_state.start_time);
  1956.  
  1957.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_SESSION_TIME, 0, 0,
  1958.                        timediff, NULL, 0);
  1959.         break;
  1960.     }
  1961.  
  1962. #ifdef ENABLE_GARDENACCOUNTING
  1963.     if (incl_garden && _options.uamgardendata) {
  1964.       radius_addattr(radius, &radius_pack,
  1965.              RADIUS_ATTR_VENDOR_SPECIFIC,
  1966.              RADIUS_VENDOR_COOVACHILLI,
  1967.              RADIUS_ATTR_COOVACHILLI_GARDEN_INPUT_OCTETS,
  1968.              (uint32_t) conn->s_state.garden_input_octets, NULL, 0);
  1969.       radius_addattr(radius, &radius_pack,
  1970.              RADIUS_ATTR_VENDOR_SPECIFIC,
  1971.              RADIUS_VENDOR_COOVACHILLI,
  1972.              RADIUS_ATTR_COOVACHILLI_GARDEN_OUTPUT_OCTETS,
  1973.              (uint32_t) conn->s_state.garden_output_octets, NULL, 0);
  1974.  
  1975.       radius_addattr(radius, &radius_pack,
  1976.              RADIUS_ATTR_VENDOR_SPECIFIC,
  1977.              RADIUS_VENDOR_COOVACHILLI,
  1978.              RADIUS_ATTR_COOVACHILLI_GARDEN_INPUT_GIGAWORDS,
  1979.              (uint32_t) (conn->s_state.garden_input_octets >> 32), NULL, 0);
  1980.       radius_addattr(radius, &radius_pack,
  1981.              RADIUS_ATTR_VENDOR_SPECIFIC,
  1982.              RADIUS_VENDOR_COOVACHILLI,
  1983.              RADIUS_ATTR_COOVACHILLI_GARDEN_OUTPUT_GIGAWORDS,
  1984.              (uint32_t) (conn->s_state.garden_output_octets >> 32), NULL, 0);
  1985.  
  1986.       if (_options.uamotherdata) {
  1987.     radius_addattr(radius, &radius_pack,
  1988.                RADIUS_ATTR_VENDOR_SPECIFIC,
  1989.                RADIUS_VENDOR_COOVACHILLI,
  1990.                RADIUS_ATTR_COOVACHILLI_OTHER_INPUT_OCTETS,
  1991.                (uint32_t) conn->s_state.other_input_octets, NULL, 0);
  1992.     radius_addattr(radius, &radius_pack,
  1993.                RADIUS_ATTR_VENDOR_SPECIFIC,
  1994.                RADIUS_VENDOR_COOVACHILLI,
  1995.                RADIUS_ATTR_COOVACHILLI_OTHER_OUTPUT_OCTETS,
  1996.                (uint32_t) conn->s_state.other_output_octets, NULL, 0);
  1997.  
  1998.     radius_addattr(radius, &radius_pack,
  1999.                RADIUS_ATTR_VENDOR_SPECIFIC,
  2000.                RADIUS_VENDOR_COOVACHILLI,
  2001.                RADIUS_ATTR_COOVACHILLI_OTHER_INPUT_GIGAWORDS,
  2002.                (uint32_t) (conn->s_state.other_input_octets >> 32), NULL, 0);
  2003.     radius_addattr(radius, &radius_pack,
  2004.                RADIUS_ATTR_VENDOR_SPECIFIC,
  2005.                RADIUS_VENDOR_COOVACHILLI,
  2006.                RADIUS_ATTR_COOVACHILLI_OTHER_OUTPUT_GIGAWORDS,
  2007.                (uint32_t) (conn->s_state.other_output_octets >> 32), NULL, 0);
  2008.       }
  2009.     }
  2010. #endif
  2011.   }
  2012.  
  2013.   if (status_type == RADIUS_STATUS_TYPE_STOP ||
  2014.       status_type == RADIUS_STATUS_TYPE_ACCOUNTING_OFF) {
  2015.  
  2016.     switch(type) {
  2017. #ifdef ENABLE_GARDENACCOUNTING
  2018.       case ACCT_GARDEN:
  2019.         break;
  2020. #endif
  2021.       case ACCT_USER:
  2022.         radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
  2023.                        0, 0, conn->s_state.terminate_cause, NULL, 0);
  2024.         break;
  2025.     }
  2026.   }
  2027.  
  2028. #ifdef ENABLE_SESSIONSTATE
  2029.   if (conn->s_state.session_state) {
  2030.     radius_addattr(radius, &radius_pack,
  2031.            RADIUS_ATTR_VENDOR_SPECIFIC,
  2032.            RADIUS_VENDOR_COOVACHILLI,
  2033.            RADIUS_ATTR_COOVACHILLI_SESSION_STATE,
  2034.            conn->s_state.session_state, 0, 0);
  2035.   }
  2036. #endif
  2037.  
  2038.   chilli_req_attrs(radius, &radius_pack,
  2039.            type, service_type, status_type,
  2040.            conn->unit, conn->hismac,
  2041.            &conn->hisip,
  2042.            &conn->s_state);
  2043.  
  2044.   radius_req(radius, &radius_pack, conn);
  2045.  
  2046.   return 0;
  2047. }
  2048.  
  2049. #ifdef ENABLE_UAMANYIP
  2050. /**
  2051.  * Assigns an ip from the dynamic pool, for SNAT'ing anyip connections.
  2052.  * If anyip is on and the clients address is outside of our network,
  2053.  * we need to SNAT to an ip of our network.
  2054.  */
  2055. int chilli_assign_snat(struct app_conn_t *appconn, int force) {
  2056.   struct ippoolm_t *newipm;
  2057.  
  2058.   if (!_options.uamanyip) return 0;
  2059.   if (!_options.uamnatanyip) return 0;
  2060.   if (appconn->natip.s_addr && !force) return 0;
  2061.  
  2062.   /* check if excluded from anyip */
  2063.   if (_options.uamnatanyipex_addr.s_addr &&
  2064.       (appconn->hisip.s_addr & _options.uamnatanyipex_mask.s_addr) ==
  2065.       _options.uamnatanyipex_addr.s_addr) {
  2066.     if (_options.debug)
  2067.       syslog(LOG_DEBUG, "%s(%d): Excluding ip %s from SNAT becuase it is in uamnatanyipex", __FUNCTION__, __LINE__,
  2068.              inet_ntoa(appconn->hisip));
  2069.     return 0;
  2070.   }
  2071.  
  2072.   if ((appconn->hisip.s_addr & _options.mask.s_addr) == _options.net.s_addr)
  2073.     return 0;
  2074.  
  2075.   if (_options.debug) {
  2076.     syslog(LOG_DEBUG, "%s(%d): Request SNAT ip for client ip: %s", __FUNCTION__, __LINE__,
  2077.            inet_ntoa(appconn->hisip));
  2078.     syslog(LOG_DEBUG, "%s(%d): SNAT mask: %s", __FUNCTION__, __LINE__, inet_ntoa(appconn->mask));
  2079.     syslog(LOG_DEBUG, "%s(%d): SNAT ourip: %s", __FUNCTION__, __LINE__, inet_ntoa(appconn->ourip));
  2080.   }
  2081.  
  2082.   if (ippool_newip(ippool, &newipm, &appconn->natip, 0)) {
  2083.     syslog(LOG_ERR, "Failed to allocate SNAT IP address");
  2084.     /*
  2085.      *  Clean up the static pool listing too, it's misconfigured now.
  2086.      */
  2087.     if (appconn->dnlink) {
  2088.       dhcp_freeconn((struct dhcp_conn_t *)appconn->dnlink, 0);
  2089.     }
  2090.     return -1;
  2091.   }
  2092.  
  2093.   appconn->natip.s_addr = newipm->addr.s_addr;
  2094.   newipm->peer = appconn;
  2095.  
  2096.   if (_options.debug)
  2097.     syslog(LOG_DEBUG, "%s(%d): SNAT IP %s assigned", __FUNCTION__, __LINE__, inet_ntoa(appconn->natip));
  2098.  
  2099.   return 0;
  2100. }
  2101. #endif
  2102.  
  2103.  
  2104. /***********************************************************
  2105.  *
  2106.  * Functions handling downlink protocol authentication.
  2107.  * Called in response to radius access request response.
  2108.  *
  2109.  ***********************************************************/
  2110.  
  2111. int dnprot_reject(struct app_conn_t *appconn) {
  2112.   struct dhcp_conn_t* dhcpconn = NULL;
  2113.   /*struct ippoolm_t *ipm;*/
  2114.  
  2115.   if (appconn->is_adminsession) return 0;
  2116.  
  2117.   switch (appconn->dnprot) {
  2118.  
  2119. #ifdef ENABLE_EAPOL
  2120.     case DNPROT_EAPOL:
  2121.       if (!(dhcpconn = (struct dhcp_conn_t*) appconn->dnlink)) {
  2122.         syslog(LOG_ERR, "No downlink protocol");
  2123.         return 0;
  2124.       }
  2125.  
  2126.       dhcp_sendEAPreject(dhcpconn, NULL, 0);
  2127.       return 0;
  2128. #endif
  2129.  
  2130.     case DNPROT_UAM:
  2131.       if (_options.debug)
  2132.         syslog(LOG_DEBUG, "%s(%d): Rejecting UAM", __FUNCTION__, __LINE__);
  2133.       return 0;
  2134.  
  2135. #ifdef ENABLE_RADPROXY
  2136.     case DNPROT_WPA:
  2137.       return radius_access_reject(appconn);
  2138. #endif
  2139.  
  2140.     case DNPROT_MAC:
  2141.       /* remove the username since we're not logged in */
  2142.       if (!appconn->s_state.authenticated)
  2143.         strlcpy(appconn->s_state.redir.username, "-", USERNAMESIZE);
  2144.  
  2145.       if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
  2146.         syslog(LOG_ERR, "No downlink protocol");
  2147.         return 0;
  2148.       }
  2149.  
  2150.       if (_options.macauthdeny) {
  2151.         dhcpconn->authstate = DHCP_AUTH_DROP;
  2152.         appconn->dnprot = DNPROT_NULL;
  2153.       }
  2154.       else {
  2155.         dhcpconn->authstate = DHCP_AUTH_DNAT;
  2156.         appconn->dnprot = DNPROT_UAM;
  2157.       }
  2158.  
  2159.       return 0;
  2160.  
  2161.     case DNPROT_NULL:
  2162. #ifdef ENABLE_LAYER3
  2163.     case DNPROT_LAYER3:
  2164. #endif
  2165.       return 0;
  2166.  
  2167.     default:
  2168.       syslog(LOG_ERR, "Unknown downlink protocol");
  2169.       return 0;
  2170.   }
  2171. }
  2172.  
  2173. #if defined(ENABLE_RADPROXY) || defined(ENABLE_EAPOL)
  2174. int static dnprot_challenge(struct app_conn_t *appconn) {
  2175.  
  2176.   switch (appconn->dnprot) {
  2177.  
  2178. #ifdef ENABLE_EAPOL
  2179.     case DNPROT_EAPOL:
  2180.       {
  2181.         struct dhcp_conn_t* dhcpconn = NULL;
  2182.         if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
  2183.           syslog(LOG_ERR, "No downlink protocol");
  2184.           return 0;
  2185.         }
  2186.  
  2187.         dhcp_sendEAP(dhcpconn, appconn->chal, appconn->challen);
  2188.       }
  2189.       break;
  2190. #endif
  2191.  
  2192.     case DNPROT_NULL:
  2193.     case DNPROT_UAM:
  2194.     case DNPROT_MAC:
  2195. #ifdef ENABLE_LAYER3
  2196.     case DNPROT_LAYER3:
  2197. #endif
  2198.       break;
  2199.  
  2200. #ifdef ENABLE_RADPROXY
  2201.     case DNPROT_WPA:
  2202.       radius_access_challenge(appconn);
  2203.       break;
  2204. #endif
  2205.  
  2206.     default:
  2207.       syslog(LOG_ERR, "Unknown downlink protocol");
  2208.   }
  2209.  
  2210.   return 0;
  2211. }
  2212. #endif
  2213.  
  2214. int dnprot_accept(struct app_conn_t *appconn) {
  2215.   struct dhcp_conn_t* dhcpconn = NULL;
  2216.  
  2217.   if (appconn->is_adminsession) return 0;
  2218.  
  2219.   if (!appconn->hisip.s_addr) {
  2220.     syslog(LOG_ERR, "IP address not allocated");
  2221.     return 0;
  2222.   }
  2223.  
  2224.   switch (appconn->dnprot) {
  2225.  
  2226. #ifdef ENABLE_EAPOL
  2227.     case DNPROT_EAPOL:
  2228.       if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
  2229.         syslog(LOG_ERR, "No downlink protocol");
  2230.         return 0;
  2231.       }
  2232.  
  2233.       dhcp_set_addrs(dhcpconn,
  2234.                      &appconn->hisip, &appconn->hismask,
  2235.                      &appconn->ourip, &appconn->mask,
  2236.                      &appconn->dns1, &appconn->dns2);
  2237.  
  2238.       /* This is the one and only place eapol authentication is accepted */
  2239.  
  2240.       dhcpconn->authstate = DHCP_AUTH_PASS;
  2241.  
  2242.       /* Tell client it was successful */
  2243.       dhcp_sendEAP(dhcpconn, appconn->chal, appconn->challen);
  2244.  
  2245.       syslog(LOG_WARNING, "Do not know how to set encryption keys on this platform!");
  2246.       break;
  2247. #endif
  2248.  
  2249.     case DNPROT_UAM:
  2250.       if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
  2251.         syslog(LOG_ERR, "No downlink protocol");
  2252.         return 0;
  2253.       }
  2254.  
  2255.       dhcp_set_addrs(dhcpconn,
  2256.                      &appconn->hisip, &appconn->hismask,
  2257.                      &appconn->ourip, &appconn->mask,
  2258.                      &appconn->dns1, &appconn->dns2);
  2259.  
  2260.       /* This is the one and only place UAM authentication is accepted */
  2261.       dhcpconn->authstate = DHCP_AUTH_PASS;
  2262.       appconn->s_params.flags &= ~REQUIRE_UAM_AUTH;
  2263.       break;
  2264.  
  2265. #ifdef ENABLE_RADPROXY
  2266.     case DNPROT_WPA:
  2267.       if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
  2268.         syslog(LOG_ERR, "No downlink protocol");
  2269.         return 0;
  2270.       }
  2271.  
  2272.       dhcp_set_addrs(dhcpconn,
  2273.                      &appconn->hisip, &appconn->hismask,
  2274.                      &appconn->ourip, &appconn->mask,
  2275.                      &appconn->dns1, &appconn->dns2);
  2276.  
  2277.       /* This is the one and only place WPA authentication is accepted */
  2278.       if (appconn->s_params.flags & REQUIRE_UAM_AUTH) {
  2279.         appconn->dnprot = DNPROT_DHCP_NONE;
  2280.         dhcpconn->authstate = DHCP_AUTH_NONE;
  2281.       }
  2282.       else {
  2283.         dhcpconn->authstate = DHCP_AUTH_PASS;
  2284.       }
  2285.  
  2286.       /* Tell access point it was successful */
  2287.       radius_access_accept(appconn);
  2288.  
  2289.       break;
  2290. #endif
  2291.  
  2292.     case DNPROT_MAC:
  2293.       if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
  2294.         syslog(LOG_ERR, "No downlink protocol");
  2295.         return 0;
  2296.       }
  2297.  
  2298.       dhcp_set_addrs(dhcpconn,
  2299.                      &appconn->hisip, &appconn->hismask,
  2300.                      &appconn->ourip, &appconn->mask,
  2301.                      &appconn->dns1, &appconn->dns2);
  2302.  
  2303.       dhcpconn->authstate = DHCP_AUTH_PASS;
  2304.       break;
  2305.  
  2306.     case DNPROT_NULL:
  2307.     case DNPROT_DHCP_NONE:
  2308.       return 0;
  2309.  
  2310. #ifdef ENABLE_LAYER3
  2311.     case DNPROT_LAYER3:
  2312.       break;
  2313. #endif
  2314.  
  2315.     default:
  2316.       syslog(LOG_ERR, "Unknown downlink protocol");
  2317.       return 0;
  2318.   }
  2319.  
  2320.   if ((dhcpconn && appconn->s_params.flags & REQUIRE_UAM_SPLASH) ||
  2321.       (dhcpconn && appconn->s_params.flags & REQUIRE_UAM_AUTH))
  2322.     dhcpconn->authstate = DHCP_AUTH_SPLASH;
  2323.  
  2324.   if (!(appconn->s_params.flags & REQUIRE_UAM_AUTH)) {
  2325.     /* This is the one and only place state is switched to authenticated */
  2326.     appconn->s_state.authenticated = 1;
  2327.  
  2328. #ifdef ENABLE_SESSIONSTATE
  2329.     appconn->s_state.session_state =
  2330.         RADIUS_VALUE_COOVACHILLI_SESSION_AUTH;
  2331. #endif
  2332.  
  2333. #ifdef HAVE_NETFILTER_COOVA
  2334.     if (_options.kname) {
  2335.       kmod_coova_update(appconn);
  2336.     }
  2337. #endif
  2338.  
  2339. #ifdef ENABLE_MODULES
  2340.     { int i;
  2341.       for (i=0; i < MAX_MODULES; i++) {
  2342.     if (!_options.modules[i].name[0]) break;
  2343.     if (_options.modules[i].ctx) {
  2344.       struct chilli_module *m =
  2345.               (struct chilli_module *)_options.modules[i].ctx;
  2346.       if (m->session_start)
  2347.         m->session_start(appconn);
  2348.     }
  2349.       }
  2350.     }
  2351. #endif
  2352.  
  2353.     /* if (!(appconn->s_params.flags & IS_UAM_REAUTH))*/
  2354.     acct_req(ACCT_USER, appconn, RADIUS_STATUS_TYPE_START);
  2355.  
  2356.     /* Run connection up script */
  2357.     if (_options.conup && !(appconn->s_params.flags & NO_SCRIPT)) {
  2358.  if (_options.debug)
  2359.      syslog(LOG_DEBUG, "%s(%d): Calling connection up script: %s\n", __FUNCTION__, __LINE__, _options.conup);
  2360.       runscript(appconn, _options.conup, 0, 0);
  2361.     }
  2362.   }
  2363.  
  2364.   appconn->s_params.flags &= ~IS_UAM_REAUTH;
  2365.  
  2366. #ifdef ENABLE_STATFILE
  2367.   if (_options.statusfilesave)
  2368.     printstatus();
  2369. #endif
  2370.  
  2371.   return 0;
  2372. }
  2373.  
  2374. #ifdef ENABLE_SSDP
  2375. static int fwd_ssdp(struct in_addr *dst,
  2376.             struct pkt_ipphdr_t *iph,
  2377.             struct pkt_udphdr_t *udph,
  2378.             struct pkt_buffer *pb,
  2379.             int ethhdr) {
  2380.   struct pkt_ethhdr_t *ethh = pkt_ethhdr(pkt_buffer_head(pb));
  2381.  
  2382.   if (udph && dst->s_addr == ssdp.s_addr) {
  2383.  
  2384.     if (_options.debug)
  2385.       syslog(LOG_DEBUG, "%s(%d): src="MAC_FMT" "
  2386.              "dst="MAC_FMT" prot=%.4x", __FUNCTION__, __LINE__,
  2387.              MAC_ARG(ethh->src),
  2388.              MAC_ARG(ethh->dst),
  2389.              ntohs(ethh->prot));
  2390.  
  2391.     /* TODO: also check that the source is from this machine in case we
  2392.      * are forwarding packets that we dont want to. */
  2393.  
  2394.     if (_options.debug) {
  2395.       char *bufr = (char *)(((void *)udph) + sizeof(struct pkt_udphdr_t));
  2396.       struct in_addr src;
  2397.  
  2398.       src.s_addr = iph->saddr;
  2399.  
  2400.       syslog(LOG_DEBUG, "%s(%d): ssdp multicast from %s\n%.*s", __FUNCTION__, __LINE__, inet_ntoa(src),
  2401.              ntohs(udph->len), bufr);
  2402.     }
  2403.  
  2404.     /* This sends to a unicast MAC address but a multicast IP address.
  2405.      */
  2406.     struct dhcp_conn_t *conn = dhcp->firstusedconn;
  2407.     while (conn) {
  2408.       if (conn->inuse && conn->authstate == DHCP_AUTH_PASS) {
  2409.     /*
  2410.     if (_options.debug)
  2411.   syslog(LOG_DEBUG, "sending to %s.", inet_ntoa(conn->hisip ));
  2412.     */
  2413.     dhcp_data_req(conn, pb, ethhdr);
  2414.       }
  2415.       conn = conn->next;
  2416.     }
  2417.  
  2418.     return 1; /* match */
  2419.   }
  2420.  
  2421.   return 0; /* no match */
  2422. }
  2423. #endif
  2424.  
  2425. #ifdef ENABLE_LAYER3
  2426. static int fwd_layer3(struct app_conn_t *appconn,
  2427.               struct in_addr *dst,
  2428.               struct pkt_udphdr_t *udph,
  2429.               struct pkt_buffer *pb,
  2430.               int ethhdr) {
  2431.   if (udph && udph->src == htons(DHCP_BOOTPS)) {
  2432.     struct dhcp_packet_t *pdhcp =
  2433.         (struct dhcp_packet_t *)(((void *)udph) + PKT_UDP_HLEN);
  2434.  
  2435.     if (pdhcp && pdhcp->op == DHCP_BOOTREPLY &&
  2436.     pdhcp->options[0] == 0x63 &&
  2437.     pdhcp->options[1] == 0x82 &&
  2438.     pdhcp->options[2] == 0x53 &&
  2439.     pdhcp->options[3] == 0x63) {
  2440.  
  2441.       if (!appconn) {
  2442.     struct in_addr src;
  2443.         if (_options.debug)
  2444.           syslog(LOG_DEBUG, "%s(%d): Detecting layer3 IP assignment", __FUNCTION__, __LINE__);
  2445.  
  2446.     src.s_addr = pdhcp->yiaddr;
  2447.     appconn = chilli_connect_layer3(&src, 0);
  2448.     if (!appconn) {
  2449.       syslog(LOG_ERR, "could not allocate for %s", inet_ntoa(src));
  2450.       return 1;
  2451.     }
  2452.       }
  2453.  
  2454. #ifdef ENABLE_TAP
  2455.       if (_options.usetap) {
  2456.     struct pkt_ethhdr_t *ethh = pkt_ethhdr(pkt_buffer_head(pb));
  2457.  
  2458.         if (_options.debug)
  2459.           syslog(LOG_DEBUG, "%s(%d): forwarding layer3 dhcp-broadcast: %s",__FUNCTION__, __LINE__, inet_ntoa(*dst));
  2460.  
  2461.     dhcp_send(dhcp, -1, ethh->dst,
  2462.           pkt_buffer_head(pb),
  2463.           pkt_buffer_length(pb));
  2464.       } else
  2465. #endif
  2466.       {
  2467.     struct pkt_ethhdr_t *ethh;
  2468.     uint8_t packet[PKT_MAX_LEN];
  2469.     size_t length = pkt_buffer_length(pb);
  2470.     size_t hdrlen = PKT_ETH_HLEN;
  2471.  
  2472.     memset(packet, 0, hdrlen);
  2473.  
  2474.     ethh = pkt_ethhdr(packet);
  2475.  
  2476.     uint8_t *dstmac = pdhcp->chaddr;
  2477.  
  2478.     memcpy(packet + hdrlen,
  2479.            pkt_buffer_head(pb),
  2480.            pkt_buffer_length(pb));
  2481.     length += hdrlen;
  2482.  
  2483.     copy_mac6(ethh->dst, dstmac);
  2484.     copy_mac6(ethh->src, dhcp_nexthop(dhcp));
  2485.     ethh->prot = htons(PKT_ETH_PROTO_IP);
  2486.  
  2487.     dhcp_send(dhcp, -1, dstmac, packet, length);
  2488.       }
  2489.       return 1;
  2490.     }
  2491.   }
  2492.   return 0;
  2493. }
  2494. #endif
  2495.  
  2496.  
  2497. /*
  2498.  * Tun callbacks
  2499.  *
  2500.  * Called from the tun_decaps function. This method is passed either
  2501.  * a Ethernet frame or an IP packet.
  2502.  */
  2503.  
  2504. int cb_tun_ind(struct tun_t *tun, struct pkt_buffer *pb, int idx) {
  2505.   struct in_addr dst;
  2506.   struct ippoolm_t *ipm;
  2507.   struct app_conn_t *appconn = 0;
  2508.   struct pkt_udphdr_t *udph = 0;
  2509.   struct pkt_ipphdr_t *ipph;
  2510.  
  2511.   uint8_t *pack = pkt_buffer_head(pb);
  2512.   size_t len = pkt_buffer_length(pb);
  2513.  
  2514.   int ethhdr = (tun(tun, idx).flags & NET_ETHHDR) != 0;
  2515.   size_t ip_len = len;
  2516.  
  2517. #ifdef ENABLE_TAP
  2518.   if (idx) ethhdr = 0;
  2519.  
  2520.   if (ethhdr) {
  2521.     struct pkt_ethhdr_t *ethh = 0;
  2522.     /*
  2523.      *   Will never be 802.1Q
  2524.      */
  2525.     uint16_t prot;
  2526.  
  2527.     ethh = pkt_ethhdr(pack);
  2528.     prot = ntohs(ethh->prot);
  2529.  
  2530.     ipph = (struct pkt_ipphdr_t *)((char *)pack + PKT_ETH_HLEN);
  2531.     ip_len -= PKT_ETH_HLEN;
  2532.  
  2533.     switch (prot) {
  2534.       case PKT_ETH_PROTO_IPv6:
  2535.         return 0;
  2536.  
  2537.       case PKT_ETH_PROTO_IP:
  2538.         break;
  2539.  
  2540.       case PKT_ETH_PROTO_ARP:
  2541.         {
  2542.           /*
  2543.            *  Send arp reply
  2544.            */
  2545.           uint8_t packet[PKT_BUFFER];
  2546.  
  2547.           struct pkt_ethhdr_t *p_ethh = pkt_ethhdr(pack);
  2548.           struct arp_packet_t *p_arp = pkt_arppkt(pack);
  2549.           struct pkt_ethhdr_t *packet_ethh = pkt_ethhdr(packet);
  2550.           struct arp_packet_t *packet_arp =
  2551.               ((struct arp_packet_t *)(((uint8_t*)(packet)) + PKT_ETH_HLEN));
  2552.  
  2553.           size_t length = PKT_ETH_HLEN + sizeof(struct arp_packet_t);
  2554.  
  2555.           struct in_addr reqaddr;
  2556.  
  2557.           /*
  2558.            *   Get local copy of the target address to resolve
  2559.            */
  2560.           memcpy(&reqaddr.s_addr, p_arp->tpa, PKT_IP_ALEN);
  2561.  
  2562.           if (_options.debug)
  2563.             syslog(LOG_DEBUG, "%s(%d): arp: ifidx=%d src="MAC_FMT" "
  2564.                    "dst="MAC_FMT" "
  2565.                    "prot=%.4x (asking for %s)", __FUNCTION__, __LINE__,
  2566.                    tun(tun,idx).ifindex,
  2567.                    MAC_ARG(ethh->src),
  2568.                    MAC_ARG(ethh->dst),
  2569.                    ntohs(ethh->prot),
  2570.                    inet_ntoa(reqaddr));
  2571.  
  2572.           /*
  2573.            *  Lookup request address, see if we control it.
  2574.            */
  2575.           if (ippool_getip(ippool, &ipm, &reqaddr)) {
  2576.             if (_options.debug)
  2577.               syslog(LOG_DEBUG, "%s(%d): ARP for unknown IP %s", __FUNCTION__, __LINE__, inet_ntoa(reqaddr));
  2578.             return 0;
  2579.           }
  2580.  
  2581.           if ((appconn  = (struct app_conn_t *)ipm->peer) == NULL ||
  2582.               (appconn->dnlink) == NULL) {
  2583.             syslog(LOG_ERR, "No peer protocol defined for ARP request");
  2584.             return 0;
  2585.           }
  2586.  
  2587.           /* Get packet default values */
  2588.           memset(&packet, 0, sizeof(packet));
  2589.  
  2590.           /* ARP Payload */
  2591.           packet_arp->hrd = htons(DHCP_HTYPE_ETH);
  2592.           packet_arp->pro = htons(PKT_ETH_PROTO_IP);
  2593.           packet_arp->hln = PKT_ETH_ALEN;
  2594.           packet_arp->pln = PKT_IP_ALEN;
  2595.           packet_arp->op  = htons(DHCP_ARP_REPLY);
  2596.  
  2597.           /* Source address */
  2598.           /*memcpy(packet_arp->sha, appconn->hismac, PKT_ETH_ALEN);*/
  2599.           memcpy(packet_arp->sha, dhcp->rawif[0].hwaddr, PKT_ETH_ALEN);
  2600.  
  2601. #ifdef ENABLE_UAMANYIP
  2602.           /*
  2603.            * ARP replies need to tell the NATed ip address,
  2604.            * when client is an anyip client.
  2605.            */
  2606.           if (_options.uamanyip && appconn->natip.s_addr) {
  2607.             memcpy(packet_arp->spa, &appconn->natip.s_addr, PKT_IP_ALEN);
  2608.             if (_options.debug) {
  2609.               char ip[56];
  2610.               char snatip[56];
  2611.               strlcpy(ip, inet_ntoa(appconn->hisip), sizeof(ip));
  2612.               strlcpy(snatip, inet_ntoa(appconn->natip), sizeof(snatip));
  2613.               syslog(LOG_DEBUG, "%s(%d): SNAT anyip in ARP response from %s to %s", __FUNCTION__, __LINE__,
  2614.                      ip, snatip);
  2615.             }
  2616.           } else
  2617. #endif
  2618.             memcpy(packet_arp->spa, &appconn->hisip.s_addr, PKT_IP_ALEN);
  2619.  
  2620.           /* Target address */
  2621.           memcpy(packet_arp->tha, p_arp->sha, PKT_ETH_ALEN);
  2622.           memcpy(packet_arp->tpa, p_arp->spa, PKT_IP_ALEN);
  2623.  
  2624.           /* Ethernet header */
  2625.           memcpy(packet_ethh->dst, p_ethh->src, PKT_ETH_ALEN);
  2626.           /*memcpy(packet_ethh->src, appconn->hismac, PKT_ETH_ALEN);*/
  2627.           memcpy(packet_ethh->src, dhcp->rawif[0].hwaddr, PKT_ETH_ALEN);
  2628.  
  2629.           packet_ethh->prot = htons(PKT_ETH_PROTO_ARP);
  2630.  
  2631.           if (_options.debug) {
  2632.             syslog(LOG_DEBUG, "%s(%d): arp-reply: src="MAC_FMT" "
  2633.                    "dst="MAC_FMT, __FUNCTION__, __LINE__,
  2634.                    MAC_ARG(packet_ethh->src),
  2635.                    MAC_ARG(packet_ethh->dst));
  2636.  
  2637.             memcpy(&reqaddr.s_addr, packet_arp->spa, PKT_IP_ALEN);
  2638.             syslog(LOG_DEBUG, "%s(%d): arp-reply: source sha="MAC_FMT" spa=%s", __FUNCTION__, __LINE__,
  2639.                    MAC_ARG(packet_arp->sha),
  2640.                    inet_ntoa(reqaddr));
  2641.  
  2642.             memcpy(&reqaddr.s_addr, packet_arp->tpa, PKT_IP_ALEN);
  2643.             syslog(LOG_DEBUG, "%s(%d): arp-reply: target tha="MAC_FMT" tpa=%s", __FUNCTION__, __LINE__,
  2644.                    MAC_ARG(packet_arp->tha),
  2645.                    inet_ntoa(reqaddr));
  2646.           }
  2647.  
  2648.           return tun_write(tun, (uint8_t *)&packet, length, idx);
  2649.         }
  2650.       default:
  2651.         if (_options.debug)
  2652.           syslog(LOG_DEBUG, "%s(%d): unhandled protocol %x", __FUNCTION__, __LINE__, prot);
  2653.         return 0;
  2654.     }
  2655.  
  2656.   } else
  2657. #endif
  2658.   {
  2659.     ipph = (struct pkt_ipphdr_t *)pack;
  2660.   }
  2661.  
  2662.   size_t hlen = (ipph->version_ihl & 0x0f) << 2;
  2663.   if (ntohs(ipph->tot_len) > ip_len || hlen > ip_len) {
  2664.     if (_options.debug)
  2665.       syslog(LOG_DEBUG, "%s(%d): invalid IP packet %d / %zu", __FUNCTION__, __LINE__,
  2666.              ntohs(ipph->tot_len),
  2667.              len);
  2668.     return 0;
  2669.   }
  2670.  
  2671.   /*
  2672.    *  Filter out unsupported / unhandled protocols,
  2673.    *  and check some basic length sanity.
  2674.    */
  2675.   switch(ipph->protocol) {
  2676.     case PKT_IP_PROTO_GRE:
  2677.     case PKT_IP_PROTO_TCP:
  2678.     case PKT_IP_PROTO_ICMP:
  2679.     case PKT_IP_PROTO_ESP:
  2680.     case PKT_IP_PROTO_AH:
  2681.       break;
  2682.     case PKT_IP_PROTO_UDP:
  2683.       {
  2684.         /*
  2685.          * Only the first IP fragment has the UDP header.
  2686.          */
  2687.         if (iphdr_offset((struct pkt_iphdr_t*)ipph) == 0) {
  2688.           udph = (struct pkt_udphdr_t *)(((void *)ipph) + hlen);
  2689.         }
  2690.         if (udph && !iphdr_more_frag((struct pkt_iphdr_t*)ipph) && (ntohs(udph->len) > ip_len)) {
  2691.           if (_options.debug)
  2692.             syslog(LOG_DEBUG, "%s(%d): invalid UDP packet %d / %d / %zu", __FUNCTION__, __LINE__,
  2693.                    ntohs(ipph->tot_len),
  2694.                    udph ? ntohs(udph->len) : -1, ip_len);
  2695.           return 0;
  2696.         }
  2697.       }
  2698.       break;
  2699.     default:
  2700.       if (_options.debug)
  2701.         syslog(LOG_DEBUG, "%s(%d): dropping unhandled packet: %x", __FUNCTION__, __LINE__, ipph->protocol);
  2702.       return 0;
  2703.   }
  2704.  
  2705.   dst.s_addr = ipph->daddr;
  2706.  
  2707. #if(_debug_ > 1)
  2708.   if (_options.debug)
  2709.     syslog(LOG_DEBUG, "%s(%d): sending to : %s", __FUNCTION__, __LINE__, inet_ntoa(dst));
  2710. #endif
  2711.  
  2712.   if (ippool_getip(ippool, &ipm, &dst)) {
  2713.  
  2714.     /*
  2715.      *  TODO: If within statip range, allow the packet through (?)
  2716.      */
  2717.  
  2718. #ifdef ENABLE_SSDP
  2719.     if (fwd_ssdp(&dst, ipph, udph, pb, ethhdr)) return 0;
  2720. #endif
  2721.  
  2722. #ifdef ENABLE_LAYER3
  2723.     if (_options.layer3)
  2724.       if (fwd_layer3(0, &dst, udph, pb, ethhdr))
  2725.     return 0;
  2726. #endif
  2727.  
  2728.     if (_options.debug)
  2729.       syslog(LOG_DEBUG, "%s(%d): dropping packet with unknown destination: %s", __FUNCTION__, __LINE__, inet_ntoa(dst));
  2730.  
  2731.     return 0;
  2732.   }
  2733.  
  2734.   appconn = (struct app_conn_t *)ipm->peer;
  2735.  
  2736. #ifdef ENABLE_LEAKYBUCKET
  2737.   if (_options.scalewin && appconn && appconn->s_state.bucketdownsize) {
  2738.     uint16_t win = appconn->s_state.bucketdownsize -
  2739.         appconn->s_state.bucketdown;
  2740.     //log_dbg("window scaling to %d", win);
  2741.     pkt_shape_tcpwin((struct pkt_iphdr_t *)ipph, win);
  2742.   }
  2743. #endif
  2744.  
  2745. #ifdef ENABLE_LAYER3
  2746.   if (_options.layer3 && appconn && !appconn->dnlink)
  2747.     if (fwd_layer3(appconn, &dst, udph, pb, ethhdr))
  2748.       return 0;
  2749. #endif
  2750.  
  2751.   if (appconn == NULL || appconn->dnlink == NULL) {
  2752.     syslog(LOG_ERR, "No %s protocol defined for %s",
  2753.            appconn ? "dnlink" : "peer", inet_ntoa(dst));
  2754.     return 0;
  2755.   }
  2756.  
  2757. #ifdef ENABLE_UAMANYIP
  2758.   /**
  2759.    * connection needs to be NAT'ed, since client is an anyip client
  2760.    * outside of our network.
  2761.    * So, let's NAT the SNAT ip back to it's client ip.
  2762.    */
  2763.   if (_options.uamanyip && appconn->natip.s_addr) {
  2764. #if(_debug_ > 1)
  2765.     if (_options.debug) {
  2766.       char ip[56];
  2767.       char snatip[56];
  2768.       strlcpy(ip, inet_ntoa(appconn->hisip), sizeof(ip));
  2769.       strlcpy(snatip, inet_ntoa(appconn->natip), sizeof(snatip));
  2770.       syslog(LOG_DEBUG, "%s(%d): SNAT anyip replace %s back to %s; snat was: %s", __FUNCTION__, __LINE__,
  2771.              inet_ntoa(dst), ip, snatip);
  2772.     }
  2773. #endif
  2774.     ipph->daddr = appconn->hisip.s_addr;
  2775.     if (chksum((struct pkt_iphdr_t *) ipph) < 0)
  2776.       return 0;
  2777.   }
  2778. #endif
  2779.  
  2780.   /* If the ip src is uamlisten and psrc is uamport
  2781.      we won't call leaky_bucket */
  2782.   if ( ! (ipph->saddr  == _options.uamlisten.s_addr &&
  2783.       (ipph->sport == htons(_options.uamport)
  2784. #ifdef ENABLE_UAMUIPORT
  2785.        || ipph->sport == htons(_options.uamuiport)
  2786. #endif
  2787.        ))) {
  2788.     if (chilli_acct_tosub(appconn, ipph))
  2789.       return 0;
  2790.   }
  2791.  
  2792.   switch (appconn->dnprot) {
  2793.     case DNPROT_NULL:
  2794.     case DNPROT_DHCP_NONE:
  2795.       if (_options.debug)
  2796.         syslog(LOG_DEBUG, "%s(%d): Dropping...", __FUNCTION__, __LINE__);
  2797.       break;
  2798.  
  2799.     case DNPROT_UAM:
  2800.     case DNPROT_WPA:
  2801.     case DNPROT_MAC:
  2802. #ifdef ENABLE_EAPOL
  2803.     case DNPROT_EAPOL:
  2804. #endif
  2805. #ifdef ENABLE_LAYER3
  2806.     case DNPROT_LAYER3:
  2807. #endif
  2808.       dhcp_data_req((struct dhcp_conn_t *)appconn->dnlink, pb, ethhdr);
  2809.       break;
  2810.  
  2811.     default:
  2812.       syslog(LOG_ERR, "Unknown downlink protocol: %d", appconn->dnprot);
  2813.       break;
  2814.   }
  2815.  
  2816.   return 0;
  2817. }
  2818.  
  2819. /*********************************************************
  2820.  *
  2821.  * Redir callbacks
  2822.  *
  2823.  *********************************************************/
  2824.  
  2825. int cb_redir_getstate(struct redir_t *redir,
  2826.               struct sockaddr_in *address,
  2827.               struct sockaddr_in *baddress,
  2828.               struct redir_conn_t *conn) {
  2829.   struct in_addr *addr = &address->sin_addr;
  2830.   struct ippoolm_t *ipm;
  2831.   struct app_conn_t *appconn;
  2832.   struct dhcp_conn_t *dhcpconn;
  2833.   uint8_t flags = 0;
  2834.  
  2835. #if defined(HAVE_NETFILTER_QUEUE) || defined(HAVE_NETFILTER_COOVA)
  2836.   if (_options.uamlisten.s_addr != _options.dhcplisten.s_addr) {
  2837.     addr->s_addr  = addr->s_addr & ~(_options.mask.s_addr);
  2838.     addr->s_addr |= _options.dhcplisten.s_addr & _options.mask.s_addr;
  2839.   }
  2840. #endif
  2841.  
  2842.   if (ippool_getip(ippool, &ipm, addr)) {
  2843.     if (_options.debug)
  2844.       syslog(LOG_DEBUG, "%s(%d): did not find %s", __FUNCTION__, __LINE__, inet_ntoa(*addr));
  2845.     return -1;
  2846.   }
  2847.  
  2848.   if ( (appconn  = (struct app_conn_t *)ipm->peer)        == NULL ||
  2849.        (dhcpconn = (struct dhcp_conn_t *)appconn->dnlink) == NULL ) {
  2850.     syslog(LOG_WARNING, "No peer protocol defined app-null=%d", appconn == 0);
  2851.     return -1;
  2852.   }
  2853.  
  2854.   conn->nasip = _options.radiuslisten;
  2855.   conn->nasport = appconn->unit;
  2856.   memcpy(conn->hismac, dhcpconn->hismac, PKT_ETH_ALEN);
  2857.   conn->ourip = appconn->ourip;
  2858.   conn->hisip = appconn->hisip;
  2859.  
  2860. #ifdef HAVE_SSL
  2861.   /*
  2862.    *  Determine if the connection is SSL or not.
  2863.    */
  2864.   {
  2865.     int n;
  2866.     for (n=0; n < DHCP_DNAT_MAX; n++) {
  2867.       /*
  2868.        *  First, search the dnat list to see if we are tracking the port.
  2869.        */
  2870.       /*syslog("%d(%d) == %d",ntohs(dhcpconn->dnat[n].src_port),ntohs(dhcpconn->dnat[n].dst_port),ntohs(address->sin_port));*/
  2871.       if (dhcpconn->dnat[n].src_port == address->sin_port) {
  2872.     if (dhcpconn->dnat[n].dst_port == htons(DHCP_HTTPS)
  2873. #ifdef ENABLE_UAMUIPORT
  2874.         || (_options.uamuissl && dhcpconn->dnat[n].dst_port == htons(_options.uamuiport))
  2875. #endif
  2876.         ) {
  2877. #if(_debug_)
  2878.           if (_options.debug)
  2879.             syslog(LOG_DEBUG, "%s(%d): redir connection is SSL", __FUNCTION__, __LINE__);
  2880. #endif
  2881.       flags |= USING_SSL;
  2882.     }
  2883.     break;
  2884.       }
  2885.     }
  2886. #ifdef ENABLE_UAMUIPORT
  2887.     /*
  2888.      *  If not in dnat, if uamuissl is enabled, and this is indeed that
  2889.      *  port, then we also know it is SSL (directly to https://uamlisten:uamuiport).
  2890.      */
  2891.     if (n == DHCP_DNAT_MAX && _options.uamuissl &&
  2892.     ntohs(baddress->sin_port) == _options.uamuiport) {
  2893. #if(_debug_)
  2894.       if (_options.debug)
  2895.         syslog(LOG_DEBUG, "%s(%d): redir connection is SSL", __FUNCTION__, __LINE__);
  2896. #endif
  2897.       flags |= USING_SSL;
  2898.     }
  2899. #endif
  2900.   }
  2901. #endif
  2902.  
  2903.   conn->flags = flags;
  2904.  
  2905.   memcpy(&conn->s_params, &appconn->s_params, sizeof(appconn->s_params));
  2906.   memcpy(&conn->s_state,  &appconn->s_state,  sizeof(appconn->s_state));
  2907.  
  2908.   /* reset state */
  2909.   appconn->uamexit = 0;
  2910.  
  2911.   return conn->s_state.authenticated == 1;
  2912. }
  2913.  
  2914. #ifdef ENABLE_LOCATION
  2915. int
  2916. chilli_learn_location(uint8_t *loc, int loclen,
  2917.               struct app_conn_t *appconn, char force) {
  2918.   char loc_buff[MAX_LOCATION_LENGTH];
  2919.   char prev_loc_buff[MAX_LOCATION_LENGTH];
  2920.   int prev_loc_len=0;
  2921.  
  2922.   char has_new_location = 0;
  2923.   char restart_accounting = 0;
  2924.  
  2925.   if (loclen >= MAX_LOCATION_LENGTH) {
  2926.     syslog(LOG_ERR, "Location too long %d", loclen);
  2927.     return 0;
  2928.   }
  2929.  
  2930.   memcpy(loc_buff, (char *)loc, loclen);
  2931.   loc_buff[loclen]=0;
  2932.  
  2933.   strlcpy(prev_loc_buff, appconn->s_state.location, sizeof(prev_loc_buff));
  2934.   prev_loc_len = strlen(prev_loc_buff);
  2935.  
  2936.   if (_options.debug)
  2937.     syslog(LOG_DEBUG, "%s(%d): Learned location : [%.*s]", __FUNCTION__, __LINE__, loclen, loc);
  2938.  
  2939.   if (prev_loc_len == 0 ||
  2940.       prev_loc_len != loclen ||
  2941.       memcmp(prev_loc_buff, loc, prev_loc_len)) {
  2942.  
  2943.     if (force || !strcmp(appconn->s_state.pending_location,
  2944.              loc_buff)) {
  2945.  
  2946.       has_new_location = 1;
  2947.       appconn->s_state.location_changes++;
  2948.       appconn->s_state.pending_location[0]=0;
  2949.  
  2950.       if (_options.debug)
  2951.         syslog(LOG_DEBUG, "%s(%d): Learned new-location : %d [%.*s] old %d [%s]", __FUNCTION__, __LINE__,
  2952.                loclen, loclen, loc,
  2953.                prev_loc_len, prev_loc_buff);
  2954.  
  2955. #if defined(ENABLE_LOCATION) && defined(HAVE_AVL)
  2956.       location_add_conn(appconn, loc_buff);
  2957. #endif
  2958.  
  2959.       if (_options.locationupdate) {
  2960.     runscript(appconn, _options.locationupdate,
  2961.           loc_buff, prev_loc_buff);
  2962.       }
  2963.  
  2964.       if (_options.location_stop_start) {
  2965.     restart_accounting = 1;
  2966.       }
  2967.     } else {
  2968.       strlcpy(appconn->s_state.pending_location, loc_buff,
  2969.     sizeof(appconn->s_state.pending_location));
  2970.     }
  2971.   }
  2972.  
  2973.   if (appconn->s_state.authenticated == 1 &&
  2974.       has_new_location && restart_accounting) {
  2975.     /* make sure not already over a limit ... */
  2976.     session_interval(appconn);
  2977.  
  2978. #ifdef ENABLE_SESSIONSTATE
  2979.     appconn->s_state.session_state =
  2980.         RADIUS_VALUE_COOVACHILLI_SESSION_LOCATION_CHANGE;
  2981. #endif
  2982.  
  2983.     if (appconn->s_state.authenticated == 1)
  2984.       acct_req(ACCT_USER, appconn, RADIUS_STATUS_TYPE_STOP);
  2985.   }
  2986.  
  2987. #ifdef ENABLE_GARDENACCOUNTING
  2988.   if (_options.uamgardendata &&
  2989.       has_new_location && restart_accounting &&
  2990.       appconn->hisip.s_addr) {
  2991.  
  2992. #ifdef ENABLE_SESSIONSTATE
  2993.     appconn->s_state.session_state =
  2994.         RADIUS_VALUE_COOVACHILLI_SESSION_LOCATION_CHANGE;
  2995. #endif
  2996.  
  2997.     acct_req(ACCT_GARDEN, appconn, RADIUS_STATUS_TYPE_STOP);
  2998.   }
  2999. #endif
  3000.  
  3001.   if (has_new_location) {
  3002.     memcpy(appconn->s_state.location, (char *) loc, loclen);
  3003.     appconn->s_state.location[loclen] = 0;
  3004.   }
  3005.  
  3006. #ifdef ENABLE_GARDENACCOUNTING
  3007.   if (_options.uamgardendata &&
  3008.       has_new_location && restart_accounting &&
  3009.       appconn->hisip.s_addr) {
  3010.     acct_req(ACCT_GARDEN, appconn, RADIUS_STATUS_TYPE_START);
  3011.   }
  3012. #endif
  3013.  
  3014.   if (appconn->s_state.authenticated == 1 &&
  3015.       has_new_location && restart_accounting) {
  3016.  
  3017.     /* adjust session parameters to be zeroed out */
  3018.  
  3019.     set_sessionid(appconn, 0);
  3020.  
  3021.     if (appconn->s_params.sessiontimeout) {
  3022.       uint32_t sessiontime = mainclock_diffu(appconn->s_state.start_time);
  3023.       if (sessiontime > appconn->s_params.sessiontimeout)
  3024.     /* (should be the case, having done the session_interval() above) */
  3025.     appconn->s_params.sessiontimeout -= sessiontime;
  3026.     }
  3027.  
  3028.     if (appconn->s_params.maxinputoctets) {
  3029.       if (appconn->s_params.maxinputoctets > appconn->s_state.input_octets)
  3030.     appconn->s_params.maxinputoctets -= appconn->s_state.input_octets;
  3031.     }
  3032.  
  3033.     if (appconn->s_params.maxoutputoctets) {
  3034.       if (appconn->s_params.maxoutputoctets > appconn->s_state.output_octets)
  3035.     appconn->s_params.maxoutputoctets -= appconn->s_state.output_octets;
  3036.     }
  3037.  
  3038.     if (appconn->s_params.maxtotaloctets) {
  3039.       uint64_t total = appconn->s_state.input_octets +
  3040.           appconn->s_state.output_octets;
  3041.       if (appconn->s_params.maxtotaloctets > total)
  3042.     appconn->s_params.maxtotaloctets -= total;
  3043.     }
  3044.  
  3045.     appconn->s_state.start_time = mainclock.tv_sec;
  3046.     appconn->s_state.interim_time = mainclock.tv_sec;
  3047.     appconn->s_state.last_time = mainclock.tv_sec;
  3048.     appconn->s_state.last_up_time = mainclock.tv_sec;
  3049.     appconn->s_state.input_packets = 0;
  3050.     appconn->s_state.input_octets = 0;
  3051.     appconn->s_state.output_packets = 0;
  3052.     appconn->s_state.output_octets = 0;
  3053.  
  3054.     acct_req(ACCT_USER, appconn, RADIUS_STATUS_TYPE_START);
  3055.   }
  3056.   else if (_options.location_immediate_update && has_new_location) {
  3057.  
  3058. #ifdef ENABLE_SESSIONSTATE
  3059.     int old_state = appconn->s_state.session_state;
  3060.  
  3061.     appconn->s_state.session_state =
  3062.         RADIUS_VALUE_COOVACHILLI_SESSION_LOCATION_CHANGE;
  3063. #endif
  3064.  
  3065.     if (appconn->s_state.authenticated == 1)
  3066.       acct_req(ACCT_USER, appconn, RADIUS_STATUS_TYPE_INTERIM_UPDATE);
  3067.  
  3068. #ifdef ENABLE_GARDENACCOUNTING
  3069.     if (_options.uamgardendata)
  3070.       acct_req(ACCT_GARDEN, appconn, RADIUS_STATUS_TYPE_INTERIM_UPDATE);
  3071. #endif
  3072.  
  3073. #ifdef ENABLE_SESSIONSTATE
  3074.     appconn->s_state.session_state = old_state;
  3075. #endif
  3076.  
  3077.   }
  3078.  
  3079.   return 0;
  3080. }
  3081. #endif
  3082.  
  3083. #ifdef ENABLE_RADPROXY
  3084.  
  3085. #if defined(ENABLE_LOCATION) || defined(ENABLE_PROXYVSA)
  3086. static int
  3087. chilli_proxy_radlocation(struct radius_packet_t *pack,
  3088.              struct app_conn_t *appconn, char force) {
  3089.   struct radius_attr_t *attr = 0;
  3090. #ifdef ENABLE_PROXYVSA
  3091.   uint8_t * vsa = appconn->s_state.redir.vsa;
  3092.   int instance=0;
  3093. #endif
  3094.  
  3095.   if (_options.location_copy_called) {
  3096.     if (!radius_getattr(pack, &attr, RADIUS_ATTR_CALLED_STATION_ID, 0, 0, 0)) {
  3097.       if (attr->l - 2 < sizeof(appconn->s_state.redir.called) - 1) {
  3098.     appconn->s_state.redir.calledlen = attr->l - 2;
  3099.     memcpy(appconn->s_state.redir.called, attr->v.t,
  3100.            appconn->s_state.redir.calledlen);
  3101.     appconn->s_state.redir.called[appconn->s_state.redir.calledlen]=0;
  3102.       }
  3103.     }
  3104.   }
  3105.  
  3106. #ifdef ENABLE_PROXYVSA
  3107.   do {
  3108.     attr=NULL;
  3109.     if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC, 0, 0,
  3110.             instance++)) {
  3111.  
  3112.       if ((appconn->s_state.redir.vsalen + (size_t) attr->l) >
  3113.       RADIUS_PROXYVSA) {
  3114.     syslog(LOG_WARNING, "VSAs too long");
  3115.     return -1;
  3116.       }
  3117.  
  3118.       memcpy(vsa + appconn->s_state.redir.vsalen,
  3119.          (void *)attr, (size_t) attr->l);
  3120.       appconn->s_state.redir.vsalen += (size_t) attr->l;
  3121.  
  3122. #if(_debug_)
  3123.       if (_options.debug)
  3124.         syslog(LOG_DEBUG, "%s(%d): Remembering VSA", __FUNCTION__, __LINE__);
  3125. #endif
  3126.     }
  3127.   } while (attr);
  3128. #endif
  3129.  
  3130. #ifdef ENABLE_LOCATION
  3131.   if (_options.proxy_loc[0].attr) {
  3132.     int i;
  3133.  
  3134.     attr = 0;
  3135.  
  3136.     for (i=0; i < PROXYVSA_ATTR_CNT; i++) {
  3137.  
  3138.       if (!_options.proxy_loc[i].attr_vsa &&
  3139.       !_options.proxy_loc[i].attr)
  3140.     break;
  3141.  
  3142.       if (!_options.proxy_loc[i].attr_vsa) {
  3143.     /*
  3144.      *  We have a loc_attr, but it isn't a VSA (so not included above)
  3145.      */
  3146.  
  3147. #if(_debug_)
  3148.         if (_options.debug)
  3149.           syslog(LOG_DEBUG, "%s(%d): looking for attr %d", __FUNCTION__, __LINE__, _options.proxy_loc[i].attr);
  3150. #endif
  3151.  
  3152.     if (radius_getattr(pack, &attr, _options.proxy_loc[i].attr,
  3153.                0, 0, 0)) {
  3154.           if (_options.debug)
  3155.             syslog(LOG_DEBUG, "%s(%d): didn't find attr %d", __FUNCTION__, __LINE__, _options.proxy_loc[i].attr);
  3156.       attr = 0;
  3157.     }
  3158.       } else {
  3159.     /*
  3160.      *  We have a loc_attr and VSA number (so it is included above).
  3161.      */
  3162.  
  3163. #if(_debug_)
  3164.         if (_options.debug)
  3165.           syslog(LOG_DEBUG, "%s(%d): looking for attr %d/%d", __FUNCTION__, __LINE__, _options.proxy_loc[i].attr_vsa,
  3166.                  _options.proxy_loc[i].attr);
  3167. #endif
  3168.  
  3169.     if (radius_getattr(pack, &attr,
  3170.                RADIUS_ATTR_VENDOR_SPECIFIC,
  3171.                _options.proxy_loc[i].attr_vsa,
  3172.                _options.proxy_loc[i].attr, 0)) {
  3173. #if(_debug_)
  3174.           if (_options.debug)
  3175.             syslog(LOG_DEBUG, "%s(%d): didn't find attr %d/%d", __FUNCTION__, __LINE__, _options.proxy_loc[i].attr_vsa,
  3176.                    _options.proxy_loc[i].attr);
  3177. #endif
  3178.       attr = 0;
  3179.     }
  3180.       }
  3181.     }
  3182.  
  3183.     if (attr && attr->l > 2) {
  3184.       chilli_learn_location(attr->v.t, attr->l - 2, appconn, force);
  3185.     }
  3186.   }
  3187. #endif
  3188.  
  3189.   return 0;
  3190. }
  3191. #endif
  3192.  
  3193. /* Handle an accounting request */
  3194. int accounting_request(struct radius_packet_t *pack,
  3195.                struct sockaddr_in *peer) {
  3196.   struct radius_attr_t *attr = NULL;
  3197.   struct radius_attr_t *hismacattr = NULL;
  3198.   struct radius_attr_t *nasipattr = NULL;
  3199.   struct radius_attr_t *nasportattr = NULL;
  3200.   struct radius_packet_t radius_pack;
  3201.   struct app_conn_t *appconn = NULL;
  3202.   struct dhcp_conn_t *dhcpconn = NULL;
  3203.   uint8_t hismac[PKT_ETH_ALEN];
  3204.   char macstr[RADIUS_ATTR_VLEN];
  3205.   size_t macstrlen;
  3206.   unsigned int temp[PKT_ETH_ALEN];
  3207.   uint32_t nasip = 0;
  3208.   uint32_t nasport = 0;
  3209.   int status_type;
  3210.   int i;
  3211.  
  3212.   if (radius_default_pack(radius, &radius_pack,
  3213.               RADIUS_CODE_ACCOUNTING_RESPONSE)) {
  3214.     syslog(LOG_ERR, "radius_default_pack() failed");
  3215.     return -1;
  3216.   }
  3217.  
  3218.   /* We will only respond, not proxy */
  3219.   radius_pack.id = pack->id;
  3220.  
  3221.   /* Status type */
  3222.   if (radius_getattr(pack, &attr, RADIUS_ATTR_ACCT_STATUS_TYPE, 0, 0, 0)) {
  3223.     syslog(LOG_ERR, "Status type is missing from radius request");
  3224.     radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3225.     return 0;
  3226.   }
  3227.  
  3228.   status_type = ntohl(attr->v.i);
  3229.  
  3230.   if (RADIUS_STATUS_TYPE_ACCOUNTING_ON  != status_type &&
  3231.       RADIUS_STATUS_TYPE_ACCOUNTING_OFF != status_type) {
  3232.  
  3233.     /* NAS IP */
  3234.     if (!radius_getattr(pack, &nasipattr,
  3235.             RADIUS_ATTR_NAS_IP_ADDRESS, 0, 0, 0)) {
  3236.       if ((nasipattr->l-2) != sizeof(appconn->nasip)) {
  3237.     syslog(LOG_ERR, "Wrong length of NAS IP address");
  3238.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3239.       }
  3240.       nasip = nasipattr->v.i;
  3241.     }
  3242.  
  3243.     /* NAS PORT */
  3244.     if (!radius_getattr(pack, &nasportattr,
  3245.             RADIUS_ATTR_NAS_PORT, 0, 0, 0)) {
  3246.       if ((nasportattr->l-2) != sizeof(appconn->nasport)) {
  3247.     syslog(LOG_ERR, "Wrong length of NAS port");
  3248.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3249.       }
  3250.       nasport = nasportattr->v.i;
  3251.     }
  3252.  
  3253.     /* Calling Station ID (MAC Address) */
  3254.     if (!radius_getattr(pack, &hismacattr,
  3255.             RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0)) {
  3256.       if (_options.debug)
  3257.         syslog(LOG_DEBUG, "%s(%d): Calling Station ID is: %.*s", __FUNCTION__, __LINE__,
  3258.                hismacattr->l-2, hismacattr->v.t);
  3259.  
  3260.       if ((macstrlen = (size_t)hismacattr->l-2) >= (RADIUS_ATTR_VLEN-1)) {
  3261.     syslog(LOG_ERR, "Wrong length of called station ID");
  3262.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3263.       }
  3264.  
  3265.       memcpy(macstr, hismacattr->v.t, macstrlen);
  3266.       macstr[macstrlen] = 0;
  3267.  
  3268.       /* Replace anything but hex with space */
  3269.       for (i=0; i<macstrlen; i++)
  3270.     if (!isxdigit((int) macstr[i]))
  3271.       macstr[i] = 0x20;
  3272.  
  3273.       if (sscanf (macstr, "%2x %2x %2x %2x %2x %2x",
  3274.           &temp[0], &temp[1], &temp[2],
  3275.           &temp[3], &temp[4], &temp[5]) != 6) {
  3276.     syslog(LOG_ERR, "Failed to convert Calling Station ID to MAC Address");
  3277.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3278.       }
  3279.  
  3280.       for (i = 0; i < PKT_ETH_ALEN; i++)
  3281.     hismac[i] = temp[i];
  3282.     }
  3283.  
  3284.     if (hismacattr) {
  3285.       /*
  3286.        * Look for mac address.
  3287.        * If not found allocate new..
  3288.        */
  3289. #ifdef ENABLE_LAYER3
  3290.       if (_options.layer3) {
  3291.     syslog(LOG_ERR, "Not supported in layer3 mode");
  3292.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3293.       } else {
  3294. #endif
  3295.     if (dhcp_hashget(dhcp, &dhcpconn, hismac)) {
  3296.       if (dhcp_newconn(dhcp, &dhcpconn, hismac)) {
  3297.         syslog(LOG_ERR, "Out of connections");
  3298.         return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3299.       }
  3300.     }
  3301.     if (!(dhcpconn->peer)) {
  3302.       syslog(LOG_ERR, "No peer protocol defined");
  3303.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3304.     }
  3305.     appconn = (struct app_conn_t *)dhcpconn->peer;
  3306. #ifdef ENABLE_LAYER3
  3307.       }
  3308. #endif
  3309.     }
  3310.     else if (nasipattr && nasportattr) { /* Look for NAS IP / Port */
  3311.       if (chilli_getconn(&appconn, 0, nasip, nasport)) {
  3312.     syslog(LOG_ERR, "Unknown connection");
  3313.     radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3314.     return 0;
  3315.       }
  3316.     }
  3317.     else {
  3318.       syslog(LOG_ERR, "Calling Station ID or NAS IP/Port is missing from radius request");
  3319.       radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3320.       return 0;
  3321.     }
  3322.  
  3323.     if (!appconn) {
  3324.       if (_options.debug)
  3325.         syslog(LOG_DEBUG, "%s(%d): No application context for RADIUS proxy", __FUNCTION__, __LINE__);
  3326.       return 0;
  3327.     }
  3328.  
  3329.     /* Silently ignore radius request if allready processing one */
  3330.     if (appconn->radiuswait) {
  3331.       if (appconn->radiuswait == 2) {
  3332.         if (_options.debug)
  3333.           syslog(LOG_DEBUG, "%s(%d): Giving up on previous packet.. not dropping this one", __FUNCTION__, __LINE__);
  3334.     appconn->radiuswait = 0;
  3335.       } else {
  3336.         if (_options.debug)
  3337.           syslog(LOG_DEBUG, "%s(%d): Dropping RADIUS while waiting", __FUNCTION__, __LINE__);
  3338.     appconn->radiuswait++;
  3339.     return 0;
  3340.       }
  3341.     }
  3342.  
  3343.     if (_options.debug)
  3344.       syslog(LOG_DEBUG, "%s(%d): Handing RADIUS accounting proxy packet", __FUNCTION__, __LINE__);
  3345.  
  3346.     dhcpconn = (struct dhcp_conn_t*) appconn->dnlink;
  3347.  
  3348. #ifdef ENABLE_APSESSIONID
  3349.     if (!radius_getattr(pack, &attr,
  3350.             RADIUS_ATTR_ACCT_SESSION_ID, 0, 0, 0)) {
  3351.       int len = attr->l-2;
  3352.       if (len >= sizeof(appconn->s_state.ap_sessionid))
  3353.     len = sizeof(appconn->s_state.ap_sessionid) - 1;
  3354.       memcpy(appconn->s_state.ap_sessionid, attr->v.t, len);
  3355.       appconn->s_state.ap_sessionid[len]=0;
  3356.       if (_options.debug)
  3357.         syslog(LOG_DEBUG, "%s(%d): AP Acct-Session-ID is: %s", __FUNCTION__, __LINE__,
  3358.                appconn->s_state.ap_sessionid);
  3359.     }
  3360. #endif
  3361.  
  3362. #if defined(ENABLE_LOCATION) || defined(ENABLE_PROXYVSA)
  3363.     switch (status_type) {
  3364.       case RADIUS_STATUS_TYPE_START:
  3365.         if (chilli_proxy_radlocation(pack, appconn, 1))
  3366.           return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3367.         break;
  3368.       case RADIUS_STATUS_TYPE_INTERIM_UPDATE:
  3369.       case RADIUS_STATUS_TYPE_STOP:
  3370.         if (chilli_proxy_radlocation(pack, appconn, 0))
  3371.           return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3372.         break;
  3373.     }
  3374. #endif
  3375.  
  3376.     /* -- This needs to be optional --
  3377.        case RADIUS_STATUS_TYPE_STOP:
  3378.        if (!dhcpconn) {
  3379.        syslog(LOG_ERR,"No downlink protocol defined for RADIUS proxy client");
  3380.        return 0;
  3381.        }
  3382.        dhcp_freeconn(dhcpconn, RADIUS_TERMINATE_CAUSE_LOST_CARRIER);
  3383.        break;
  3384.     */
  3385.   }
  3386.  
  3387.   if (_options.proxyonacct) {
  3388.     /*
  3389.      *  Drop the in-coming packet through to the chilli
  3390.      *  RADIUS queue.
  3391.      */
  3392.     struct radius_packet_t acct_pack;
  3393.     if (!radius_default_pack(radius, &acct_pack,
  3394.                  RADIUS_CODE_ACCOUNTING_REQUEST)) {
  3395.       size_t len = ntohs(pack->length) - RADIUS_HDRSIZE;
  3396.       memcpy(acct_pack.payload, pack->payload, len);
  3397.       acct_pack.length = htons(len + RADIUS_HDRSIZE);
  3398.       radius_req(radius, &acct_pack, appconn);
  3399.     }
  3400.   }
  3401.  
  3402.   radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3403.   return 0;
  3404. }
  3405.  
  3406. int access_request(struct radius_packet_t *pack,
  3407.            struct sockaddr_in *peer) {
  3408.   struct radius_packet_t radius_pack;
  3409.  
  3410.   struct ippoolm_t *ipm = NULL;
  3411.  
  3412.   struct radius_attr_t *hisipattr = NULL;
  3413.   struct radius_attr_t *nasipattr = NULL;
  3414.   struct radius_attr_t *nasportattr = NULL;
  3415.   struct radius_attr_t *hismacattr = NULL;
  3416.   struct radius_attr_t *uidattr = NULL;
  3417.   struct radius_attr_t *pwdattr = NULL;
  3418.   struct radius_attr_t *eapattr = NULL;
  3419.  
  3420.   struct in_addr hisip;
  3421.   char pwd[RADIUS_ATTR_VLEN];
  3422.   size_t pwdlen;
  3423.   uint8_t hismac[PKT_ETH_ALEN];
  3424.   char macstr[RADIUS_ATTR_VLEN];
  3425.   size_t macstrlen;
  3426.   unsigned int temp[PKT_ETH_ALEN];
  3427.   int i;
  3428.  
  3429.   struct app_conn_t *appconn = NULL;
  3430.   struct dhcp_conn_t *dhcpconn = NULL;
  3431.  
  3432.   uint8_t resp[MAX_EAP_LEN];     /* EAP response */
  3433.   size_t resplen;                /* Length of EAP response */
  3434.  
  3435.   size_t offset = 0;
  3436.   size_t eaplen = 0;
  3437.   int instance = 0;
  3438.   uint8_t qid;
  3439.  
  3440.   if (_options.debug)
  3441.     syslog(LOG_DEBUG, "%s(%d): RADIUS Access-Request received", __FUNCTION__, __LINE__);
  3442.  
  3443.   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REJECT)) {
  3444.     syslog(LOG_ERR, "radius_default_pack() failed");
  3445.     return -1;
  3446.   }
  3447.  
  3448.   /* result of qnext */
  3449.   qid = radius_pack.id;
  3450.  
  3451.   /* keep in case of reject */
  3452.   radius_pack.id = pack->id;
  3453.  
  3454.   /*
  3455.    *  User is identified by either IP address OR MAC address
  3456.    */
  3457.  
  3458.   /* Framed IP address (Conditional) */
  3459.   if (!radius_getattr(pack, &hisipattr,
  3460.               RADIUS_ATTR_FRAMED_IP_ADDRESS, 0, 0, 0)) {
  3461.     if ((hisipattr->l-2) != sizeof(hisip.s_addr)) {
  3462.       syslog(LOG_ERR, "Wrong length of framed IP address");
  3463.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3464.     }
  3465.     hisip.s_addr = hisipattr->v.i;
  3466.     if (_options.debug)
  3467.       syslog(LOG_DEBUG, "%s(%d): Framed IP address is: %s", __FUNCTION__, __LINE__, inet_ntoa(hisip));
  3468.   }
  3469.  
  3470.   /* Calling Station ID: MAC Address (Conditional) */
  3471.   if (!radius_getattr(pack, &hismacattr,
  3472.               RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0)) {
  3473.     if (_options.debug)
  3474.       syslog(LOG_DEBUG, "%s(%d): Calling Station ID is: %.*s", __FUNCTION__, __LINE__, hismacattr->l-2, hismacattr->v.t);
  3475.  
  3476.     if ((macstrlen = (size_t)hismacattr->l-2) >= (RADIUS_ATTR_VLEN-1)) {
  3477.       syslog(LOG_ERR, "Wrong length of calling station ID");
  3478.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3479.     }
  3480.  
  3481.     memcpy(macstr, hismacattr->v.t, macstrlen);
  3482.     macstr[macstrlen] = 0;
  3483.  
  3484.     /* Replace anything but hex with space */
  3485.     for (i=0; i<macstrlen; i++)
  3486.       if (!isxdigit((int) macstr[i]))
  3487.     macstr[i] = 0x20;
  3488.  
  3489.     if (sscanf (macstr, "%2x %2x %2x %2x %2x %2x",
  3490.         &temp[0], &temp[1], &temp[2],
  3491.         &temp[3], &temp[4], &temp[5]) != 6) {
  3492.       syslog(LOG_ERR, "Failed to convert Calling Station ID to MAC Address");
  3493.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3494.     }
  3495.  
  3496.     for (i = 0; i < PKT_ETH_ALEN; i++)
  3497.       hismac[i] = temp[i];
  3498.   }
  3499.  
  3500.   /* Framed IP address or MAC Address must be given in request */
  3501.   if ((!hisipattr) && (!hismacattr)) {
  3502.     syslog(LOG_ERR, "Framed IP address or Calling Station ID is missing from radius request");
  3503.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3504.   }
  3505.  
  3506.   /* Username (Mandatory) */
  3507.   if (radius_getattr(pack, &uidattr, RADIUS_ATTR_USER_NAME, 0, 0, 0)) {
  3508.     syslog(LOG_ERR, "User-Name is missing from radius request");
  3509.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3510.   }
  3511.  
  3512.   if (hisipattr) { /* Find user based on IP address */
  3513.     if (ippool_getip(ippool, &ipm, &hisip)) {
  3514.       syslog(LOG_ERR, "RADIUS-Request: IP Address not found");
  3515.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3516.     }
  3517.  
  3518.     if ((appconn  = (struct app_conn_t *)ipm->peer)        == NULL ||
  3519.     (dhcpconn = (struct dhcp_conn_t *)appconn->dnlink) == NULL) {
  3520.       syslog(LOG_ERR, "RADIUS-Request: No peer protocol defined");
  3521.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3522.     }
  3523.   }
  3524.   else if (hismacattr) {
  3525.     /*
  3526.      * Look for mac address.
  3527.      * If not found allocate new..
  3528.      */
  3529. #ifdef ENABLE_LAYER3
  3530.     if (_options.layer3) {
  3531.       syslog(LOG_ERR, "Not supported in layer3 mode");
  3532.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3533.     } else {
  3534. #endif
  3535.       if (dhcp_hashget(dhcp, &dhcpconn, hismac)) {
  3536.     if (dhcp_newconn(dhcp, &dhcpconn, hismac)) {
  3537.       syslog(LOG_ERR, "Out of connections");
  3538.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3539.     }
  3540.       }
  3541.       if (!(dhcpconn->peer)) {
  3542.     syslog(LOG_ERR, "No peer protocol defined");
  3543.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3544.       }
  3545.       appconn = (struct app_conn_t *)dhcpconn->peer;
  3546. #ifdef ENABLE_LAYER3
  3547.     }
  3548. #endif
  3549.   }
  3550.   else {
  3551.     syslog(LOG_ERR, "Framed-IP-Address or Calling-Station-ID required in RADIUS request");
  3552.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3553.   }
  3554.  
  3555.   /* Silently ignore radius request if already processing one */
  3556.   if (appconn->radiuswait) {
  3557.     if (appconn->radiuswait == 2) {
  3558.       if (_options.debug)
  3559.         syslog(LOG_DEBUG, "%s(%d): Giving up on previous packet.. not dropping this one", __FUNCTION__, __LINE__);
  3560.       appconn->radiuswait = 0;
  3561.     } else {
  3562.       if (_options.debug)
  3563.         syslog(LOG_DEBUG, "%s(%d): Dropping RADIUS while waiting", __FUNCTION__, __LINE__);
  3564.       appconn->radiuswait++;
  3565.       return 0;
  3566.     }
  3567.   }
  3568.  
  3569.   dhcpconn->lasttime = mainclock_now();
  3570.  
  3571.   /* Password */
  3572.   if (!radius_getattr(pack, &pwdattr, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0)) {
  3573.     if (radius_pwdecode(radius, (uint8_t*) pwd, RADIUS_ATTR_VLEN, &pwdlen,
  3574.             pwdattr->v.t, pwdattr->l-2, pack->authenticator,
  3575.             radius->proxysecret,
  3576.             radius->proxysecretlen)) {
  3577.       syslog(LOG_ERR, "radius_pwdecode() failed");
  3578.       return -1;
  3579.     }
  3580. #if(_debug_)
  3581.     if (_options.debug)
  3582.       syslog(LOG_DEBUG, "%s(%d): Password is: %s", __FUNCTION__, __LINE__, pwd);
  3583. #endif
  3584.   }
  3585.  
  3586.   /* Get EAP message */
  3587.   resplen = 0;
  3588.   do {
  3589.     eapattr=NULL;
  3590.     if (!radius_getattr(pack, &eapattr, RADIUS_ATTR_EAP_MESSAGE, 0, 0,
  3591.             instance++)) {
  3592.       if ((resplen + (size_t)eapattr->l-2) > MAX_EAP_LEN) {
  3593.     syslog(LOG_INFO, "EAP message too long %zu %d", resplen, (int)eapattr->l-2);
  3594.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3595.       }
  3596.       memcpy(resp + resplen, eapattr->v.t, (size_t)eapattr->l-2);
  3597.       resplen += (size_t)eapattr->l-2;
  3598.     }
  3599.   } while (eapattr);
  3600.  
  3601.   if (resplen) {
  3602.     appconn->dnprot = DNPROT_WPA;
  3603.   }
  3604.  
  3605. #if defined(ENABLE_LOCATION) || defined(ENABLE_PROXYVSA)
  3606.   if (chilli_proxy_radlocation(pack, appconn, 1))
  3607.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3608. #endif
  3609.  
  3610.   /* Passwd or EAP must be given in request */
  3611.   if ((!pwdattr) && (!resplen)) {
  3612.     syslog(LOG_ERR, "Password or EAP message is missing from radius request");
  3613.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3614.   }
  3615.  
  3616. #ifdef ENABLE_RADPROXY
  3617.   if (_options.proxymacaccept && !resplen) {
  3618.     syslog(LOG_INFO, "Accepting MAC login");
  3619.     radius_pack.code = RADIUS_CODE_ACCESS_ACCEPT;
  3620.     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3621.   }
  3622. #endif
  3623.  
  3624.   /* CoovaChilli Notes:
  3625.      Dublicate logins should be allowed as it might be the terminal
  3626.      moving from one access point to another. It is however
  3627.      unacceptable to login with another username on top of an allready
  3628.      existing connection
  3629.  
  3630.      TODO: New username should be allowed, but should result in
  3631.      a accounting stop message for the old connection.
  3632.      this does however pose a denial of service attack possibility
  3633.  
  3634.      If allready logged in send back accept message with username
  3635.      TODO ? Should this be a reject: Dont login twice ?
  3636.   */
  3637.  
  3638.   /* Terminate previous session if trying to login with another username */
  3639.   if ((appconn->s_state.authenticated == 1) &&
  3640.       ((strlen(appconn->s_state.redir.username) != uidattr->l-2) ||
  3641.        (memcmp(appconn->s_state.redir.username, uidattr->v.t, uidattr->l-2)))) {
  3642.     terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_USER_REQUEST);
  3643.     if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REJECT)) {
  3644.       syslog(LOG_ERR, "radius_default_pack() failed");
  3645.       return -1;
  3646.     }
  3647.   }
  3648.  
  3649.   /* NAS IP */
  3650.   if (!radius_getattr(pack, &nasipattr, RADIUS_ATTR_NAS_IP_ADDRESS, 0, 0, 0)) {
  3651.     if ((nasipattr->l-2) != sizeof(appconn->nasip)) {
  3652.       syslog(LOG_ERR, "Wrong length of NAS IP address");
  3653.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3654.     }
  3655.     appconn->nasip = nasipattr->v.i;
  3656.   }
  3657.  
  3658.   /* NAS PORT */
  3659.   if (!radius_getattr(pack, &nasportattr, RADIUS_ATTR_NAS_PORT, 0, 0, 0)) {
  3660.     if ((nasportattr->l-2) != sizeof(appconn->nasport)) {
  3661.       syslog(LOG_ERR, "Wrong length of NAS port");
  3662.       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
  3663.     }
  3664.     appconn->nasport = nasportattr->v.i;
  3665.   }
  3666.  
  3667.   /* Store parameters for later use */
  3668.   if (uidattr->l-2 < USERNAMESIZE) {
  3669.     memcpy(appconn->s_state.redir.username,
  3670.        (char *)uidattr->v.t, uidattr->l-2);
  3671.     appconn->s_state.redir.username[uidattr->l-2]=0;
  3672.   }
  3673.  
  3674.  
  3675.   appconn->radiuswait = 1;
  3676.   appconn->radiusid = pack->id;
  3677.  
  3678.   if (pwdattr)
  3679.     appconn->authtype = PAP_PASSWORD;
  3680.   else
  3681.     appconn->authtype = EAP_MESSAGE;
  3682.  
  3683.   memcpy(&appconn->radiuspeer, peer, sizeof(*peer));
  3684.   memcpy(appconn->authenticator, pack->authenticator, RADIUS_AUTHLEN);
  3685.   memcpy(appconn->hismac, dhcpconn->hismac, PKT_ETH_ALEN);
  3686.  
  3687.   /* Build up radius request */
  3688.   radius_pack.code = RADIUS_CODE_ACCESS_REQUEST;
  3689.  
  3690.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
  3691.          uidattr->v.t, uidattr->l - 2);
  3692.  
  3693.   if (appconn->s_state.redir.statelen) {
  3694.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_STATE, 0, 0, 0,
  3695.            appconn->s_state.redir.statebuf,
  3696.            appconn->s_state.redir.statelen);
  3697.   }
  3698.  
  3699.   if (pwdattr)
  3700.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0,
  3701.            (uint8_t*) pwd, pwdlen);
  3702.  
  3703.   /* Include EAP (if present) */
  3704.   offset = 0;
  3705.   while (offset < resplen) {
  3706.  
  3707.     if ((resplen - offset) > RADIUS_ATTR_VLEN)
  3708.       eaplen = RADIUS_ATTR_VLEN;
  3709.     else
  3710.       eaplen = resplen - offset;
  3711.  
  3712.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
  3713.            resp + offset, eaplen);
  3714.  
  3715.     offset += eaplen;
  3716.   }
  3717.  
  3718.   if (resplen) {
  3719.     if (_options.wpaguests)
  3720.       radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
  3721.              RADIUS_VENDOR_COOVACHILLI, RADIUS_ATTR_COOVACHILLI_CONFIG,
  3722.              0, (uint8_t*)"allow-wpa-guests", 16);
  3723.   }
  3724.  
  3725.   chilli_req_attrs(radius, &radius_pack,
  3726.            ACCT_USER,
  3727.            _options.framedservice ? RADIUS_SERVICE_TYPE_FRAMED :
  3728.            RADIUS_SERVICE_TYPE_LOGIN, 0,
  3729.            appconn->unit, appconn->hismac,
  3730.            &appconn->hisip, &appconn->s_state);
  3731.  
  3732.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
  3733.          0, 0, 0, NULL, RADIUS_MD5LEN);
  3734.  
  3735.   /* restore request id to that of queue */
  3736.   radius_pack.id = qid;
  3737.  
  3738.   return radius_req(radius, &radius_pack, appconn);
  3739. }
  3740.  
  3741. /*********************************************************
  3742.  *
  3743.  * radius proxy callback functions (request from radius server)
  3744.  *
  3745.  *********************************************************/
  3746.  
  3747. /* Radius callback when radius request has been received */
  3748. int cb_radius_ind(struct radius_t *rp, struct radius_packet_t *pack,
  3749.           struct sockaddr_in *peer) {
  3750.  
  3751.   if (rp != radius) {
  3752.     syslog(LOG_ERR, "Radius callback from unknown instance");
  3753.     return 0;
  3754.   }
  3755.  
  3756.   switch (pack->code) {
  3757.     case RADIUS_CODE_ACCOUNTING_REQUEST:
  3758.       return accounting_request(pack, peer);
  3759.     case RADIUS_CODE_ACCESS_REQUEST:
  3760.       return access_request(pack, peer);
  3761.     default:
  3762.       syslog(LOG_ERR, "Unsupported radius request received: %d", pack->code);
  3763.       return 0;
  3764.   }
  3765. }
  3766. #endif
  3767.  
  3768. static int
  3769. session_disconnect(struct app_conn_t *appconn,
  3770.            struct dhcp_conn_t *dhcpconn,
  3771.            int term_cause) {
  3772.  
  3773. #ifdef ENABLE_MODULES
  3774.   { int i;
  3775.     for (i=0; i < MAX_MODULES; i++) {
  3776.       if (!_options.modules[i].name[0]) break;
  3777.       if (_options.modules[i].ctx) {
  3778.         struct chilli_module *m =
  3779.         (struct chilli_module *)_options.modules[i].ctx;
  3780.         if (m->dhcp_disconnect)
  3781.           m->dhcp_disconnect(appconn, dhcpconn);
  3782.       }
  3783.     }
  3784.   }
  3785. #endif
  3786.  
  3787.   terminate_appconn(appconn,
  3788.             term_cause ? term_cause :
  3789.             appconn->s_state.terminate_cause ?
  3790.             appconn->s_state.terminate_cause :
  3791.             RADIUS_TERMINATE_CAUSE_LOST_CARRIER);
  3792.  
  3793.   if (appconn->uplink) {
  3794.     struct ippoolm_t *member = (struct ippoolm_t *) appconn->uplink;
  3795.  
  3796. #ifdef ENABLE_UAMANYIP
  3797.     if (_options.uamanyip) {
  3798.       if (!appconn->natip.s_addr) {
  3799.     if (member->in_use && member->is_static) {
  3800.       struct in_addr mask;
  3801.       int res;
  3802.       mask.s_addr = 0xffffffff;
  3803.       res = net_del_route(&member->addr, &appconn->ourip, &mask);
  3804.           if (_options.debug)
  3805.             syslog(LOG_DEBUG, "%s(%d): Removing route: %s %d", __FUNCTION__, __LINE__, inet_ntoa(member->addr), res);
  3806.     }
  3807.       } else {
  3808.     struct ippoolm_t *natipm;
  3809.     if (ippool_getip(ippool, &natipm, &appconn->natip) == 0) {
  3810.       if (ippool_freeip(ippool, natipm)) {
  3811.         syslog(LOG_ERR, "ippool_freeip(%s) failed for nat ip!",
  3812.                    inet_ntoa(appconn->natip));
  3813.       }
  3814.     }
  3815.       }
  3816.     }
  3817. #endif
  3818.  
  3819.     if (member->in_use && (!dhcpconn || !dhcpconn->is_reserved)) {
  3820.       if (ippool_freeip(ippool, member)) {
  3821.     syslog(LOG_ERR, "ippool_freeip(%s) failed!",
  3822.                inet_ntoa(member->addr));
  3823.       }
  3824.     }
  3825.  
  3826. #if defined(ENABLE_TAP) && defined(SIOCDARP)
  3827.     if (_options.usetap) {
  3828.       /*
  3829.        *    USETAP ARP
  3830.        */
  3831.       int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  3832.       if (sockfd > 0) {
  3833.     struct arpreq req;
  3834.  
  3835.     memset(&req, 0, sizeof(req));
  3836.  
  3837.     SET_SA_FAMILY(req.arp_pa, AF_INET);
  3838.     ((struct sockaddr_in *) &req.arp_pa)->sin_addr.s_addr =
  3839.             appconn->hisip.s_addr;
  3840.     req.arp_flags = ATF_PERM | ATF_PUBL;
  3841.  
  3842.     strlcpy(req.arp_dev, tuntap(tun).devname, sizeof(req.arp_dev));
  3843.  
  3844.     if (ioctl(sockfd, SIOCDARP, &req) < 0) {
  3845.       perror("ioctrl()");
  3846.     }
  3847.  
  3848.     safe_close(sockfd);
  3849.       }
  3850.     }
  3851. #endif
  3852.   }
  3853.  
  3854.   if (_options.macdown) {
  3855.     syslog(LOG_DEBUG, "%s(%d): Calling MAC down script: %s", __FUNCTION__, __LINE__, _options.macdown);
  3856.     runscript(appconn, _options.macdown, 0, 0);
  3857.   }
  3858.  
  3859.   if (!dhcpconn || !dhcpconn->is_reserved) {
  3860.     freeconn(appconn);
  3861.     if (dhcpconn)
  3862.       dhcpconn->peer = 0;
  3863.   }
  3864.  
  3865. #ifdef ENABLE_BINSTATFILE
  3866.   if (_options.statusfilesave)
  3867.     printstatus();
  3868. #endif
  3869.  
  3870.   return 0;
  3871. }
  3872.  
  3873. static int
  3874. upprot_getip(struct app_conn_t *appconn,
  3875.          struct in_addr *hisip,
  3876.          struct in_addr *hismask) {
  3877.   struct ippoolm_t *ipm = 0;
  3878.  
  3879.   struct dhcp_conn_t *dhcpconn = (struct dhcp_conn_t *)appconn->dnlink;
  3880.  
  3881. #if(_debug_ > 1)
  3882.   if (_options.debug)
  3883.     syslog(LOG_DEBUG, "%s(%d): UPPROT - GETIP", __FUNCTION__, __LINE__);
  3884. #endif
  3885.  
  3886.   /* If IP address is already allocated: Fill it in */
  3887.   /* This should only happen for UAM */
  3888.   if (appconn->uplink) {
  3889.     ipm = (struct ippoolm_t *)appconn->uplink;
  3890.   }
  3891.  
  3892.   if (ipm == 0) {
  3893.     /* Allocate static or dynamic IP address */
  3894.  
  3895.     if (newip(&ipm, hisip, dhcpconn ? dhcpconn->hismac : 0))
  3896.       return dnprot_reject(appconn);
  3897.  
  3898.     appconn->hisip.s_addr = ipm->addr.s_addr;
  3899.  
  3900.     if (hismask && hismask->s_addr)
  3901.       appconn->hismask.s_addr = hismask->s_addr;
  3902.     else
  3903.       appconn->hismask.s_addr = _options.mask.s_addr;
  3904.  
  3905.     /* TODO: Too many "listen" and "ourip" addresses! */
  3906.     if (!appconn->ourip.s_addr)
  3907.       appconn->ourip.s_addr = _options.dhcplisten.s_addr;
  3908.  
  3909.     appconn->uplink = ipm;
  3910.     ipm->peer = appconn;
  3911.  
  3912. #ifdef ENABLE_GARDENACCOUNTING
  3913.     if (_options.uamgardendata) {
  3914.       acct_req(ACCT_GARDEN, appconn, RADIUS_STATUS_TYPE_START);
  3915.     }
  3916. #endif
  3917.   }
  3918.  
  3919. #ifdef ENABLE_UAMANYIP
  3920.   if (chilli_assign_snat(appconn, 0) != 0) {
  3921.     return -1;
  3922.   }
  3923. #endif
  3924.  
  3925.   return dnprot_accept(appconn);
  3926. }
  3927.  
  3928. void session_param_defaults(struct session_params *params) {
  3929.  
  3930.   if (_options.defsessiontimeout && !params->sessiontimeout)
  3931.     params->sessiontimeout = _options.defsessiontimeout;
  3932.  
  3933.   if (_options.defidletimeout && !params->idletimeout)
  3934.     params->idletimeout = _options.defidletimeout;
  3935.  
  3936.   if (_options.defbandwidthmaxdown && !params->bandwidthmaxdown)
  3937.     params->bandwidthmaxdown = _options.defbandwidthmaxdown;
  3938.  
  3939.   if (_options.defbandwidthmaxup && !params->bandwidthmaxup)
  3940.     params->bandwidthmaxup = _options.defbandwidthmaxup;
  3941.  
  3942.   if (_options.definteriminterval && !params->interim_interval)
  3943.     params->interim_interval = _options.definteriminterval;
  3944. }
  3945.  
  3946. void
  3947. config_radius_session(struct session_params *params,
  3948.               struct radius_packet_t *pack,
  3949.               struct app_conn_t *appconn,
  3950.               int reconfig) {
  3951.   struct radius_attr_t *attr = NULL;
  3952.   size_t offset = 0;
  3953.   /*int is_splash = 0;*/
  3954.   int seen;
  3955.  
  3956.   /* Session timeout */
  3957.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_SESSION_TIMEOUT, 0, 0, 0))
  3958.     params->sessiontimeout = ntohl(attr->v.i);
  3959.   else if (!reconfig)
  3960.     params->sessiontimeout = 0;
  3961.  
  3962.   /* Idle timeout */
  3963.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_IDLE_TIMEOUT, 0, 0, 0))
  3964.     params->idletimeout = ntohl(attr->v.i);
  3965.   else if (!reconfig)
  3966.     params->idletimeout = 0;
  3967.  
  3968.   /* Filter ID */
  3969.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_FILTER_ID, 0, 0, 0)) {
  3970.     params->filteridlen = attr->l-2;
  3971.     memcpy(params->filteridbuf, attr->v.t, attr->l-2);
  3972.     params->filteridbuf[attr->l-2] = 0;
  3973.   }
  3974.   else if (!reconfig) {
  3975.     params->filteridlen = 0;
  3976.     params->filteridbuf[0] = 0;
  3977.   }
  3978.  
  3979.   /* Interim interval */
  3980.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, 0, 0, 0)) {
  3981.     params->interim_interval = ntohl(attr->v.i);
  3982.     if (params->interim_interval < 60) {
  3983.       syslog(LOG_ERR, "Received too small radius Acct-Interim-Interval: %d; resettings to default.",
  3984.              params->interim_interval);
  3985.       params->interim_interval = 0;
  3986.     }
  3987.   }
  3988.   else if (!reconfig)
  3989.     params->interim_interval = 0;
  3990.  
  3991.   /* Bandwidth up */
  3992.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  3993.               RADIUS_VENDOR_WISPR,
  3994.               RADIUS_ATTR_WISPR_BANDWIDTH_MAX_UP, 0))
  3995.     params->bandwidthmaxup = ntohl(attr->v.i);
  3996.   else if (!reconfig)
  3997.     params->bandwidthmaxup = 0;
  3998.  
  3999.   /* Bandwidth down */
  4000.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4001.               RADIUS_VENDOR_WISPR,
  4002.               RADIUS_ATTR_WISPR_BANDWIDTH_MAX_DOWN, 0))
  4003.     params->bandwidthmaxdown = ntohl(attr->v.i);
  4004.   else if (!reconfig)
  4005.     params->bandwidthmaxdown = 0;
  4006.  
  4007. #ifdef RADIUS_ATTR_COOVACHILLI_BANDWIDTH_MAX_UP
  4008.   /* Bandwidth up */
  4009.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4010.               RADIUS_VENDOR_COOVACHILLI,
  4011.               RADIUS_ATTR_COOVACHILLI_BANDWIDTH_MAX_UP, 0))
  4012.     params->bandwidthmaxup = ntohl(attr->v.i) * 1000;
  4013. #endif
  4014.  
  4015. #ifdef RADIUS_ATTR_COOVACHILLI_BANDWIDTH_MAX_DOWN
  4016.   /* Bandwidth down */
  4017.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4018.               RADIUS_VENDOR_COOVACHILLI,
  4019.               RADIUS_ATTR_COOVACHILLI_BANDWIDTH_MAX_DOWN, 0))
  4020.     params->bandwidthmaxdown = ntohl(attr->v.i) * 1000;
  4021. #endif
  4022.  
  4023.   /* Max input octets */
  4024.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4025.               RADIUS_VENDOR_COOVACHILLI,
  4026.               RADIUS_ATTR_COOVACHILLI_MAX_INPUT_OCTETS, 0))
  4027.     params->maxinputoctets = ntohl(attr->v.i);
  4028.   else if (!reconfig)
  4029.     params->maxinputoctets = 0;
  4030.  
  4031.   /* Max output octets */
  4032.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4033.               RADIUS_VENDOR_COOVACHILLI,
  4034.               RADIUS_ATTR_COOVACHILLI_MAX_OUTPUT_OCTETS, 0))
  4035.     params->maxoutputoctets = ntohl(attr->v.i);
  4036.   else if (!reconfig)
  4037.     params->maxoutputoctets = 0;
  4038.  
  4039.   /* Max total octets */
  4040.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4041.               RADIUS_VENDOR_COOVACHILLI,
  4042.               RADIUS_ATTR_COOVACHILLI_MAX_TOTAL_OCTETS, 0))
  4043.     params->maxtotaloctets = ntohl(attr->v.i);
  4044.   else if (!reconfig)
  4045.     params->maxtotaloctets = 0;
  4046.  
  4047.  
  4048.   /* Max input gigawords */
  4049.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4050.               RADIUS_VENDOR_COOVACHILLI,
  4051.               RADIUS_ATTR_COOVACHILLI_MAX_INPUT_GIGAWORDS, 0))
  4052.     params->maxinputoctets |= ((uint64_t)ntohl(attr->v.i) & 0xffffffff) << 32;
  4053.  
  4054.   /* Max output gigawords */
  4055.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4056.               RADIUS_VENDOR_COOVACHILLI,
  4057.               RADIUS_ATTR_COOVACHILLI_MAX_OUTPUT_GIGAWORDS, 0))
  4058.     params->maxoutputoctets |= ((uint64_t)ntohl(attr->v.i) & 0xffffffff) << 32;
  4059.  
  4060.   /* Max total octets */
  4061.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4062.               RADIUS_VENDOR_COOVACHILLI,
  4063.               RADIUS_ATTR_COOVACHILLI_MAX_TOTAL_GIGAWORDS, 0))
  4064.     params->maxtotaloctets |= ((uint64_t)ntohl(attr->v.i) & 0xffffffff) << 32;
  4065.  
  4066.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4067.               RADIUS_VENDOR_COOVACHILLI,
  4068.               RADIUS_ATTR_COOVACHILLI_REQUIRE_UAM, 0)) {
  4069.     memcpy(params->url, attr->v.t, attr->l-2);
  4070.     params->url[attr->l-2] = 0;
  4071.   }
  4072.  
  4073. #ifdef ENABLE_REDIRINJECT
  4074.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4075.               RADIUS_VENDOR_COOVACHILLI,
  4076.               RADIUS_ATTR_COOVACHILLI_INJECT_URL, 0)) {
  4077.     memcpy(params->url, attr->v.t, attr->l-2);
  4078.     params->url[attr->l-2] = 0;
  4079.     params->flags |= UAM_INJECT_URL | REQUIRE_UAM_AUTH;
  4080.   }
  4081. #endif
  4082.  
  4083. #ifdef EX_CONFIG_RADIUS_SESSION
  4084. #include EX_CONFIG_RADIUS_SESSION
  4085. #endif
  4086.  
  4087. #ifdef ENABLE_MULTIROUTE
  4088.   if (tun) {
  4089.     /* Route Index, look-up by interface name */
  4090.     if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4091.             RADIUS_VENDOR_COOVACHILLI,
  4092.             RADIUS_ATTR_COOVACHILLI_ROUTE_TO_INTERFACE, 0)) {
  4093.       char name[256];
  4094.       memcpy(name, attr->v.t, attr->l-2);
  4095.       name[attr->l-2] = 0;
  4096.       params->routeidx = tun_name2idx(tun, name);
  4097.     }
  4098.     else if (!reconfig) {
  4099.       params->routeidx = tun->routeidx;
  4100.     }
  4101.   }
  4102. #endif
  4103.  
  4104. #ifdef ENABLE_COOVACHILLICONFIG
  4105.   {
  4106.     /*
  4107.      *  Looking for CoovaChilli-Config attributes with
  4108.      *  special messages.
  4109.      */
  4110.     const char *adminreset = "admin-reset";
  4111.     const char *uamauth = "require-uam-auth";
  4112.     const char *splash = "splash";
  4113.     const char *logout = "logout";
  4114.  
  4115. #ifdef ENABLE_SESSGARDEN
  4116.     const char *uamallowed = "uamallowed=";
  4117.     const int uamallowed_len = strlen(uamallowed);
  4118. #endif
  4119.  
  4120.     while (!radius_getnextattr(pack, &attr,
  4121.                    RADIUS_ATTR_VENDOR_SPECIFIC,
  4122.                    RADIUS_VENDOR_COOVACHILLI,
  4123.                    RADIUS_ATTR_COOVACHILLI_CONFIG,
  4124.                    0, &offset)) {
  4125.       size_t len = (size_t) attr->l - 2;
  4126.       char *val = (char *) attr->v.t;
  4127.  
  4128.       if (len == strlen(uamauth) && !memcmp(val, uamauth, len)) {
  4129.         if (_options.debug)
  4130.           syslog(LOG_DEBUG, "%s(%d): received require-uam-auth", __FUNCTION__, __LINE__);
  4131.     params->flags |= REQUIRE_UAM_AUTH;
  4132.       }
  4133.       else if (len == strlen(splash) && !memcmp(val, splash, len)) {
  4134.         if (_options.debug)
  4135.           syslog(LOG_DEBUG, "%s(%d): received splash response", __FUNCTION__, __LINE__);
  4136.     params->flags |= REQUIRE_UAM_SPLASH;
  4137.     /*is_splash = 1;*/
  4138.       }
  4139. #ifdef ENABLE_SESSGARDEN
  4140.       else if (len > uamallowed_len && len < 255 &&
  4141.            !memcmp(val, uamallowed, uamallowed_len)) {
  4142.     char name[256];
  4143.  
  4144.     /* copy and null-terminate */
  4145.     len -= uamallowed_len;
  4146.     val += uamallowed_len;
  4147.     memcpy(name, val, len);
  4148.     name[len]=0;
  4149.  
  4150.     if (len == 5 && !memcmp(name,"reset",5)) {
  4151.       params->pass_through_count = 0;
  4152. #ifdef HAVE_PATRICIA
  4153.       if (appconn && appconn->ptree) {
  4154.         patricia_destroy (appconn->ptree, free);
  4155.         appconn->ptree = NULL;
  4156.       }
  4157. #endif
  4158.     } else {
  4159.  
  4160. #ifdef HAVE_PATRICIA
  4161.       if (appconn && appconn->ptree == NULL)
  4162.         appconn->ptree = patricia_new (32);
  4163. #endif
  4164.  
  4165.       pass_throughs_from_string(params->pass_throughs,
  4166.                     SESSION_PASS_THROUGH_MAX,
  4167.                     &params->pass_through_count,
  4168.                     name, 0, 0
  4169. #ifdef HAVE_PATRICIA
  4170.                     , appconn ? appconn->ptree : 0
  4171. #endif
  4172.                     );
  4173.     }
  4174.       }
  4175. #endif
  4176.       else if (appconn && len >= strlen(logout) &&
  4177.            !memcmp(val, logout, strlen(logout))) {
  4178.     if (appconn)
  4179.       terminate_appconn(appconn,
  4180.                 RADIUS_TERMINATE_CAUSE_USER_REQUEST);
  4181.       } else if (appconn && len >= strlen(adminreset) &&
  4182.          !memcmp(val, adminreset, strlen(adminreset))) {
  4183.     dhcp_release_mac(dhcp, appconn->hismac,
  4184.              RADIUS_TERMINATE_CAUSE_ADMIN_RESET);
  4185.       }
  4186.     }
  4187.   }
  4188. #endif
  4189.  
  4190.   seen = 0;
  4191.   offset = 0;
  4192.   while (!radius_getnextattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4193.                  RADIUS_VENDOR_WISPR,
  4194.                  RADIUS_ATTR_WISPR_REDIRECTION_URL,
  4195.                  0, &offset)) {
  4196.     ssize_t clen, nlen = (ssize_t) attr->l - 2;
  4197.     char *url = (char*) attr->v.t;
  4198.  
  4199.     if (seen == 0) { params->url[0]=0; seen=1; }
  4200.     clen = strlen((char*)params->url);
  4201.  
  4202.     if (clen + nlen > sizeof(params->url) - 1)
  4203.       nlen = sizeof(params->url) - clen - 1;
  4204.  
  4205.     if (nlen > 0) {
  4206.       memcpy(params->url + clen, url, nlen);
  4207.       params->url[clen + nlen] = 0;
  4208.       params->flags |= UAM_CLEAR_URL;
  4209.     }
  4210.  
  4211.     /*if (!is_splash) {
  4212.       params->flags |= REQUIRE_REDIRECT;
  4213.       }*/
  4214.   }
  4215.  
  4216.   /* Session-Terminate-Time */
  4217.   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4218.               RADIUS_VENDOR_WISPR,
  4219.               RADIUS_ATTR_WISPR_SESSION_TERMINATE_TIME, 0)) {
  4220.     char attrs[RADIUS_ATTR_VLEN + 1];
  4221.     struct tm stt;
  4222.     int tzhour, tzmin;
  4223.     char *tz;
  4224.     int result;
  4225.  
  4226.     memcpy(attrs, attr->v.t, attr->l-2);
  4227.     attrs[attr->l-2] = 0;
  4228.  
  4229.     memset(&stt, 0, sizeof(stt));
  4230.  
  4231.     result = sscanf(attrs, "%d-%d-%dT%d:%d:%d %d:%d",
  4232.             &stt.tm_year, &stt.tm_mon, &stt.tm_mday,
  4233.             &stt.tm_hour, &stt.tm_min, &stt.tm_sec,
  4234.             &tzhour, &tzmin);
  4235.  
  4236.     if (result == 8) { /* Timezone */
  4237.       /* tzhour and tzmin is hours and minutes east of GMT */
  4238.       /* timezone is defined as seconds west of GMT. Excludes DST */
  4239.       stt.tm_year -= 1900;
  4240.       stt.tm_mon  -= 1;
  4241.       stt.tm_hour -= tzhour; /* Adjust for timezone */
  4242.       stt.tm_min  -= tzmin;  /* Adjust for timezone */
  4243.       /*      stt.tm_hour += daylight;*/
  4244.       /*stt.tm_min  -= (timezone / 60);*/
  4245.       tz = getenv("TZ");
  4246.       setenv("TZ", "", 1); /* Set environment to UTC */
  4247.       tzset();
  4248.       params->sessionterminatetime = mktime(&stt);
  4249.       if (tz) setenv("TZ", tz, 1);
  4250.       else    unsetenv("TZ");
  4251.       tzset();
  4252.     }
  4253.     else if (result >= 6) { /* Local time */
  4254.       tzset();
  4255.       stt.tm_year -= 1900;
  4256.       stt.tm_mon  -= 1;
  4257.       stt.tm_isdst = -1; /*daylight;*/
  4258.       params->sessionterminatetime = mktime(&stt);
  4259.     }
  4260.     else {
  4261.       params->sessionterminatetime = 0;
  4262.       syslog(LOG_WARNING, "Invalid WISPr-Session-Terminate-Time received: %s", attrs);
  4263.     }
  4264.   }
  4265.   else if (!reconfig)
  4266.     params->sessionterminatetime = 0;
  4267.  
  4268.   session_param_defaults(params);
  4269. }
  4270.  
  4271. static int chilliauth_cb(struct radius_t *radius,
  4272.              struct radius_packet_t *pack,
  4273.              struct radius_packet_t *pack_req,
  4274.              void *cbp) {
  4275.  
  4276.   struct radius_attr_t *attr = NULL;
  4277.   size_t offset = 0;
  4278.  
  4279.   if (!pack) {
  4280.     syslog(LOG_ERR, "Radius request timed out");
  4281.     return 0;
  4282.   }
  4283.  
  4284.   if ((pack->code != RADIUS_CODE_ACCESS_REJECT) &&
  4285.       (pack->code != RADIUS_CODE_ACCESS_CHALLENGE) &&
  4286.       (pack->code != RADIUS_CODE_ACCESS_ACCEPT)) {
  4287.     syslog(LOG_ERR, "Unknown radius access reply code %d", pack->code);
  4288.     return 0;
  4289.   }
  4290.  
  4291.   /* ACCESS-ACCEPT */
  4292.   if (pack->code != RADIUS_CODE_ACCESS_ACCEPT) {
  4293.     syslog(LOG_ERR, "Administrative-User Login Failed");
  4294.     return 0;
  4295.   }
  4296.  
  4297.   if (_options.adminupdatefile) {
  4298.  
  4299.     if (_options.debug)
  4300.       syslog(LOG_DEBUG, "%s(%d): looking to replace: %s", __FUNCTION__, __LINE__, _options.adminupdatefile);
  4301.  
  4302.     if (!radius_getnextattr(pack, &attr,
  4303.                 RADIUS_ATTR_VENDOR_SPECIFIC,
  4304.                 RADIUS_VENDOR_COOVACHILLI,
  4305.                 RADIUS_ATTR_COOVACHILLI_CONFIG,
  4306.                 0, &offset)) {
  4307.  
  4308.       char template[] = "/tmp/hs.conf.XXXXXX";
  4309.       char * hs_conf = _options.adminupdatefile;
  4310.  
  4311.       /*
  4312.        *  We have configurations in the administrative-user session.
  4313.        *  Save to a temporary file.
  4314.        */
  4315.  
  4316.       if (_options.debug)
  4317.         syslog(LOG_DEBUG, "%s(%d): using template temp file: %s", __FUNCTION__, __LINE__, template);
  4318.  
  4319.       int fd = mkstemp(template);
  4320.       if (fd > 0) {
  4321.         do {
  4322.           if (safe_write(fd, attr->v.t, attr->l - 2) < 0 || safe_write(fd, "\n", 1) < 0) {
  4323.             syslog(LOG_ERR, "%s: adminupdatefile", strerror(errno));
  4324.             break;
  4325.            }
  4326.          }
  4327.          while (!radius_getnextattr(pack, &attr,
  4328.                   RADIUS_ATTR_VENDOR_SPECIFIC,
  4329.                   RADIUS_VENDOR_COOVACHILLI,
  4330.                   RADIUS_ATTR_COOVACHILLI_CONFIG,
  4331.                   0, &offset));
  4332.  
  4333.       /*
  4334.        *  Check to see if this file is different from the chilli/hs.conf
  4335.        */
  4336.       {
  4337.     int oldfd = open(hs_conf, O_RDONLY);
  4338.  
  4339.     if (fd > 0) {
  4340.      lseek(fd, SEEK_SET, 0);
  4341.       int differ = (oldfd > 0) ? 0 : 1;
  4342.       char b1[100], b2[100];
  4343.       ssize_t r1, r2;
  4344.  
  4345.       if (!differ) {
  4346.         do {
  4347.           r1 = safe_read(fd, b1, sizeof(b1));
  4348.           r2 = safe_read(oldfd, b2, sizeof(b2));
  4349.  
  4350.           if (r1 != r2 || strncmp(b1, b2, r1))
  4351.         differ = 1;
  4352.         }
  4353.         while (!differ && r1 > 0 && r2 > 0);
  4354.       }
  4355.  
  4356.       if (oldfd) {
  4357.           safe_close(oldfd);
  4358.           oldfd=0;
  4359.       }
  4360.  
  4361.       if (differ) {
  4362.             if (_options.debug)
  4363.               syslog(LOG_DEBUG, "%s(%d): Writing out new hs.conf file with administraive-user settings", __FUNCTION__, __LINE__);
  4364.  
  4365.         oldfd = open(hs_conf, O_RDWR | O_TRUNC | O_CREAT, 0644);
  4366.  
  4367.         if (fd > 0 && oldfd > 0) {
  4368.         lseek(fd, SEEK_SET, 0);
  4369.  
  4370.           while ((r1 = safe_read(fd, b1, sizeof(b1))) > 0 &&
  4371.              safe_write(oldfd, b1, r1) > 0);
  4372.  
  4373.           safe_close(oldfd); oldfd=0;
  4374.           do_interval = 1;
  4375.         }
  4376.       }
  4377.     }
  4378.     if (oldfd > 0) safe_close(oldfd);
  4379.       }
  4380.  
  4381.       /* unlink(hs_temp); */
  4382.           safe_close(fd);
  4383.         }
  4384.     }
  4385.   }
  4386.  
  4387.   if (!admin_session.s_state.authenticated) {
  4388.     admin_session.s_state.authenticated = 1;
  4389.     acct_req(ACCT_USER, &admin_session, RADIUS_STATUS_TYPE_START);
  4390.   }
  4391.  
  4392.   /* reset these values to zero */
  4393.   admin_session.s_params.idletimeout = 0;
  4394.   admin_session.s_params.sessionterminatetime = 0;
  4395.  
  4396.   /* should instead honor this with a re-auth (see interval) */
  4397.   admin_session.s_params.sessiontimeout = 0;
  4398.  
  4399.   return 0;
  4400. }
  4401.  
  4402. int cb_radius_acct_conf(struct radius_t *radius,
  4403.             struct radius_packet_t *pack,
  4404.             struct radius_packet_t *pack_req, void *cbp) {
  4405.   struct app_conn_t *appconn = (struct app_conn_t*) cbp;
  4406.  
  4407.   if (!appconn) {
  4408.     syslog(LOG_ERR,"No peer protocol defined");
  4409.     return 0;
  4410.   }
  4411.  
  4412.   if (!pack) /* Timeout */
  4413.     return 0;
  4414.  
  4415.   config_radius_session(&appconn->s_params, pack, appconn, 1);
  4416.   return 0;
  4417. }
  4418.  
  4419. /*********************************************************
  4420.  * radius callback functions (response from radius server)
  4421.  *********************************************************/
  4422. /* Radius callback when access accept/reject/challenge has been received */
  4423. int cb_radius_auth_conf(struct radius_t *radius,
  4424.             struct radius_packet_t *pack,
  4425.             struct radius_packet_t *pack_req, void *cbp) {
  4426.   struct radius_attr_t *hisipattr = NULL;
  4427.   struct radius_attr_t *lmntattr = NULL;
  4428.   struct radius_attr_t *sendattr = NULL;
  4429.   struct radius_attr_t *recvattr = NULL;
  4430.   struct radius_attr_t *succattr = NULL;
  4431.  
  4432.   struct radius_attr_t *stateattr = NULL;
  4433.   struct radius_attr_t *classattr = NULL;
  4434.   struct radius_attr_t *uidattr = NULL;
  4435.  
  4436. #ifdef ENABLE_RADPROXY
  4437.   int instance = 0;
  4438.   struct radius_attr_t *policyattr = NULL;
  4439.   struct radius_attr_t *typesattr = NULL;
  4440.   struct radius_attr_t *eapattr = NULL;
  4441. #endif
  4442.  
  4443.   int force_ip = 0;
  4444.   struct in_addr hisip;
  4445.   struct in_addr hismask;
  4446.  
  4447.   struct app_conn_t *appconn = (struct app_conn_t*) cbp;
  4448.  
  4449.   struct dhcp_conn_t *dhcpconn = NULL;
  4450.  
  4451.   if (!appconn) {
  4452.     syslog(LOG_ERR,"No peer protocol defined");
  4453.     return 0;
  4454.   }
  4455.  
  4456.   dhcpconn = (struct dhcp_conn_t *)appconn->dnlink;
  4457.  
  4458.   /* Initialise */
  4459.   appconn->s_state.redir.statelen = 0;
  4460.   hisip.s_addr = hismask.s_addr = 0;
  4461.  
  4462. #ifdef ENABLE_RADPROXY
  4463.   appconn->challen  = 0;
  4464.   appconn->sendlen  = 0;
  4465.   appconn->recvlen  = 0;
  4466.   appconn->lmntlen  = 0;
  4467. #endif
  4468.  
  4469.   if (!pack) { /* Timeout */
  4470.     syslog(LOG_ERR, "RADIUS request id=%d timed out for session %s",
  4471.            pack_req ? pack_req->id : -1,
  4472.            appconn->s_state.sessionid);
  4473.     if (_options.noradallow) {
  4474.       session_param_defaults(&appconn->s_params);
  4475.       return upprot_getip(appconn, &appconn->reqip, 0);
  4476.     }
  4477.     return dnprot_reject(appconn);
  4478.   }
  4479.  
  4480. #if(_debug_)
  4481.   if (_options.debug)
  4482.     syslog(LOG_DEBUG, "%s(%d): Received RADIUS response id=%d", __FUNCTION__, __LINE__, pack->id);
  4483. #endif
  4484.  
  4485.  
  4486.   /* Framed IP address (Optional) */
  4487.   if (!radius_getattr(pack, &hisipattr, RADIUS_ATTR_FRAMED_IP_ADDRESS, 0, 0, 0)
  4488. #ifdef ENABLE_DHCPRADIUS
  4489.       || !radius_getattr(pack, &hisipattr,
  4490.              RADIUS_ATTR_VENDOR_SPECIFIC,
  4491.              RADIUS_VENDOR_COOVACHILLI,
  4492.              RADIUS_ATTR_COOVACHILLI_DHCP_IP_ADDRESS, 0)
  4493. #endif
  4494.       ) {
  4495.     if ((hisipattr->l-2) != sizeof(struct in_addr)) {
  4496.       syslog(LOG_ERR, "Wrong length of framed IP address");
  4497.       return dnprot_reject(appconn);
  4498.     }
  4499.     force_ip = 1;
  4500.     hisip.s_addr = hisipattr->v.i;
  4501.  
  4502.     if (_options.debug)
  4503.       syslog(LOG_DEBUG, "%s(%d): Framed IP address set to: %s", __FUNCTION__, __LINE__, inet_ntoa(hisip));
  4504.  
  4505.     if (!radius_getattr(pack, &hisipattr, RADIUS_ATTR_FRAMED_IP_NETMASK, 0, 0, 0)
  4506. #ifdef ENABLE_DHCPRADIUS
  4507.     || !radius_getattr(pack, &hisipattr,
  4508.                RADIUS_ATTR_VENDOR_SPECIFIC,
  4509.                RADIUS_VENDOR_COOVACHILLI,
  4510.                RADIUS_ATTR_COOVACHILLI_DHCP_IP_NETMASK, 0)
  4511. #endif
  4512.     ) {
  4513.       if ((hisipattr->l-2) != sizeof(struct in_addr)) {
  4514.     syslog(LOG_ERR, "Wrong length of framed IP netmask");
  4515.     return dnprot_reject(appconn);
  4516.       }
  4517.       hismask.s_addr = hisipattr->v.i;
  4518.  
  4519.       if (_options.debug)
  4520.         syslog(LOG_DEBUG, "%s(%d): Framed IP netmask set to: %s", __FUNCTION__, __LINE__, inet_ntoa(hismask));
  4521.     }
  4522.   }
  4523.   else {
  4524.     hisip.s_addr = appconn->reqip.s_addr;
  4525.   }
  4526.  
  4527.   if (force_ip) {
  4528.     if (appconn->uplink) {
  4529.       struct ippoolm_t *ipm = (struct ippoolm_t *)appconn->uplink;
  4530.  
  4531.       if (hisip.s_addr) {
  4532.     /*
  4533.      *  Force the assigment of an IP address.
  4534.      */
  4535.     if (ipm->addr.s_addr != hisip.s_addr) {
  4536.       uint8_t hwaddr[sizeof(dhcpconn->hismac)];
  4537.       memcpy(hwaddr, dhcpconn->hismac, sizeof(hwaddr));
  4538.  
  4539.           if (_options.debug) {
  4540.             syslog(LOG_DEBUG, "%s(%d): Old ip address freed %s", __FUNCTION__, __LINE__, inet_ntoa(ipm->addr));
  4541.             syslog(LOG_DEBUG, "%s(%d): Resetting ip address to %s", __FUNCTION__, __LINE__, inet_ntoa(hisip));
  4542.           }
  4543.  
  4544.       dhcp_freeconn(dhcpconn, 0);
  4545.       dhcp_newconn(dhcp, &dhcpconn, hwaddr);
  4546.  
  4547.       appconn->dnprot = DNPROT_MAC;
  4548.       appconn->authtype = PAP_PASSWORD;
  4549.       dhcpconn->authstate = DHCP_AUTH_DNAT;
  4550.  
  4551.       ipm = 0;
  4552.     }
  4553.       }
  4554.     }
  4555.   }
  4556.  
  4557. #ifdef ENABLE_DHCPRADIUS
  4558.   if (_options.dhcpradius) {
  4559.     struct radius_attr_t *attr = NULL;
  4560.     if (dhcpconn) {
  4561.       if (!radius_getattr(pack, &attr,
  4562.               RADIUS_ATTR_VENDOR_SPECIFIC,
  4563.               RADIUS_VENDOR_COOVACHILLI,
  4564.               RADIUS_ATTR_COOVACHILLI_DHCP_SERVER_NAME, 0)) {
  4565.     memcpy(dhcpconn->dhcp_opts.sname, attr->v.t, attr->l-2);
  4566.       }
  4567.  
  4568.       if (!radius_getattr(pack, &attr,
  4569.               RADIUS_ATTR_VENDOR_SPECIFIC,
  4570.               RADIUS_VENDOR_COOVACHILLI,
  4571.               RADIUS_ATTR_COOVACHILLI_DHCP_FILENAME, 0)) {
  4572.     memcpy(dhcpconn->dhcp_opts.file, attr->v.t, attr->l-2);
  4573.       }
  4574.  
  4575.       if (!radius_getattr(pack, &attr,
  4576.               RADIUS_ATTR_VENDOR_SPECIFIC,
  4577.               RADIUS_VENDOR_COOVACHILLI,
  4578.               RADIUS_ATTR_COOVACHILLI_DHCP_OPTION, 0)) {
  4579.     memcpy(dhcpconn->dhcp_opts.options, attr->v.t,
  4580.            dhcpconn->dhcp_opts.option_length = attr->l-2);
  4581.       }
  4582.  
  4583.       if (!radius_getattr(pack, &attr,
  4584.               RADIUS_ATTR_VENDOR_SPECIFIC,
  4585.               RADIUS_VENDOR_COOVACHILLI,
  4586.               RADIUS_ATTR_COOVACHILLI_DHCP_DNS1, 0)) {
  4587.     if ((attr->l-2) == sizeof(struct in_addr)) {
  4588.       appconn->dns1.s_addr = attr->v.i;
  4589.       dhcpconn->dns1.s_addr = attr->v.i;
  4590.     }
  4591.       }
  4592.  
  4593.       if (!radius_getattr(pack, &attr,
  4594.               RADIUS_ATTR_VENDOR_SPECIFIC,
  4595.               RADIUS_VENDOR_COOVACHILLI,
  4596.               RADIUS_ATTR_COOVACHILLI_DHCP_DNS2, 0)) {
  4597.     if ((attr->l-2) == sizeof(struct in_addr)) {
  4598.       appconn->dns2.s_addr = attr->v.i;
  4599.       dhcpconn->dns2.s_addr = attr->v.i;
  4600.     }
  4601.       }
  4602.  
  4603.       if (!radius_getattr(pack, &attr,
  4604.               RADIUS_ATTR_VENDOR_SPECIFIC,
  4605.               RADIUS_VENDOR_COOVACHILLI,
  4606.               RADIUS_ATTR_COOVACHILLI_DHCP_GATEWAY, 0)) {
  4607.     if ((attr->l-2) == sizeof(struct in_addr)) {
  4608.       appconn->ourip.s_addr = attr->v.i;
  4609.       dhcpconn->ourip.s_addr = attr->v.i;
  4610.     }
  4611.       }
  4612.  
  4613.       if (!radius_getattr(pack, &attr,
  4614.               RADIUS_ATTR_VENDOR_SPECIFIC,
  4615.               RADIUS_VENDOR_COOVACHILLI,
  4616.               RADIUS_ATTR_COOVACHILLI_DHCP_DOMAIN, 0)) {
  4617.     if (attr->l-2 < DHCP_DOMAIN_LEN) {
  4618.       strncpy(dhcpconn->domain, (char *)attr->v.t, attr->l-2);
  4619.       dhcpconn->domain[attr->l-2]=0;
  4620.     }
  4621.       }
  4622.     }
  4623.   }
  4624. #endif
  4625.  
  4626.   /* ACCESS-REJECT */
  4627.   if (pack->code == RADIUS_CODE_ACCESS_REJECT) {
  4628.     if (_options.debug)
  4629.       syslog(LOG_DEBUG, "%s(%d): Received RADIUS Access-Reject", __FUNCTION__, __LINE__);
  4630.     config_radius_session(&appconn->s_params, pack, appconn, 0); /*XXX*/
  4631.     return dnprot_reject(appconn);
  4632.   }
  4633.  
  4634.   /* Get State */
  4635.   if (!radius_getattr(pack, &stateattr, RADIUS_ATTR_STATE, 0, 0, 0)) {
  4636.     appconn->s_state.redir.statelen = stateattr->l-2;
  4637.     memcpy(appconn->s_state.redir.statebuf, stateattr->v.t, stateattr->l-2);
  4638.   }
  4639.  
  4640. #ifdef ENABLE_RADPROXY
  4641.   /* ACCESS-CHALLENGE */
  4642.   if (pack->code == RADIUS_CODE_ACCESS_CHALLENGE) {
  4643.     if (_options.debug)
  4644.       syslog(LOG_DEBUG, "%s(%d): Received RADIUS Access-Challenge", __FUNCTION__, __LINE__);
  4645.  
  4646.     /* Get EAP message */
  4647.     appconn->challen = 0;
  4648.     do {
  4649.       eapattr=NULL;
  4650.       if (!radius_getattr(pack, &eapattr, RADIUS_ATTR_EAP_MESSAGE, 0, 0, instance++)) {
  4651.     if ((appconn->challen + eapattr->l-2) > MAX_EAP_LEN) {
  4652.       syslog(LOG_INFO, "EAP message too long %zu %d",
  4653.                  appconn->challen, (int) eapattr->l-2);
  4654.       return dnprot_reject(appconn);
  4655.     }
  4656.     memcpy(appconn->chal+appconn->challen, eapattr->v.t, eapattr->l-2);
  4657.     appconn->challen += eapattr->l-2;
  4658.       }
  4659.     } while (eapattr);
  4660.  
  4661.     if (!appconn->challen) {
  4662.       syslog(LOG_INFO, "No EAP message found");
  4663.       return dnprot_reject(appconn);
  4664.     }
  4665.  
  4666.     return dnprot_challenge(appconn);
  4667.   }
  4668. #endif
  4669.  
  4670.   /* ACCESS-ACCEPT */
  4671.   if (pack->code != RADIUS_CODE_ACCESS_ACCEPT) {
  4672.     syslog(LOG_ERR, "Unknown RADIUS code");
  4673.     return dnprot_reject(appconn);
  4674.   }
  4675.  
  4676. #if(_debug_)
  4677.   if (_options.debug)
  4678.     syslog(LOG_DEBUG, "%s(%d): Received RADIUS Access-Accept", __FUNCTION__, __LINE__);
  4679. #endif
  4680.  
  4681.   if (!radius_getattr(pack, &uidattr, RADIUS_ATTR_USER_NAME, 0, 0, 0)) {
  4682.     if (uidattr->l-2 < USERNAMESIZE) {
  4683.       memcpy(appconn->s_state.redir.username,
  4684.         (char *)uidattr->v.t, uidattr->l-2);
  4685.         appconn->s_state.redir.username[uidattr->l-2]=0;
  4686.     }
  4687. #if(_debug_)
  4688.     if (_options.debug)
  4689.       syslog(LOG_DEBUG, "%s(%d): Received User-Name override from RADIUS Access-Accept: %s", __FUNCTION__, __LINE__, appconn->s_state.redir.username);
  4690. #endif
  4691.   }
  4692.  
  4693.   /* Class */
  4694.   if (!radius_getattr(pack, &classattr, RADIUS_ATTR_CLASS, 0, 0, 0)) {
  4695.     appconn->s_state.redir.classlen = classattr->l-2;
  4696.     memcpy(appconn->s_state.redir.classbuf, classattr->v.t, classattr->l-2);
  4697.     /*syslog("!!!! CLASSLEN = %d !!!!", appconn->s_state.redir.classlen);*/
  4698.   }
  4699.   else {
  4700.     /*syslog("!!!! RESET CLASSLEN !!!!");*/
  4701.     appconn->s_state.redir.classlen = 0;
  4702.   }
  4703.  
  4704.   config_radius_session(&appconn->s_params, pack, appconn, 0);
  4705.  
  4706.   if (appconn->is_adminsession) {
  4707.     /* for the admin session */
  4708.     return chilliauth_cb(radius, pack, pack_req, cbp);
  4709.   }
  4710.  
  4711.   if (appconn->s_params.sessionterminatetime) {
  4712.     if (mainclock_rtdiff(appconn->s_params.sessionterminatetime) > 0) {
  4713.       syslog(LOG_WARNING, "WISPr-Session-Terminate-Time in the past received, rejecting");
  4714.       return dnprot_reject(appconn);
  4715.     }
  4716.   }
  4717.  
  4718. #ifdef ENABLE_RADPROXY
  4719.   /* EAP Message */
  4720.   appconn->challen = 0;
  4721.   do {
  4722.     eapattr=NULL;
  4723.     if (!radius_getattr(pack, &eapattr, RADIUS_ATTR_EAP_MESSAGE, 0, 0,
  4724.             instance++)) {
  4725.       if ((appconn->challen + eapattr->l-2) > MAX_EAP_LEN) {
  4726.     syslog(LOG_INFO, "EAP message too long %zu %d",
  4727.                appconn->challen, (int) eapattr->l-2);
  4728.     return dnprot_reject(appconn);
  4729.       }
  4730.       memcpy(appconn->chal + appconn->challen,
  4731.          eapattr->v.t, eapattr->l-2);
  4732.  
  4733.       appconn->challen += eapattr->l-2;
  4734.     }
  4735.   } while (eapattr);
  4736.  
  4737.   /* Get sendkey */
  4738.   if (!radius_getattr(pack, &sendattr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4739.               RADIUS_VENDOR_MS,
  4740.               RADIUS_ATTR_MS_MPPE_SEND_KEY, 0)) {
  4741.     if (radius_keydecode(radius, appconn->sendkey, RADIUS_ATTR_VLEN, &appconn->sendlen,
  4742.              (uint8_t *)&sendattr->v.t, sendattr->l-2,
  4743.              pack_req->authenticator,
  4744.              radius->secret, radius->secretlen)) {
  4745.       syslog(LOG_ERR, "radius_keydecode() failed!");
  4746.       return dnprot_reject(appconn);
  4747.     }
  4748.   }
  4749.  
  4750.   /* Get recvkey */
  4751.   if (!radius_getattr(pack, &recvattr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4752.               RADIUS_VENDOR_MS,
  4753.               RADIUS_ATTR_MS_MPPE_RECV_KEY, 0)) {
  4754.     if (radius_keydecode(radius, appconn->recvkey, RADIUS_ATTR_VLEN, &appconn->recvlen,
  4755.              (uint8_t *)&recvattr->v.t, recvattr->l-2,
  4756.              pack_req->authenticator,
  4757.              radius->secret, radius->secretlen) ) {
  4758.       syslog(LOG_ERR, "radius_keydecode() failed!");
  4759.       return dnprot_reject(appconn);
  4760.     }
  4761.   }
  4762.  
  4763.   /* Get LMNT keys */
  4764.   if (!radius_getattr(pack, &lmntattr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4765.               RADIUS_VENDOR_MS,
  4766.               RADIUS_ATTR_MS_CHAP_MPPE_KEYS, 0)) {
  4767.  
  4768.     /* TODO: Check length of vendor attributes */
  4769.     if (radius_pwdecode(radius, appconn->lmntkeys, RADIUS_MPPEKEYSSIZE,
  4770.             &appconn->lmntlen, (uint8_t *)&lmntattr->v.t,
  4771.             lmntattr->l-2, pack_req->authenticator,
  4772.             radius->secret, radius->secretlen)) {
  4773.       syslog(LOG_ERR, "radius_pwdecode() failed");
  4774.       return dnprot_reject(appconn);
  4775.     }
  4776.   }
  4777.  
  4778.   /* Get encryption policy */
  4779.   if (!radius_getattr(pack, &policyattr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4780.               RADIUS_VENDOR_MS,
  4781.               RADIUS_ATTR_MS_MPPE_ENCRYPTION_POLICY, 0)) {
  4782.     appconn->policy = ntohl(policyattr->v.i);
  4783.   }
  4784.  
  4785.   /* Get encryption types */
  4786.   if (!radius_getattr(pack, &typesattr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4787.               RADIUS_VENDOR_MS,
  4788.               RADIUS_ATTR_MS_MPPE_ENCRYPTION_TYPES, 0)) {
  4789.     appconn->types = ntohl(typesattr->v.i);
  4790.   }
  4791.  
  4792.   /* Get MS_Chap_v2 SUCCESS */
  4793.   if (!radius_getattr(pack, &succattr, RADIUS_ATTR_VENDOR_SPECIFIC,
  4794.               RADIUS_VENDOR_MS,
  4795.               RADIUS_ATTR_MS_CHAP2_SUCCESS, 0)) {
  4796.     if ((succattr->l-5) != MS2SUCCSIZE) {
  4797.       syslog(LOG_ERR, "Wrong length of MS-CHAP2 success: %d", succattr->l-5);
  4798.       return dnprot_reject(appconn);
  4799.     }
  4800.     memcpy(appconn->ms2succ, ((void*)&succattr->v.t)+3, MS2SUCCSIZE);
  4801.   }
  4802. #endif
  4803.  
  4804.   switch(appconn->authtype) {
  4805.  
  4806.     case PAP_PASSWORD:
  4807.       break;
  4808.  
  4809. #ifdef ENABLE_RADPROXY
  4810.     case EAP_MESSAGE:
  4811.       if (!appconn->challen) {
  4812.         syslog(LOG_INFO, "No EAP message found");
  4813.         return dnprot_reject(appconn);
  4814.       }
  4815.       break;
  4816. #endif
  4817.  
  4818.     case CHAP_DIGEST_MD5:
  4819.       break;
  4820.  
  4821.     case CHAP_MICROSOFT:
  4822.       if (!lmntattr) {
  4823.         syslog(LOG_INFO, "No MPPE keys found");
  4824.         return dnprot_reject(appconn);
  4825.       }
  4826.       if (!succattr) {
  4827.         syslog(LOG_ERR, "No MS-CHAP2 success found");
  4828.         return dnprot_reject(appconn);
  4829.       }
  4830.       break;
  4831.  
  4832.     case CHAP_MICROSOFT_V2:
  4833.       if (!sendattr) {
  4834.         syslog(LOG_INFO, "No MPPE sendkey found");
  4835.         return dnprot_reject(appconn);
  4836.       }
  4837.  
  4838.       if (!recvattr) {
  4839.         syslog(LOG_INFO, "No MPPE recvkey found");
  4840.         return dnprot_reject(appconn);
  4841.       }
  4842.  
  4843.       break;
  4844.  
  4845.     default:
  4846.       syslog(LOG_ERR, "Unknown authtype");
  4847.       return dnprot_reject(appconn);
  4848.   }
  4849.  
  4850.   return upprot_getip(appconn, &hisip, &hismask);
  4851. }
  4852.  
  4853. #ifdef ENABLE_COA
  4854. /* Radius callback when coa or disconnect request has been received */
  4855. int cb_radius_coa_ind(struct radius_t *radius, struct radius_packet_t *pack,
  4856.               struct sockaddr_in *peer) {
  4857.   struct app_conn_t *appconn;
  4858.   struct radius_attr_t *uattr = NULL;
  4859.   struct radius_attr_t *sattr = NULL;
  4860.   struct radius_packet_t radius_pack;
  4861.   int authorize = 0;
  4862.   int found = 0;
  4863.   int iscoa = 0;
  4864.  
  4865. #if(_debug_)
  4866.   if (_options.debug)
  4867.     syslog(LOG_DEBUG, "%s(%d): Received coa or disconnect request\n", __FUNCTION__, __LINE__);
  4868. #endif
  4869.  
  4870.   if (pack->code != RADIUS_CODE_DISCONNECT_REQUEST &&
  4871.       pack->code != RADIUS_CODE_COA_REQUEST) {
  4872.     syslog(LOG_ERR, "Radius packet not supported: %d,\n", pack->code);
  4873.     return -1;
  4874.   }
  4875.  
  4876.   iscoa = pack->code == RADIUS_CODE_COA_REQUEST;
  4877.  
  4878.   /* Get username */
  4879.   if (radius_getattr(pack, &uattr, RADIUS_ATTR_USER_NAME, 0, 0, 0)) {
  4880.     syslog(LOG_WARNING, "Username must be included in disconnect request");
  4881.     return -1;
  4882.   }
  4883.  
  4884.   if (!radius_getattr(pack, &sattr, RADIUS_ATTR_ACCT_SESSION_ID, 0, 0, 0))
  4885.     if (_options.debug) {
  4886.       syslog(LOG_DEBUG, "%s(%d): Session-id present in disconnect. Only disconnecting that session\n", __FUNCTION__, __LINE__);
  4887.  
  4888.       syslog(LOG_DEBUG, "%s(%d): Looking for session [username=%.*s,sessionid=%.*s]", __FUNCTION__, __LINE__,
  4889.              uattr->l-2, uattr->v.t, sattr ? sattr->l-2 : 3,
  4890.              sattr ? (char*)sattr->v.t : "all");
  4891.     }
  4892.  
  4893.   for (appconn = firstusedconn; appconn; appconn = appconn->next) {
  4894.  
  4895.     if (!appconn->inuse) { syslog(LOG_ERR, "Connection with inuse == 0!"); }
  4896.  
  4897.     if (
  4898.             (strlen(appconn->s_state.redir.username) == uattr->l-2 &&
  4899.              !memcmp(appconn->s_state.redir.username, uattr->v.t, uattr->l-2)) &&
  4900.             (!sattr ||
  4901.              (strlen(appconn->s_state.sessionid) == sattr->l-2 &&
  4902.               !strncasecmp(appconn->s_state.sessionid, (char*)sattr->v.t, sattr->l-2)))) {
  4903.  
  4904. #if(_debug_)
  4905.       if (_options.debug)
  4906.         syslog(LOG_DEBUG, "%s(%d): Found session %s", __FUNCTION__, __LINE__, appconn->s_state.sessionid);
  4907. #endif
  4908.  
  4909.       if (iscoa) {
  4910.     struct radius_attr_t *attr = NULL;
  4911.  
  4912.     /* Session state */
  4913.     if (!radius_getattr(pack, &attr,
  4914.                 RADIUS_ATTR_VENDOR_SPECIFIC,
  4915.                 RADIUS_VENDOR_COOVACHILLI,
  4916.                 RADIUS_ATTR_COOVACHILLI_SESSION_STATE, 0)) {
  4917.       uint32_t v = ntohl(attr->v.i);
  4918.       switch (v) {
  4919.             case RADIUS_VALUE_COOVACHILLI_SESSION_AUTH:
  4920.               if (!appconn->s_state.authenticated)
  4921.                 authorize = 1;
  4922.               break;
  4923.             case RADIUS_VALUE_COOVACHILLI_SESSION_NOAUTH:
  4924.               if (appconn->s_state.authenticated)
  4925.                 terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_USER_REQUEST);
  4926.               break;
  4927.       }
  4928.     }
  4929.       } else {
  4930.     terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_ADMIN_RESET);
  4931.       }
  4932.  
  4933.       config_radius_session(&appconn->s_params, pack, appconn, 0);
  4934.  
  4935.       if (authorize)
  4936.     dnprot_accept(appconn);
  4937.  
  4938.       found = 1;
  4939.     }
  4940.   }
  4941.  
  4942.   if (found) {
  4943.     if (radius_default_pack(radius, &radius_pack,
  4944.                 iscoa ? RADIUS_CODE_COA_ACK : RADIUS_CODE_DISCONNECT_ACK)) {
  4945.       syslog(LOG_ERR, "radius_default_pack() failed");
  4946.       return -1;
  4947.     }
  4948.   }
  4949.   else {
  4950.     if (radius_default_pack(radius, &radius_pack,
  4951.                 iscoa ? RADIUS_CODE_COA_NAK : RADIUS_CODE_DISCONNECT_NAK)) {
  4952.       syslog(LOG_ERR, "radius_default_pack() failed");
  4953.       return -1;
  4954.     }
  4955.   }
  4956.  
  4957.   radius_pack.id = pack->id;
  4958.   (void) radius_coaresp(radius, &radius_pack, peer, pack->authenticator);
  4959.  
  4960.   return 0;
  4961. }
  4962. #endif
  4963.  
  4964. /***********************************************************
  4965.  *
  4966.  * dhcp callback functions
  4967.  *
  4968.  ***********************************************************/
  4969.  
  4970. /* DHCP callback for allocating new IP address */
  4971. /* In the case of WPA it is allready allocated,
  4972.  * for UAM address is allocated before authentication */
  4973. int cb_dhcp_request(struct dhcp_conn_t *conn, struct in_addr *addr,
  4974.             uint8_t *dhcp_pkt, size_t dhcp_len) {
  4975.   struct app_conn_t *appconn = conn->peer;
  4976.   struct ippoolm_t *ipm = 0;
  4977.   char domacauth = (char) _options.macauth;
  4978.   char allocate = 1;
  4979.  
  4980. #if(_debug_)
  4981.   syslog(LOG_DEBUG, "%s(%d): DHCP request for IP address %s", __FUNCTION__, __LINE__,
  4982.          addr ? inet_ntoa(*addr) : "n/a");
  4983. #endif
  4984.  
  4985.   if (!appconn) {
  4986.     syslog(LOG_ERR, "Peer protocol not defined");
  4987.     return -1;
  4988.   }
  4989.  
  4990. #ifdef ENABLE_UAMANYIP
  4991.   /* if uamanyip is on we have to filter out which ip's are allowed */
  4992.   if (_options.uamanyip && addr && addr->s_addr) {
  4993.  
  4994.     if (addr->s_addr == _options.uamlisten.s_addr) {
  4995.       return -1;
  4996.     }
  4997.  
  4998.     if (_options.uamanyipex_addr.s_addr &&
  4999.     (addr->s_addr & _options.uamanyipex_mask.s_addr) ==
  5000.     _options.uamanyipex_addr.s_addr) {
  5001.       return -1;
  5002.     }
  5003.  
  5004.     if ((addr->s_addr & ipv4ll_mask.s_addr) == ipv4ll_ip.s_addr) {
  5005.       /* clients with an IPv4LL ip normally have no default gw assigned, rendering uamanyip useless
  5006.      They must rather get a proper dynamic ip via dhcp */
  5007.       if (_options.debug)
  5008.         syslog(LOG_DEBUG, "%s(%d): IPv4LL/APIPA address requested, ignoring %s", __FUNCTION__, __LINE__,
  5009.                inet_ntoa(*addr));
  5010.       return -1;
  5011.     }
  5012.   }
  5013. #endif
  5014.  
  5015.   /* Save for MAC auth later */
  5016.   appconn->reqip.s_addr = addr ? addr->s_addr : 0;
  5017.  
  5018.   if (appconn->uplink) {
  5019.  
  5020.     /*
  5021.      *  IP Address is already known and allocated.
  5022.      */
  5023.     ipm = (struct ippoolm_t*) appconn->uplink;
  5024.  
  5025.   } else {
  5026.  
  5027.     if ( ! conn->is_reserved) {
  5028.  
  5029.       if ((_options.macoklen) &&
  5030.       (appconn->dnprot == DNPROT_DHCP_NONE) &&
  5031.       !maccmp(conn->hismac)) {
  5032.  
  5033.     /*
  5034.      *  When using macallowed option, and hismac matches.
  5035.      */
  5036.     appconn->dnprot = DNPROT_MAC;
  5037.  
  5038.     if (_options.macallowlocal) {
  5039.       char mac[MACSTRLEN+1];
  5040.  
  5041.       snprintf(mac, sizeof(mac), MAC_FMT, MAC_ARG(conn->hismac));
  5042.  
  5043.       strlcpy(appconn->s_state.redir.username, mac, USERNAMESIZE);
  5044.  
  5045.       if (_options.macsuffix) {
  5046.         size_t ulen = strlen(appconn->s_state.redir.username);
  5047.         strlcpy(appconn->s_state.redir.username + ulen,
  5048.                     _options.macsuffix, USERNAMESIZE - ulen);
  5049.       }
  5050.  
  5051.       /*
  5052.        *  Local MAC allowed list, authenticate without RADIUS.
  5053.        */
  5054.       upprot_getip(appconn, &appconn->reqip, 0);
  5055.  
  5056.       syslog(LOG_INFO, "Granted MAC=%s with IP=%s access without radius auth",
  5057.                  mac, inet_ntoa(appconn->hisip));
  5058.  
  5059.       ipm = (struct ippoolm_t*) appconn->uplink;
  5060.       domacauth = 0;
  5061.  
  5062.     } else {
  5063.       /*
  5064.        *  Otherwise, authenticate with RADIUS.
  5065.        */
  5066.       auth_radius(appconn, 0, 0, dhcp_pkt, dhcp_len);
  5067.  
  5068.       allocate = !_options.strictmacauth;
  5069.       domacauth = 0;
  5070.     }
  5071.  
  5072.       } else if ((_options.macauth) &&
  5073.          (appconn->dnprot == DNPROT_DHCP_NONE)) {
  5074.  
  5075.     /*
  5076.      *  Using macauth option to authenticate via RADIUS.
  5077.      */
  5078.     appconn->dnprot = DNPROT_MAC;
  5079.  
  5080.     auth_radius(appconn, 0, 0, dhcp_pkt, dhcp_len);
  5081.  
  5082.     allocate = !_options.strictmacauth;
  5083.     domacauth = 0;
  5084.       }
  5085.     }
  5086.   }
  5087.  
  5088.   if (!ipm) {
  5089.  
  5090.     if (!allocate)
  5091.       return -1;
  5092.  
  5093.     if (appconn->dnprot != DNPROT_DHCP_NONE && appconn->hisip.s_addr) {
  5094.       syslog(LOG_WARNING, "Requested IP address when already allocated (hisip %s)",
  5095.              inet_ntoa(appconn->hisip));
  5096.       appconn->reqip.s_addr = appconn->hisip.s_addr;
  5097.     }
  5098.  
  5099.     /* Allocate dynamic IP address */
  5100.     /* XXX  if (ippool_newip(ippool, &ipm, &appconn->reqip, 0)) {*/
  5101.     if (newip(&ipm, &appconn->reqip, conn->hismac)) {
  5102.       syslog(LOG_ERR, "Failed allocate dynamic IP address");
  5103.       return -1;
  5104.     }
  5105.  
  5106.     appconn->hisip.s_addr = ipm->addr.s_addr;
  5107.     appconn->hismask.s_addr = _options.mask.s_addr;
  5108.  
  5109.     if (_options.debug)
  5110.       syslog(LOG_DEBUG, "%s(%d): Client MAC="MAC_FMT" assigned IP %s" , __FUNCTION__, __LINE__,
  5111.              MAC_ARG(conn->hismac), inet_ntoa(appconn->hisip));
  5112.  
  5113. #ifdef ENABLE_MODULES
  5114.     { int i;
  5115.       for (i=0; i < MAX_MODULES; i++) {
  5116.     if (!_options.modules[i].name[0]) break;
  5117.     if (_options.modules[i].ctx) {
  5118.       struct chilli_module *m =
  5119.               (struct chilli_module *)_options.modules[i].ctx;
  5120.       if (m->dhcp_connect)
  5121.         m->dhcp_connect(appconn, conn);
  5122.     }
  5123.       }
  5124.     }
  5125. #endif
  5126.  
  5127.     /* TODO: Too many "listen" and "our" addresses hanging around */
  5128.     if (!appconn->ourip.s_addr)
  5129.       appconn->ourip.s_addr = _options.dhcplisten.s_addr;
  5130.  
  5131.     appconn->uplink = ipm;
  5132.     ipm->peer = appconn;
  5133.  
  5134. #ifdef ENABLE_GARDENACCOUNTING
  5135.     if (_options.uamgardendata) {
  5136.       acct_req(ACCT_GARDEN, appconn, RADIUS_STATUS_TYPE_START);
  5137.     }
  5138. #endif
  5139.  
  5140. #ifdef ENABLE_UAMANYIP
  5141.     if (chilli_assign_snat(appconn, 0) != 0) {
  5142.       return -1;
  5143.     }
  5144. #endif
  5145.   }
  5146.  
  5147.   if (ipm) {
  5148.     dhcp_set_addrs(conn,
  5149.            &ipm->addr, &_options.mask,
  5150.            &appconn->ourip, &appconn->mask,
  5151.            &_options.dns1, &_options.dns2);
  5152.   }
  5153.  
  5154.   if (!appconn->s_state.authenticated) {
  5155.  
  5156.     if (domacauth) {
  5157.       auth_radius(appconn, 0, 0, dhcp_pkt, dhcp_len);
  5158.     }
  5159.  
  5160.     /* if not already authenticated, ensure DNAT authstate */
  5161. #ifdef ENABLE_LAYER3
  5162.     if (!_options.layer3)
  5163. #endif
  5164.       conn->authstate = DHCP_AUTH_DNAT;
  5165.   }
  5166.  
  5167.   /* If IP was requested before authentication it was UAM */
  5168.   if (appconn->dnprot == DNPROT_DHCP_NONE)
  5169.     appconn->dnprot = DNPROT_UAM;
  5170.  
  5171.   if (_options.dhcpnotidle)
  5172.     appconn->s_state.last_up_time = mainclock.tv_sec;
  5173.  
  5174.   return 0;
  5175. }
  5176.  
  5177.  
  5178. int chilli_connect(struct app_conn_t **appconn, struct dhcp_conn_t *conn) {
  5179.   struct app_conn_t *aconn;
  5180.  
  5181. #if(_debug_)
  5182.   if (_options.debug)
  5183.     syslog(LOG_DEBUG, "%s(%d): New Chilli Connection", __FUNCTION__, __LINE__);
  5184. #endif
  5185.  
  5186.   /* Allocate new application connection */
  5187.   if (chilli_new_conn(appconn)) {
  5188.     syslog(LOG_ERR, "Failed to allocate connection");
  5189.     return -1;
  5190.   }
  5191.  
  5192.   aconn = *appconn;
  5193.   aconn->dnlink =  conn;
  5194.   aconn->dnprot =  DNPROT_DHCP_NONE;
  5195.  
  5196.   aconn->net.s_addr = _options.net.s_addr;
  5197.   aconn->mask.s_addr = _options.mask.s_addr;
  5198.   aconn->dns1.s_addr = _options.dns1.s_addr;
  5199.   aconn->dns2.s_addr = _options.dns2.s_addr;
  5200.  
  5201.   if (conn) {
  5202.     memcpy(aconn->hismac, conn->hismac, PKT_ETH_ALEN);
  5203.   }
  5204.  
  5205.   set_sessionid(aconn, 1);
  5206.  
  5207.   app_conn_set_idx(aconn, conn);
  5208.  
  5209. #ifdef ENABLE_BINSTATFILE
  5210.   if (_options.statusfilesave)
  5211.     printstatus();
  5212. #endif
  5213.  
  5214.   return 0;
  5215. }
  5216.  
  5217. /* DHCP callback for establishing new connection */
  5218. int cb_dhcp_connect(struct dhcp_conn_t *conn) {
  5219.   struct app_conn_t *appconn;
  5220.  
  5221.   if (_options.debug)
  5222.     syslog(LOG_DEBUG, "%s(%d): New DHCP request from MAC="MAC_FMT, __FUNCTION__, __LINE__,
  5223.            MAC_ARG(conn->hismac));
  5224.  
  5225.   if (chilli_connect(&appconn, conn))
  5226.     return 0;
  5227.  
  5228.   conn->peer = appconn;
  5229.  
  5230.   conn->authstate = DHCP_AUTH_NONE; /* TODO: Not yet authenticated */
  5231.  
  5232.   if (_options.macup) {
  5233.     if (_options.debug)
  5234.       syslog(LOG_DEBUG, "%s(%d): Calling MAC up script: %s", __FUNCTION__, __LINE__, _options.macup);
  5235.     runscript(appconn, _options.macup, 0, 0);
  5236.   }
  5237.  
  5238.   return 0;
  5239. }
  5240.  
  5241. #ifdef ENABLE_LAYER3
  5242. struct app_conn_t * chilli_connect_layer3(struct in_addr *src, struct dhcp_conn_t *conn) {
  5243.   struct app_conn_t *appconn = 0;
  5244.   struct ippoolm_t *ipm = 0;
  5245.  
  5246.   if (ippool_getip(ippool, &ipm, src)) {
  5247.     if (_options.debug)
  5248.       syslog(LOG_DEBUG, "%s(%d): New Layer3 %s", __FUNCTION__, __LINE__, inet_ntoa(*src));
  5249.     if (ippool_newip(ippool, &ipm, src, 1)) {
  5250.       if (ippool_newip(ippool, &ipm, src, 0)) {
  5251.     syslog(LOG_ERR, "Failed to allocate either static or dynamic IP address");
  5252.     return 0;
  5253.       }
  5254.     }
  5255.   }
  5256.  
  5257.   if (!ipm) {
  5258.     if (_options.debug)
  5259.       syslog(LOG_DEBUG, "%s(%d): unknown ip", __FUNCTION__, __LINE__);
  5260.     return 0;
  5261.   }
  5262.  
  5263.   if ((appconn = (struct app_conn_t *)ipm->peer) == NULL) {
  5264.     if (chilli_getconn(&appconn, src->s_addr, 0, 0)) {
  5265.       if (chilli_connect(&appconn, conn)) {
  5266.     syslog(LOG_ERR, "chilli_connect()");
  5267.     return 0;
  5268.       }
  5269.     }
  5270.   }
  5271.  
  5272.   appconn->s_state.last_up_time = mainclock_now();
  5273.   appconn->hisip.s_addr = src->s_addr;
  5274.   appconn->hismask.s_addr = _options.mask.s_addr;
  5275.   appconn->dnprot = DNPROT_LAYER3;
  5276.   appconn->uplink = ipm;
  5277.   ipm->peer = appconn;
  5278.   return appconn;
  5279. }
  5280. #endif
  5281.  
  5282. #ifdef ENABLE_CHILLIQUERY
  5283. static char *state2name(int authstate) {
  5284.   switch(authstate) {
  5285.     case DHCP_AUTH_NONE:   return "none";
  5286.     case DHCP_AUTH_DROP:   return "drop";
  5287.     case DHCP_AUTH_PASS:   return "pass";
  5288.     case DHCP_AUTH_DNAT:   return "dnat";
  5289.     case DHCP_AUTH_SPLASH: return "splash";
  5290. #ifdef ENABLE_LAYER3
  5291.     case DHCP_AUTH_ROUTER: return "layer2";
  5292. #endif
  5293.     default:               return "unknown";
  5294.   }
  5295. }
  5296.  
  5297. int chilli_getinfo(struct app_conn_t *appconn, bstring b, int fmt) {
  5298.   uint32_t sessiontime = 0;
  5299.   uint32_t idletime = 0;
  5300.  
  5301.   if (appconn->s_state.authenticated) {
  5302.     sessiontime = mainclock_diffu(appconn->s_state.start_time);
  5303.     idletime    = mainclock_diffu(appconn->s_state.last_up_time);
  5304.   }
  5305.  
  5306.   switch(fmt) {
  5307. #ifdef ENABLE_JSON
  5308.     case LIST_JSON_FMT:
  5309.       if (appconn->s_state.authenticated)
  5310.         session_json_fmt(&appconn->s_state, &appconn->s_params, b, 0);
  5311.       break;
  5312. #endif
  5313.     default:
  5314.       {
  5315.         bstring tmp = bfromcstr("");
  5316.  
  5317.         /* adding: session-id auth-state user-name */
  5318.         bassignformat(tmp, " %.*s %d %.*s",
  5319.                       appconn->s_state.sessionid[0] ? strlen(appconn->s_state.sessionid) : 1,
  5320.                       appconn->s_state.sessionid[0] ? appconn->s_state.sessionid : "-",
  5321.                       appconn->s_state.authenticated,
  5322.                       appconn->s_state.redir.username[0] ? strlen(appconn->s_state.redir.username) : 1,
  5323.                       appconn->s_state.redir.username[0] ? appconn->s_state.redir.username : "-");
  5324.         bconcat(b, tmp);
  5325.  
  5326.         /* adding: session-time/session-timeout idle-time/idle-timeout */
  5327.         bassignformat(tmp, " %d/%d %d/%d",
  5328.                       sessiontime, (int)appconn->s_params.sessiontimeout,
  5329.                       idletime, (int)appconn->s_params.idletimeout);
  5330.         bconcat(b, tmp);
  5331.  
  5332.         /* adding: input-octets/max-input-octets */
  5333. #ifdef ENABLE_GARDENACCOUNTING
  5334.         if (_options.uamgardendata && _options.uamotherdata)
  5335.           bassignformat(tmp, " %lld/%lld/%lld/%lld",
  5336.                         appconn->s_state.input_octets,
  5337.                         appconn->s_params.maxinputoctets,
  5338.                         appconn->s_state.garden_input_octets,
  5339.                         appconn->s_state.other_input_octets);
  5340.         else if (_options.uamgardendata)
  5341.           bassignformat(tmp, " %lld/%lld/%lld",
  5342.                         appconn->s_state.input_octets,
  5343.                         appconn->s_params.maxinputoctets,
  5344.                         appconn->s_state.garden_input_octets);
  5345.         else
  5346. #endif
  5347.           bassignformat(tmp, " %lld/%lld",
  5348.                         appconn->s_state.input_octets,
  5349.                         appconn->s_params.maxinputoctets);
  5350.         bconcat(b, tmp);
  5351.  
  5352.         /* adding: output-octets/max-output-octets */
  5353. #ifdef ENABLE_GARDENACCOUNTING
  5354.         if (_options.uamgardendata && _options.uamotherdata)
  5355.           bassignformat(tmp, " %lld/%lld/%lld/%lld",
  5356.                         appconn->s_state.output_octets,
  5357.                         appconn->s_params.maxoutputoctets,
  5358.                         appconn->s_state.garden_output_octets,
  5359.                         appconn->s_state.other_output_octets);
  5360.         else if (_options.uamgardendata)
  5361.           bassignformat(tmp, " %lld/%lld/%lld",
  5362.                         appconn->s_state.output_octets,
  5363.                         appconn->s_params.maxoutputoctets,
  5364.                         appconn->s_state.garden_output_octets);
  5365.         else
  5366. #endif
  5367.           bassignformat(tmp, " %lld/%lld",
  5368.                         appconn->s_state.output_octets,
  5369.                         appconn->s_params.maxoutputoctets);
  5370.         bconcat(b, tmp);
  5371.  
  5372.         /* adding: max-total-octets option-swapoctets */
  5373.         bassignformat(tmp, " %lld %d",
  5374.                       appconn->s_params.maxtotaloctets, _options.swapoctets);
  5375.         bconcat(b, tmp);
  5376.  
  5377. #ifdef ENABLE_LEAKYBUCKET
  5378.         /* adding: max-bandwidth-up max-bandwidth-down */
  5379.         if (appconn->s_state.bucketupsize) {
  5380.           bassignformat(tmp, " %d%%/%lld",
  5381.                         (int) (appconn->s_state.bucketup * 100 /
  5382.                                appconn->s_state.bucketupsize),
  5383.                         appconn->s_params.bandwidthmaxup);
  5384.           bconcat(b, tmp);
  5385.         } else
  5386. #endif
  5387.           bcatcstr(b, " 0/0");
  5388.  
  5389. #ifdef ENABLE_LEAKYBUCKET
  5390.         if (appconn->s_state.bucketdownsize) {
  5391.           bassignformat(tmp, " %d%%/%lld ",
  5392.                         (int) (appconn->s_state.bucketdown * 100 /
  5393.                                appconn->s_state.bucketdownsize),
  5394.                         appconn->s_params.bandwidthmaxdown);
  5395.           bconcat(b, tmp);
  5396.         } else
  5397. #endif
  5398.           bcatcstr(b, " 0/0 ");
  5399.  
  5400.         /* adding: original url */
  5401.         if (appconn->s_state.redir.userurl[0])
  5402.           bcatcstr(b, appconn->s_state.redir.userurl);
  5403.         else
  5404.           bcatcstr(b, "-");
  5405.  
  5406. #ifdef ENABLE_IEEE8021Q
  5407.         /* adding: vlan, if one */
  5408.         if (_options.ieee8021q && appconn->s_state.tag8021q) {
  5409.           bassignformat(tmp, " vlan=%d",
  5410.                         (int)ntohs(appconn->s_state.tag8021q &
  5411.                                    PKT_8021Q_MASK_VID));
  5412.           bconcat(b, tmp);
  5413.         } else {
  5414. #endif
  5415. #ifdef ENABLE_MULTILAN
  5416.           if (app_conn_idx(appconn)) {
  5417.             bassignformat(tmp, " vlan=%s",
  5418.                           _options.moreif[app_conn_idx(appconn)-1].vlan ?
  5419.                           _options.moreif[app_conn_idx(appconn)-1].vlan :
  5420.                           _options.moreif[app_conn_idx(appconn)-1].dhcpif);
  5421.           } else {
  5422.             bassignformat(tmp, " vlan=%s", _options.vlan);
  5423.           }
  5424.           bconcat(b, tmp);
  5425. #endif
  5426. #ifdef ENABLE_IEEE8021Q
  5427.         }
  5428. #endif
  5429.  
  5430. #ifdef ENABLE_LOCATION
  5431.         if (appconn->s_state.location[0]) {
  5432.           bstring tmp2 = bfromcstr("");
  5433.           bcatcstr(b, " loc=");
  5434.           bassigncstr(tmp, appconn->s_state.location);
  5435.           redir_urlencode(tmp, tmp2);
  5436.           bconcat(b, tmp2);
  5437.           bdestroy(tmp2);
  5438.         }
  5439. #endif
  5440.  
  5441.         bdestroy(tmp);
  5442.       }
  5443.   }
  5444.   return 0;
  5445. }
  5446.  
  5447. void chilli_print(bstring s, int listfmt,
  5448.           struct app_conn_t *appconn,
  5449.           struct dhcp_conn_t *conn) {
  5450.  
  5451.   if (!appconn && conn)
  5452.     appconn = (struct app_conn_t *)conn->peer;
  5453.  
  5454.   if (
  5455. #ifdef ENABLE_LAYER3
  5456.           !_options.layer3 &&
  5457. #endif
  5458.           (!appconn || !appconn->inuse)) {
  5459. #if(_debug_)
  5460.     if (_options.debug)
  5461.       syslog(LOG_DEBUG, "%s(%d): Can not print info about unused chilli connection", __FUNCTION__, __LINE__);
  5462. #endif
  5463.     return;
  5464.   } else if (conn && !conn->inuse) {
  5465. #if(_debug_)
  5466.     if (_options.debug)
  5467.       syslog(LOG_DEBUG, "%s(%d): Can not print info about unused dhcp connection", __FUNCTION__, __LINE__);
  5468. #endif
  5469.     return;
  5470.   } else {
  5471.     bstring b = bfromcstr("");
  5472.     bstring tmp = bfromcstr("");
  5473.  
  5474.     switch(listfmt) {
  5475. #ifdef ENABLE_JSON
  5476.       case LIST_JSON_FMT:
  5477.         if ((conn && conn != dhcp->firstusedconn) ||
  5478.             (appconn && appconn != firstusedconn))
  5479.           bcatcstr(b, ",");
  5480.  
  5481.         bcatcstr(b, "{");
  5482.  
  5483.         if (appconn) {
  5484.           bcatcstr(b, "\"nasPort\":");
  5485.           bassignformat(tmp, "%d", appconn->unit);
  5486.           bconcat(b, tmp);
  5487.           bcatcstr(b, ",\"clientState\":");
  5488.           bassignformat(tmp, "%d", appconn->s_state.authenticated);
  5489.           bconcat(b, tmp);
  5490.           bcatcstr(b, ",\"ipAddress\":\"");
  5491.           bcatcstr(b, inet_ntoa(appconn->hisip));
  5492.           bcatcstr(b, "\"");
  5493.         }
  5494.  
  5495.         if (conn) {
  5496.           if (appconn) bcatcstr(b, ",");
  5497.           bcatcstr(b, "\"macAddress\":\"");
  5498.           bassignformat(tmp, MAC_FMT, MAC_ARG(conn->hismac));
  5499.           bconcat(b, tmp);
  5500.           bcatcstr(b, "\",\"dhcpState\":\"");
  5501.           bcatcstr(b, state2name(conn->authstate));
  5502.           bcatcstr(b, "\"");
  5503.         }
  5504.  
  5505.         if (appconn)
  5506.           chilli_getinfo(appconn, b, listfmt);
  5507.  
  5508.         bcatcstr(b, "}");
  5509.         break;
  5510. #endif
  5511.  
  5512.       default:
  5513.         if (conn && !appconn)
  5514.           bassignformat(b, MAC_FMT" %s", MAC_ARG(conn->hismac),
  5515.                         state2name(conn->authstate));
  5516.         else if (conn)
  5517.           bassignformat(b, MAC_FMT" %s %s", MAC_ARG(conn->hismac),
  5518.                         inet_ntoa(conn->hisip), state2name(conn->authstate));
  5519.         else
  5520.           bassignformat(b, "%s", inet_ntoa(appconn->hisip));
  5521.  
  5522.         switch(listfmt) {
  5523.           case LIST_LONG_FMT:
  5524.             if (appconn)
  5525.               chilli_getinfo(appconn, b, listfmt);
  5526.             break;
  5527.           case LIST_SHORT_FMT:
  5528.             if (conn) {
  5529.               bassignformat(tmp, " %d/%d",
  5530.                             mainclock_diff(conn->lasttime),
  5531.                             dhcp->lease);
  5532.               bconcat(b, tmp);
  5533.             }
  5534.             break;
  5535.         }
  5536.  
  5537.         bcatcstr(b, "\n");
  5538.         break;
  5539.     }
  5540.  
  5541.     bconcat(s, b);
  5542.  
  5543.     bdestroy(b);
  5544.     bdestroy(tmp);
  5545.   }
  5546. }
  5547. #endif
  5548.  
  5549. static void
  5550. clear_appconn(struct app_conn_t *appconn) {
  5551.   appconn->s_params.bandwidthmaxup =
  5552.       appconn->s_params.bandwidthmaxdown =
  5553.       appconn->s_params.maxinputoctets =
  5554.       appconn->s_params.maxoutputoctets =
  5555.       appconn->s_params.maxtotaloctets =
  5556.       appconn->s_params.sessiontimeout = 0;
  5557.   appconn->s_params.idletimeout = 0;
  5558.   appconn->s_params.interim_interval = 0;
  5559.   appconn->s_params.sessionterminatetime = 0;
  5560. }
  5561.  
  5562. int terminate_appconn(struct app_conn_t *appconn, int terminate_cause) {
  5563.  
  5564.   if (appconn->s_state.authenticated == 1) {
  5565.  
  5566.     dnprot_terminate(appconn);
  5567.  
  5568.     appconn->s_state.terminate_cause = terminate_cause;
  5569.  
  5570. #ifdef ENABLE_MODULES
  5571.     { int i;
  5572.       for (i=0; i < MAX_MODULES; i++) {
  5573.     if (!_options.modules[i].name[0]) break;
  5574.     if (_options.modules[i].ctx) {
  5575.       struct chilli_module *m =
  5576.               (struct chilli_module *)_options.modules[i].ctx;
  5577.       if (m->session_stop)
  5578.         m->session_stop(appconn);
  5579.     }
  5580.       }
  5581.     }
  5582. #endif
  5583.  
  5584.     if (_options.condown && !(appconn->s_params.flags & NO_SCRIPT)) {
  5585.       if (_options.debug)
  5586.         syslog(LOG_DEBUG, "%s(%d): Calling connection down script: %s\n", __FUNCTION__, __LINE__, _options.condown);
  5587.       runscript(appconn, _options.condown, 0, 0);
  5588.     }
  5589.  
  5590.     acct_req(ACCT_USER, appconn, RADIUS_STATUS_TYPE_STOP);
  5591.  
  5592.     clear_appconn(appconn);
  5593.     set_sessionid(appconn, 0);
  5594.  
  5595. #ifdef ENABLE_STATFILE
  5596.     if (_options.statusfilesave)
  5597.       printstatus();
  5598. #endif
  5599.   }
  5600.  
  5601.   return 0;
  5602. }
  5603.  
  5604. /* Callback when a dhcp connection is deleted */
  5605. int cb_dhcp_disconnect(struct dhcp_conn_t *conn, int term_cause) {
  5606.   struct app_conn_t *appconn;
  5607.  
  5608.   syslog(LOG_INFO, "DHCP Released MAC="MAC_FMT" IP=%s",
  5609.          MAC_ARG(conn->hismac), inet_ntoa(conn->hisip));
  5610.  
  5611.   if (_options.debug)
  5612.     syslog(LOG_DEBUG, "%s(%d): DHCP connection removed", __FUNCTION__, __LINE__);
  5613.  
  5614.   if (!conn->peer) {
  5615.     /* No appconn allocated. Stop here */
  5616. #ifdef ENABLE_BINSTATFILE
  5617.     if (_options.statusfilesave)
  5618.       printstatus();
  5619. #endif
  5620.     return 0;
  5621.   }
  5622.  
  5623.   appconn = (struct app_conn_t*) conn->peer;
  5624.  
  5625.   return session_disconnect(appconn, conn, term_cause);
  5626. }
  5627.  
  5628. /* Callback for receiving messages from dhcp */
  5629. int cb_dhcp_data_ind(struct dhcp_conn_t *conn, uint8_t *pack, size_t len) {
  5630.   struct app_conn_t *appconn = dhcp_get_appconn_pkt(conn, pkt_iphdr(pack), 0);
  5631.   struct pkt_ipphdr_t *ipph = pkt_ipphdr(pack);
  5632.  
  5633.   /*if (_options.debug)
  5634.     syslog(LOG_DEBUG, "cb_dhcp_data_ind. Packet received. DHCP authstate: %d\n",
  5635.     conn->authstate);*/
  5636.  
  5637. #ifdef ENABLE_LEAKYBUCKET
  5638.   if (_options.scalewin && appconn && appconn->s_state.bucketup) {
  5639.     uint16_t win = appconn->s_state.bucketupsize -
  5640.         appconn->s_state.bucketup;
  5641.     //log_dbg("window scaling to %d", win);
  5642.     pkt_shape_tcpwin((struct pkt_iphdr_t *)ipph, win);
  5643.   }
  5644. #endif
  5645.  
  5646.   if (!appconn) {
  5647. #ifdef ENABLE_LAYER3
  5648.     if (_options.layer3) {
  5649.       struct ippoolm_t *ipm = 0;
  5650.       struct in_addr addr;
  5651.  
  5652.       addr.s_addr = ipph->saddr;
  5653.  
  5654.       if (!addr.s_addr) {
  5655.     return tun_encaps(tun, pack, len, 0);
  5656.       }
  5657.  
  5658.       if (ippool_getip(ippool, &ipm, &addr)) {
  5659.         if (_options.debug)
  5660.           syslog(LOG_DEBUG, "%s(%d): unknown IP address: %s", __FUNCTION__, __LINE__, inet_ntoa(addr));
  5661.     return -1;
  5662.       }
  5663.  
  5664.       appconn = ipm->peer;
  5665.     }
  5666.     if (!appconn)
  5667. #endif
  5668.     {
  5669.       syslog(LOG_ERR, "No peer protocol defined");
  5670.       return -1;
  5671.     }
  5672.   }
  5673.  
  5674.   switch (appconn->dnprot) {
  5675.     case DNPROT_NULL:
  5676.     case DNPROT_DHCP_NONE:
  5677.       if (_options.debug)
  5678.         syslog(LOG_DEBUG, "%s(%d): NULL: %d", __FUNCTION__, __LINE__, appconn->dnprot);
  5679.       return -1;
  5680.  
  5681.     case DNPROT_UAM:
  5682.     case DNPROT_WPA:
  5683.     case DNPROT_MAC:
  5684. #ifdef ENABLE_EAPOL
  5685.     case DNPROT_EAPOL:
  5686. #endif
  5687. #ifdef ENABLE_LAYER3
  5688.     case DNPROT_LAYER3:
  5689. #endif
  5690.       break;
  5691.  
  5692.     default:
  5693.       syslog(LOG_ERR, "Unknown downlink protocol: %d", appconn->dnprot);
  5694.       break;
  5695.   }
  5696.  
  5697. #ifdef ENABLE_UAMANYIP
  5698.   /**
  5699.    * packet is coming from an anyip client, therefore SNAT address
  5700.    * has been assigned from dynamic pool. So, let's do the SNAT here.
  5701.    */
  5702.   if (_options.uamanyip && appconn->natip.s_addr) {
  5703. #if(_debug_ > 1)
  5704.     if (_options.debug)
  5705.       syslog(LOG_DEBUG, "%s(%d): SNAT to: %s", __FUNCTION__, __LINE__, inet_ntoa(appconn->natip));
  5706. #endif
  5707.     ipph->saddr = appconn->natip.s_addr;
  5708.     if (chksum((struct pkt_iphdr_t *) ipph) < 0)
  5709.       return 0;
  5710.   }
  5711. #endif
  5712.  
  5713.   /*
  5714.    * If the ip dst is uamlisten and pdst is uamport we won't call leaky_bucket,
  5715.    * and we always send these packets through to the tun/tap interface (index 0)
  5716.    */
  5717.   if (ipph->daddr  == _options.uamlisten.s_addr &&
  5718.       (ipph->dport == htons(_options.uamport)
  5719. #ifdef ENABLE_UAMUIPORT
  5720.        || ipph->dport == htons(_options.uamuiport)
  5721. #endif
  5722.        )) {
  5723.     return tun_encaps(tun, pack, len, 0);
  5724.   }
  5725.  
  5726.   if (chilli_acct_fromsub(appconn, ipph))
  5727.     return 0;
  5728.  
  5729.   return tun_encaps(tun, pack, len, appconn->s_params.routeidx);
  5730. }
  5731.  
  5732. int chilli_acct_fromsub(struct app_conn_t *appconn,
  5733.             struct pkt_ipphdr_t *ipph) {
  5734.   int len = ntohs(ipph->tot_len);
  5735. #ifdef ENABLE_GARDENACCOUNTING
  5736.   char checked_garden = 0;
  5737. #endif
  5738.   char is_garden = 0;
  5739.   char is_auth;
  5740.   char do_acct;
  5741. #ifdef ENABLE_LEAKYBUCKET
  5742.   char do_bw;
  5743. #endif
  5744.  
  5745.   is_auth = appconn->s_state.authenticated == 1;
  5746.  
  5747.   if (is_auth) {
  5748.  
  5749.     do_acct = is_auth;
  5750. #ifdef ENABLE_LEAKYBUCKET
  5751.     do_bw = is_auth;
  5752. #endif
  5753.  
  5754. #ifdef ENABLE_AUTHEDALLOWED
  5755.     if (dhcp_garden_check_auth(dhcp, 0, appconn, ipph, 1)) {
  5756.       /*
  5757.        *  Change to garden accounting.
  5758.        */
  5759.       if (_options.nousergardendata)
  5760.     is_garden = 1;
  5761. #ifdef ENABLE_LEAKYBUCKET
  5762.       do_bw = 0;
  5763.       if (_options.debug)
  5764.         syslog(LOG_DEBUG, "%s(%d): !!!! Skipping leaky bucket because of authedallowed", __FUNCTION__, __LINE__);
  5765. #endif
  5766.     }
  5767. #endif
  5768.  
  5769.     if (_options.uamauthedallowed
  5770. #ifdef ENABLE_LEAKYBUCKET
  5771.         && do_bw
  5772. #endif
  5773.         ) {
  5774. #ifdef ENABLE_GARDENACCOUNTING
  5775.       checked_garden = 1;
  5776. #endif
  5777.       if (dhcp_garden_check(dhcp, 0, appconn, ipph, 1)) {
  5778.     /*
  5779.      *  Garden accounting taken care of in dhcp_garden_check()
  5780.      */
  5781.     do_acct = 0;
  5782. #ifdef ENABLE_LEAKYBUCKET
  5783.     do_bw = 0;
  5784.         if (_options.debug)
  5785.           syslog(LOG_DEBUG, "%s(%d): !!!! Skipping leaky bucket because of uamauthedallowed", __FUNCTION__, __LINE__);
  5786. #endif
  5787.       }
  5788.     }
  5789.  
  5790. #ifdef ENABLE_GARDENACCOUNTING
  5791.     if (_options.nousergardendata) {
  5792.       if (!checked_garden) {
  5793.     checked_garden = 1;
  5794.     if (dhcp_garden_check(dhcp, 0, appconn, ipph, 1)) {
  5795.       do_acct = 0;
  5796.     }
  5797.       }
  5798.     }
  5799. #endif
  5800.  
  5801. #ifdef ENABLE_LEAKYBUCKET
  5802. #ifndef COUNT_UPLINK_DROP
  5803.     if (do_bw) {
  5804.       if (leaky_bucket(appconn, len, 0)) return 1;
  5805.     }
  5806. #endif
  5807. #endif
  5808.  
  5809.     if (do_acct) {
  5810.  
  5811.       if (is_garden) {
  5812. #ifdef ENABLE_GARDENACCOUNTING
  5813.     if (_options.swapoctets) {
  5814.       appconn->s_state.garden_input_octets += len;
  5815.       if (admin_session.s_state.authenticated) {
  5816.         admin_session.s_state.garden_input_octets += len;
  5817.       }
  5818.     } else {
  5819.       appconn->s_state.garden_output_octets += len;
  5820.       if (admin_session.s_state.authenticated) {
  5821.         admin_session.s_state.garden_output_octets += len;
  5822.       }
  5823.     }
  5824. #endif
  5825.       } else {
  5826.     if (_options.swapoctets) {
  5827.       appconn->s_state.input_packets++;
  5828.       appconn->s_state.input_octets += len;
  5829.       if (admin_session.s_state.authenticated) {
  5830.         admin_session.s_state.input_packets++;
  5831.         admin_session.s_state.input_octets += len;
  5832.       }
  5833.     } else {
  5834.       appconn->s_state.output_packets++;
  5835.       appconn->s_state.output_octets += len;
  5836.       if (admin_session.s_state.authenticated) {
  5837.         admin_session.s_state.output_packets++;
  5838.         admin_session.s_state.output_octets += len;
  5839.       }
  5840.     }
  5841.       }
  5842.     }
  5843.  
  5844. #ifdef ENABLE_LEAKYBUCKET
  5845. #ifdef COUNT_UPLINK_DROP
  5846.     if (do_bw) {
  5847.       if (leaky_bucket(appconn, len, 0)) return 1;
  5848.     }
  5849. #endif
  5850. #endif
  5851.   }
  5852.  
  5853.   appconn->s_state.last_time = mainclock.tv_sec;
  5854.   appconn->s_state.last_up_time = mainclock.tv_sec;
  5855.  
  5856.   return 0;
  5857. }
  5858.  
  5859. int chilli_acct_tosub(struct app_conn_t *appconn,
  5860.               struct pkt_ipphdr_t *ipph) {
  5861.   int len = ntohs(ipph->tot_len);
  5862. #ifdef ENABLE_GARDENACCOUNTING
  5863.   char checked_garden = 0;
  5864. #endif
  5865.   char is_garden = 0;
  5866.   char is_auth;
  5867.   char do_acct;
  5868. #ifdef ENABLE_LEAKYBUCKET
  5869.   char do_bw;
  5870. #endif
  5871.  
  5872.   is_auth = appconn->s_state.authenticated == 1;
  5873.  
  5874.   if (is_auth) {
  5875.  
  5876.     do_acct = is_auth;
  5877. #ifdef ENABLE_LEAKYBUCKET
  5878.     do_bw = is_auth;
  5879. #endif
  5880.  
  5881. #ifdef ENABLE_AUTHEDALLOWED
  5882.     if (dhcp_garden_check_auth(dhcp, 0, appconn, ipph, 0)) {
  5883.       /*
  5884.        *  Change to garden accounting.
  5885.        */
  5886.       if (_options.nousergardendata)
  5887.     is_garden = 1;
  5888. #ifdef ENABLE_LEAKYBUCKET
  5889.       do_bw = 0;
  5890. #endif
  5891.     }
  5892. #endif
  5893.  
  5894.     if (_options.uamauthedallowed
  5895. #ifdef ENABLE_LEAKYBUCKET
  5896.         && do_bw
  5897. #endif
  5898.         ) {
  5899. #ifdef ENABLE_GARDENACCOUNTING
  5900.       checked_garden = 1;
  5901. #endif
  5902.       if (dhcp_garden_check(dhcp, 0, appconn, ipph, 0)) {
  5903.     /*
  5904.      *  Garden accounting taken care of in dhcp_garden_check()
  5905.      */
  5906.     do_acct = 0;
  5907. #ifdef ENABLE_LEAKYBUCKET
  5908.     do_bw = 0;
  5909. #endif
  5910.       }
  5911.     }
  5912.  
  5913. #ifdef ENABLE_GARDENACCOUNTING
  5914.     if (_options.nousergardendata) {
  5915.       if (!checked_garden) {
  5916.     checked_garden = 1;
  5917.     if (dhcp_garden_check(dhcp, 0, appconn, ipph, 0)) {
  5918.       do_acct = 0;
  5919.     }
  5920.       }
  5921.     }
  5922. #endif
  5923.  
  5924. #ifdef ENABLE_LEAKYBUCKET
  5925. #ifndef COUNT_DOWNLINK_DROP
  5926.     if (do_bw) {
  5927.       if (leaky_bucket(appconn, 0, len)) return 1;
  5928.     }
  5929. #endif
  5930. #endif
  5931.  
  5932.     if (do_acct) {
  5933.  
  5934.       if (is_garden) {
  5935. #ifdef ENABLE_GARDENACCOUNTING
  5936.     if (_options.swapoctets) {
  5937.       appconn->s_state.garden_output_octets += len;
  5938.       if (admin_session.s_state.authenticated) {
  5939.         admin_session.s_state.garden_output_octets += len;
  5940.       }
  5941.     } else {
  5942.       appconn->s_state.garden_input_octets += len;
  5943.       if (admin_session.s_state.authenticated) {
  5944.         admin_session.s_state.garden_input_octets += len;
  5945.       }
  5946.     }
  5947. #endif
  5948.       } else {
  5949.     if (_options.swapoctets) {
  5950.       appconn->s_state.output_packets++;
  5951.       appconn->s_state.output_octets += len;
  5952.       if (admin_session.s_state.authenticated) {
  5953.         admin_session.s_state.output_packets++;
  5954.         admin_session.s_state.output_octets += len;
  5955.       }
  5956.     } else {
  5957.       appconn->s_state.input_packets++;
  5958.       appconn->s_state.input_octets += len;
  5959.       if (admin_session.s_state.authenticated) {
  5960.         admin_session.s_state.input_packets++;
  5961.         admin_session.s_state.input_octets += len;
  5962.       }
  5963.     }
  5964.       }
  5965.     }
  5966.  
  5967. #ifdef ENABLE_LEAKYBUCKET
  5968. #ifdef COUNT_DOWNLINK_DROP
  5969.     if (do_bw) {
  5970.       if (leaky_bucket(appconn, 0, len)) return 1;
  5971.     }
  5972. #endif
  5973. #endif
  5974.   }
  5975.  
  5976.   appconn->s_state.last_time = mainclock.tv_sec;
  5977.  
  5978.   return 0;
  5979. }
  5980.  
  5981. #ifdef ENABLE_EAPOL
  5982. /* Callback for receiving messages from eapol */
  5983. int cb_dhcp_eap_ind(struct dhcp_conn_t *conn, uint8_t *pack, size_t len) {
  5984.   struct eap_packet_t *eap = (struct eap_packet_t *)pack;
  5985.   struct app_conn_t *appconn = conn->peer;
  5986.   struct radius_packet_t radius_pack;
  5987.   size_t offset;
  5988.  
  5989. #if(_debug_)
  5990.   if (_options.debug)
  5991.     syslog(LOG_DEBUG, "%s(%d): EAP Packet received", __FUNCTION__, __LINE__);
  5992. #endif
  5993.  
  5994.   /* If this is the first EAPOL authentication request */
  5995.   if ((appconn->dnprot == DNPROT_DHCP_NONE) ||
  5996.       (appconn->dnprot == DNPROT_EAPOL)) {
  5997.     if ((eap->code == 2) && /* Response */
  5998.     (eap->type == 1) && /* Identity */
  5999.     (len > 5) &&        /* Must be at least 5 octets */
  6000.     ((len - 5) < REDIR_USERNAMESIZE-1 )) {
  6001.       memcpy(appconn->s_state.redir.username, eap->payload, len - 5);
  6002.       appconn->s_state.redir.username[len - 5] = 0;
  6003.       appconn->dnprot = DNPROT_EAPOL;
  6004.       appconn->authtype = EAP_MESSAGE;
  6005.     }
  6006.     else if (appconn->dnprot == DNPROT_DHCP_NONE) {
  6007.       syslog(LOG_ERR, "Initial EAP response was not a valid identity response!");
  6008.       return 0;
  6009.     }
  6010.   }
  6011.  
  6012.   /* Return if not EAPOL */
  6013.   if (appconn->dnprot != DNPROT_EAPOL) {
  6014.     syslog(LOG_WARNING, "Received EAP message, processing for authentication");
  6015.     appconn->dnprot = DNPROT_EAPOL;
  6016.     return 0;
  6017.   }
  6018.  
  6019.   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REQUEST)) {
  6020.     syslog(LOG_ERR, "radius_default_pack() failed");
  6021.     return -1;
  6022.   }
  6023.  
  6024.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
  6025.                  (uint8_t*) appconn->s_state.redir.username,
  6026.                  strlen(appconn->s_state.redir.username));
  6027.  
  6028.   /* Include EAP (if present) */
  6029.   offset = 0;
  6030.   while (offset < len) {
  6031.     size_t eaplen;
  6032.  
  6033.     if ((len - offset) > RADIUS_ATTR_VLEN)
  6034.       eaplen = RADIUS_ATTR_VLEN;
  6035.     else
  6036.       eaplen = len - offset;
  6037.  
  6038.     radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
  6039.            pack + offset, eaplen);
  6040.  
  6041.     offset += eaplen;
  6042.   }
  6043.  
  6044.   chilli_req_attrs(radius, &radius_pack,
  6045.            ACCT_USER,
  6046.            _options.framedservice ? RADIUS_SERVICE_TYPE_FRAMED :
  6047.            RADIUS_SERVICE_TYPE_LOGIN, 0,
  6048.            appconn->unit, appconn->hismac,
  6049.            &appconn->hisip, &appconn->s_state);
  6050.  
  6051.   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
  6052.          0, 0, 0, NULL, RADIUS_MD5LEN);
  6053.  
  6054.   return radius_req(radius, &radius_pack, appconn);
  6055. }
  6056. #endif
  6057.  
  6058. /***********************************************************
  6059.  *
  6060.  *   uam message handling functions
  6061.  *
  6062.  ***********************************************************/
  6063.  
  6064. int static uam_msg(struct redir_msg_t *msg) {
  6065.  
  6066.   struct ippoolm_t *ipm;
  6067.   struct app_conn_t *appconn = NULL;
  6068.   struct dhcp_conn_t* dhcpconn;
  6069.  
  6070. #if defined(HAVE_NETFILTER_QUEUE) || defined(HAVE_NETFILTER_COOVA)
  6071.   if (_options.uamlisten.s_addr != _options.dhcplisten.s_addr) {
  6072.     msg->mdata.address.sin_addr.s_addr  = msg->mdata.address.sin_addr.s_addr & ~(_options.mask.s_addr);
  6073.     msg->mdata.address.sin_addr.s_addr |= _options.dhcplisten.s_addr & _options.mask.s_addr;
  6074.   }
  6075. #endif
  6076.  
  6077.   if (ippool_getip(ippool, &ipm, &msg->mdata.address.sin_addr)) {
  6078.     if (_options.debug)
  6079.       syslog(LOG_DEBUG, "%s(%d): UAM login with unknown IP address: %s", __FUNCTION__, __LINE__, inet_ntoa(msg->mdata.address.sin_addr));
  6080.     return 0;
  6081.   }
  6082.  
  6083.   if ((appconn  = (struct app_conn_t *)ipm->peer)        == NULL ||
  6084.       (dhcpconn = (struct dhcp_conn_t *)appconn->dnlink) == NULL) {
  6085.     syslog(LOG_ERR, "No peer protocol defined");
  6086.     return 0;
  6087.   }
  6088.  
  6089.   if (appconn->s_state.authenticated == 0 || msg->mtype == REDIR_LOGOUT) {
  6090.     /* Ensure that the session is not already authenticated before changing session */
  6091.     if (msg->mdata.opt & REDIR_MSG_OPT_REDIR)
  6092.       memcpy(&appconn->s_state.redir, &msg->mdata.redir, sizeof(msg->mdata.redir));
  6093.  
  6094.     if (msg->mdata.opt & REDIR_MSG_OPT_PARAMS)
  6095.       memcpy(&appconn->s_params, &msg->mdata.params, sizeof(msg->mdata.params));
  6096.  
  6097.     if (msg->mdata.opt & REDIR_MSG_NSESSIONID)
  6098.       set_sessionid(appconn, 0);
  6099.   }
  6100.  
  6101.   switch(msg->mtype) {
  6102.  
  6103.     case REDIR_LOGIN:
  6104.       if (appconn->uamabort) {
  6105.         syslog(LOG_INFO, "UAM login from username=%s IP=%s was aborted!",
  6106.            msg->mdata.redir.username, inet_ntoa(appconn->hisip));
  6107.         appconn->uamabort = 0;
  6108.         return 0;
  6109.       }
  6110.  
  6111.       syslog(LOG_INFO, "Successful UAM login from username=%s IP=%s",
  6112.          msg->mdata.redir.username, inet_ntoa(appconn->hisip));
  6113.  
  6114.       /* Initialise */
  6115.       appconn->s_params.routeidx = tun->routeidx;
  6116.       appconn->s_state.redir.statelen = 0;
  6117.  
  6118. #ifdef ENABLE_RADPROXY
  6119.       appconn->challen  = 0;
  6120.       appconn->sendlen  = 0;
  6121.       appconn->recvlen  = 0;
  6122.       appconn->lmntlen  = 0;
  6123. #endif
  6124.  
  6125.       memcpy(appconn->hismac, dhcpconn->hismac, PKT_ETH_ALEN);
  6126.  
  6127. #ifdef ENABLE_LEAKYBUCKET
  6128.       leaky_bucket_init(appconn);
  6129. #endif
  6130.  
  6131.       return upprot_getip(appconn, 0, 0);
  6132.  
  6133.     case REDIR_LOGOUT:
  6134.  
  6135.       syslog(LOG_INFO, "Received UAM logoff from username=%s IP=%s",
  6136.          appconn->s_state.redir.username, inet_ntoa(appconn->hisip));
  6137.  
  6138.       if (_options.debug)
  6139.         syslog(LOG_DEBUG, "%s(%d): Received logoff from UAM", __FUNCTION__, __LINE__);
  6140.  
  6141.       if (appconn->s_state.authenticated == 1) {
  6142. #ifdef ENABLE_SESSIONSTATE
  6143.         appconn->s_state.session_state =
  6144.             RADIUS_VALUE_COOVACHILLI_SESSION_USER_LOGOUT_URL;
  6145. #endif
  6146.         terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_USER_REQUEST);
  6147.         appconn->s_params.sessiontimeout = 0;
  6148.         appconn->s_params.idletimeout = 0;
  6149.       }
  6150.  
  6151.       appconn->uamabort = 0;
  6152.       appconn->s_state.uamtime = mainclock.tv_sec;
  6153.  
  6154. #ifdef ENABLE_LAYER3
  6155.       if (!_options.layer3)
  6156. #endif
  6157.         dhcpconn->authstate = DHCP_AUTH_DNAT;
  6158.  
  6159.       break;
  6160.  
  6161.     case REDIR_ABORT:
  6162.  
  6163.       syslog(LOG_INFO, "Received UAM abort from IP=%s", inet_ntoa(appconn->hisip));
  6164.  
  6165.       appconn->uamabort = 1; /* Next login will be aborted */
  6166.       appconn->s_state.uamtime = 0;  /* Force generation of new challenge */
  6167.  
  6168. #ifdef ENABLE_LAYER3
  6169.       if (!_options.layer3)
  6170. #endif
  6171.         dhcpconn->authstate = DHCP_AUTH_DNAT;
  6172.  
  6173.       terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_USER_REQUEST);
  6174.  
  6175.       break;
  6176.  
  6177.     case REDIR_CHALLENGE:
  6178.       appconn->s_state.uamtime = mainclock.tv_sec;
  6179.       appconn->uamabort = 0;
  6180.       break;
  6181.  
  6182.     case REDIR_MACREAUTH:
  6183.       auth_radius(appconn, 0, 0, 0, 0);
  6184.       break;
  6185.  
  6186.     case REDIR_ALREADY:
  6187.     case REDIR_NOTYET:
  6188.       break;
  6189.   }
  6190.  
  6191.   return 0;
  6192. }
  6193.  
  6194. #if defined(ENABLE_CHILLIQUERY) || defined(ENABLE_CLUSTER)
  6195. static struct app_conn_t * find_app_conn(struct cmdsock_request *req,
  6196.                                          int *has_criteria) {
  6197.   struct app_conn_t *appconn = 0;
  6198.   struct dhcp_conn_t *dhcpconn = 0;
  6199.  
  6200.   if (req->ip.s_addr) {
  6201.     appconn = dhcp_get_appconn_ip(0, &req->ip);
  6202.     if (has_criteria)
  6203.       *has_criteria = 1;
  6204.   } else {
  6205. #ifdef ENABLE_LAYER3
  6206.     if (!_options.layer3)
  6207. #endif
  6208.       if (req->mac[0]||req->mac[1]||req->mac[2]||
  6209.       req->mac[3]||req->mac[4]||req->mac[5]) {
  6210.     dhcp_hashget(dhcp, &dhcpconn, req->mac);
  6211.     if (has_criteria)
  6212.       *has_criteria = 1;
  6213.       }
  6214.   }
  6215.  
  6216.   if (!appconn && dhcpconn
  6217. #ifdef ENABLE_LAYER3
  6218.       && !_options.layer3
  6219. #endif
  6220.       )
  6221.     appconn = (struct app_conn_t *) dhcpconn->peer;
  6222.  
  6223.   if (!appconn && req->d.sess.sessionid[0] != 0) {
  6224.     struct app_conn_t *aconn = firstusedconn;
  6225.     if (has_criteria)
  6226.       *has_criteria = 1;
  6227.     while (aconn) {
  6228.       if (!strcmp(aconn->s_state.sessionid, req->d.sess.sessionid)) {
  6229.     appconn = aconn;
  6230.     break;
  6231.       }
  6232.       aconn = aconn->next;
  6233.     }
  6234.   }
  6235.  
  6236.   if (appconn && !appconn->inuse) {
  6237.     if (_options.debug)
  6238.       syslog(LOG_DEBUG, "%s(%d): appconn not in use!", __FUNCTION__, __LINE__);
  6239.     return 0;
  6240.   }
  6241.  
  6242.   return appconn;
  6243. }
  6244.  
  6245. int chilli_cmd(struct cmdsock_request *req, bstring s, int sock) {
  6246.  
  6247. #ifdef HAVE_NETFILTER_COOVA
  6248.   if (_options.kname) {
  6249.     kmod_coova_sync();
  6250.   }
  6251. #endif
  6252.  
  6253.   switch(req->type) {
  6254.  
  6255. #ifdef ENABLE_INSPECT
  6256.     case CMDSOCK_INSPECT:
  6257.       {
  6258.         struct app_conn_t *appconn = 0;
  6259.         struct dhcp_conn_t *dhcpconn = 0;
  6260.         uint8_t z[PKT_ETH_ALEN];
  6261.         memset(z, 0, PKT_ETH_ALEN);
  6262.  
  6263.         if (_options.debug)
  6264.           syslog(LOG_DEBUG, "%s(%d): looking to inspect ip=%s/mac="MAC_FMT, __FUNCTION__, __LINE__,
  6265.                  inet_ntoa(req->ip), MAC_ARG(req->mac));
  6266.  
  6267.         if (req->ip.s_addr)
  6268.           appconn = dhcp_get_appconn_ip(0, &req->ip);
  6269.         else
  6270. #ifdef ENABLE_LAYER3
  6271.           if (!_options.layer3)
  6272. #endif
  6273.             dhcp_hashget(dhcp, &dhcpconn, req->mac);
  6274.  
  6275.         if (!appconn && !dhcpconn) {
  6276.  
  6277.           if (_options.debug)
  6278.             syslog(LOG_DEBUG, "%s(%d): not found", __FUNCTION__, __LINE__);
  6279.  
  6280.         } else {
  6281.  
  6282.           bstring tmp = bfromcstr("");
  6283.  
  6284.           uint32_t sessiontime = 0;
  6285.           uint32_t idletime = 0;
  6286.  
  6287.           char *down="down";
  6288.           char *up="up";
  6289.  
  6290.           char *in_label=down;
  6291.           char *out_label=up;
  6292.  
  6293.           if (!appconn)
  6294.             appconn = (struct app_conn_t *) dhcpconn->peer;
  6295.  
  6296.           if (!dhcpconn
  6297. #ifdef ENABLE_LAYER3
  6298.               && !_options.layer3
  6299. #endif
  6300.               )
  6301.             dhcpconn = (struct dhcp_conn_t *) appconn->dnlink;
  6302.  
  6303.           if (_options.swapoctets) {
  6304.             in_label=up;
  6305.             out_label=down;
  6306.           }
  6307.  
  6308.           if (appconn->s_state.authenticated) {
  6309.             sessiontime = mainclock_diffu(appconn->s_state.start_time);
  6310.             idletime    = mainclock_diffu(appconn->s_state.last_up_time);
  6311.           }
  6312.  
  6313.           bassignformat(tmp,
  6314.                         "MAC:   "MAC_FMT"   IP:  %s\n"
  6315.                         "---------------------------------------------------\n",
  6316.                         MAC_ARG(appconn->hismac),
  6317.                         inet_ntoa(appconn->hisip));
  6318.           bconcat(s, tmp);
  6319.  
  6320. #ifdef ENABLE_IEEE8021Q
  6321.           /* adding: vlan, if one */
  6322.           if (_options.ieee8021q && appconn->s_state.tag8021q) {
  6323.             bassignformat(tmp, "%20s: %d\n",
  6324.                           "vlan",
  6325.                           (int)ntohs(appconn->s_state.tag8021q &
  6326.                                      PKT_8021Q_MASK_VID));
  6327.             bconcat(s, tmp);
  6328.           } else {
  6329. #endif
  6330. #ifdef ENABLE_MULTILAN
  6331.             if (app_conn_idx(appconn)) {
  6332.               bassignformat(tmp,
  6333.                             "%20s: %s\n"
  6334.                             "%20s: %s\n",
  6335.                             "dhcpif",
  6336.                             _options.moreif[app_conn_idx(appconn)-1].dhcpif,
  6337.                             "vlan",
  6338.                             _options.moreif[app_conn_idx(appconn)-1].vlan ?
  6339.                             _options.moreif[app_conn_idx(appconn)-1].vlan :
  6340.                             _options.moreif[app_conn_idx(appconn)-1].dhcpif);
  6341.             } else {
  6342.               bassignformat(tmp,
  6343.                             "%20s: %s\n"
  6344.                             "%20s: %s\n",
  6345.                             "dhcpif",
  6346.                             _options.dhcpif,
  6347.                             "vlan",
  6348.                             _options.vlan);
  6349.             }
  6350.             bconcat(s, tmp);
  6351. #endif
  6352. #ifdef ENABLE_IEEE8021Q
  6353.           }
  6354. #endif
  6355.  
  6356.           bassignformat(tmp,
  6357.                         "%20s:%s authenticated\n",
  6358.                         "status",
  6359.                         appconn->s_state.authenticated ?
  6360.                         "" : " not");
  6361.           bconcat(s, tmp);
  6362.  
  6363.           {
  6364.             char buffer[128];
  6365.             redir_chartohex(appconn->s_state.redir.uamchal,
  6366.                             buffer, REDIR_MD5LEN);
  6367.             bassignformat(tmp,
  6368.                           "%20s: %s\n",
  6369.                           "challenge",
  6370.                           buffer);
  6371.             bconcat(s, tmp);
  6372.           }
  6373.  
  6374.           bassignformat(tmp,
  6375.                         "%20s: %.*s\n",
  6376.                         "session id",
  6377.                         appconn->s_state.sessionid[0] ?
  6378.                         strlen(appconn->s_state.sessionid) : 1,
  6379.                         appconn->s_state.sessionid[0] ?
  6380.                         appconn->s_state.sessionid : "-");
  6381.           bconcat(s, tmp);
  6382.  
  6383. #ifdef ENABLE_SESSIONID
  6384.           bassignformat(tmp,
  6385.                         "%20s: %s\n",
  6386.                         "chilli session id",
  6387.                         appconn->s_state.chilli_sessionid);
  6388.           bconcat(s, tmp);
  6389. #endif
  6390. #ifdef ENABLE_GARDENACCOUNTING
  6391.           if (appconn->s_state.garden_sessionid[0]) {
  6392.             bassignformat(tmp,
  6393.                           "%20s: %s\n",
  6394.                           "garden session id",
  6395.                           appconn->s_state.garden_sessionid);
  6396.             bconcat(s, tmp);
  6397.           }
  6398. #endif
  6399. #ifdef ENABLE_APSESSIONID
  6400.           if (appconn->s_state.ap_sessionid[0]) {
  6401.             bassignformat(tmp,
  6402.                           "%20s: %s\n",
  6403.                           "ap session id",
  6404.                           appconn->s_state.ap_sessionid);
  6405.             bconcat(s, tmp);
  6406.           }
  6407. #endif
  6408.  
  6409. #ifdef ENABLE_LOCATION
  6410.           if (appconn->s_state.location[0]) {
  6411.             bassignformat(tmp,
  6412.                           "%20s: %s\n",
  6413.                           "location",
  6414.                           appconn->s_state.location);
  6415.             bconcat(s, tmp);
  6416.           }
  6417.           if (appconn->s_state.pending_location[0]) {
  6418.             bassignformat(tmp,
  6419.                           "%20s: %s\n",
  6420.                           "pending location",
  6421.                           appconn->s_state.pending_location);
  6422.             bconcat(s, tmp);
  6423.           }
  6424.           if (appconn->s_state.location_changes) {
  6425.             bassignformat(tmp,
  6426.                           "%20s: %d\n",
  6427.                           "location changes",
  6428.                           appconn->s_state.location_changes);
  6429.             bconcat(s, tmp);
  6430.           }
  6431. #endif
  6432.  
  6433.           bassignformat(tmp,
  6434.                         "%20s: %.*s\n",
  6435.                         "user name",
  6436.                         appconn->s_state.redir.username[0] ?
  6437.                         strlen(appconn->s_state.redir.username) : 1,
  6438.                         appconn->s_state.redir.username[0] ?
  6439.                         appconn->s_state.redir.username : "-");
  6440.           bconcat(s, tmp);
  6441.  
  6442.           bassignformat(tmp,
  6443.                         "%20s: %d sec\n"
  6444.                         "%20s: %d sec\n"
  6445.                         "%20s: %d sec\n"
  6446.                         "%20s: %d sec\n",
  6447.                         "session time",
  6448.                         sessiontime,
  6449.                         "session timeout",
  6450.                         (int)appconn->s_params.sessiontimeout,
  6451.                         "idle time",
  6452.                         idletime,
  6453.                         "idle timeout",
  6454.                         (int)appconn->s_params.idletimeout);
  6455.           bconcat(s, tmp);
  6456.  
  6457.           bassignformat(tmp,
  6458.                         "%20s: in=%s, out=%s\n",
  6459.                         "octets in/out",
  6460.                         in_label, out_label);
  6461.           bconcat(s, tmp);
  6462.  
  6463.           if (appconn->s_params.maxtotaloctets) {
  6464.             bassignformat(tmp,
  6465.                           "%20s: %lld\n",
  6466.                           "max total octets",
  6467.                           appconn->s_params.maxtotaloctets);
  6468.             bconcat(s, tmp);
  6469.           }
  6470.  
  6471.           bassignformat(tmp,
  6472.                         "%20s: %lld\n",
  6473.                         "octets in",
  6474.                         appconn->s_state.input_octets);
  6475.           bconcat(s, tmp);
  6476.  
  6477.           if (appconn->s_params.maxinputoctets) {
  6478.             bassignformat(tmp,
  6479.                           "%20s: %lld\n",
  6480.                           "max octets in",
  6481.                           appconn->s_params.maxinputoctets);
  6482.             bconcat(s, tmp);
  6483.           }
  6484.  
  6485. #ifdef ENABLE_GARDENACCOUNTING
  6486.           if (_options.uamgardendata) {
  6487.             bassignformat(tmp,
  6488.                           "%20s: %lld\n",
  6489.                           "garden octets in",
  6490.                           appconn->s_state.garden_input_octets);
  6491.             bconcat(s, tmp);
  6492.             if (_options.uamotherdata) {
  6493.               bassignformat(tmp,
  6494.                             "%20s: %lld\n",
  6495.                             "other octets in",
  6496.                             appconn->s_state.other_input_octets);
  6497.               bconcat(s, tmp);
  6498.             }
  6499.           }
  6500. #endif
  6501.  
  6502.           bassignformat(tmp,
  6503.                         "%20s: %lld\n",
  6504.                         "octets out",
  6505.                         appconn->s_state.output_octets);
  6506.           bconcat(s, tmp);
  6507.  
  6508.           if (appconn->s_params.maxoutputoctets) {
  6509.             bassignformat(tmp,
  6510.                           "%20s: %lld\n",
  6511.                           "max octets out",
  6512.                           appconn->s_params.maxoutputoctets);
  6513.             bconcat(s, tmp);
  6514.           }
  6515.  
  6516. #ifdef ENABLE_GARDENACCOUNTING
  6517.           if (_options.uamgardendata) {
  6518.             bassignformat(tmp,
  6519.                           "%20s: %lld\n",
  6520.                           "garden octets out",
  6521.                           appconn->s_state.garden_output_octets);
  6522.             bconcat(s, tmp);
  6523.             if (_options.uamotherdata) {
  6524.               bassignformat(tmp,
  6525.                             "%20s: %lld\n",
  6526.                             "other octets out",
  6527.                             appconn->s_state.other_output_octets);
  6528.               bconcat(s, tmp);
  6529.             }
  6530.           }
  6531. #endif
  6532.  
  6533.           bassignformat(tmp,
  6534.                         "%20s: %lld (%d%%)\n"
  6535.                         "%20s: %lld (%d%%)\n",
  6536.                         "max b/w up",
  6537.                         appconn->s_params.bandwidthmaxup,
  6538.                         appconn->s_state.bucketupsize ?
  6539.                         (int) (appconn->s_state.bucketup * 100
  6540.                                / appconn->s_state.bucketupsize) : 0,
  6541.                         "max b/w down",
  6542.                         appconn->s_params.bandwidthmaxdown,
  6543.                         appconn->s_state.bucketdownsize ?
  6544.                         (int) (appconn->s_state.bucketdown * 100
  6545.                                / appconn->s_state.bucketdownsize) : 0);
  6546.           bconcat(s, tmp);
  6547.  
  6548.           bassignformat(tmp,
  6549.                         "%20s: %d sec ago\n",
  6550.                         "last sent time",
  6551.                         appconn->s_state.last_up_time ?
  6552.                         mainclock_now()-appconn->s_state.last_up_time:0);
  6553.           bconcat(s, tmp);
  6554.  
  6555.           if (dhcpconn) {
  6556.             bassignformat(tmp,
  6557.                           "%20s: %d sec ago\n",
  6558.                           "last seen",
  6559.                           dhcpconn->lasttime ?
  6560.                           mainclock_now()-dhcpconn->lasttime:0);
  6561.             bconcat(s, tmp);
  6562.           }
  6563.  
  6564.           bassignformat(tmp,
  6565.                         "%20s: %s\n",
  6566.                         "user url",
  6567.                         appconn->s_state.redir.userurl);
  6568.           bconcat(s, tmp);
  6569.  
  6570. #ifdef ENABLE_USERAGENT
  6571.           if (appconn->s_state.redir.useragent[0]) {
  6572.             bassignformat(tmp,
  6573.                           "%20s: %s\n",
  6574.                           "user agent",
  6575.                           appconn->s_state.redir.useragent);
  6576.             bconcat(s, tmp);
  6577.           }
  6578. #endif
  6579.  
  6580. #ifdef ENABLE_ACCEPTLANGUAGE
  6581.           if (appconn->s_state.redir.acceptlanguage[0]) {
  6582.             bassignformat(tmp,
  6583.                           "%20s: %s\n",
  6584.                           "accept language",
  6585.                           appconn->s_state.redir.acceptlanguage);
  6586.             bconcat(s, tmp);
  6587.           }
  6588. #endif
  6589.  
  6590.           bassignformat(tmp,
  6591.                         "%20s: %s\n",
  6592.                         "url param",
  6593.                         appconn->s_params.url);
  6594.           bconcat(s, tmp);
  6595.  
  6596.           bassignformat(tmp,
  6597.                         "%20s:",
  6598.                         "flags");
  6599.           if (appconn->s_params.flags & REQUIRE_UAM_AUTH)
  6600.             bcatcstr(tmp, " require-uam-auth");
  6601.           if (appconn->s_params.flags & REQUIRE_UAM_SPLASH)
  6602.             bcatcstr(tmp, " uam-splash");
  6603.           if (appconn->s_params.flags & REQUIRE_REDIRECT)
  6604.             bcatcstr(tmp, " require-redirect");
  6605.           if (appconn->s_params.flags & NO_ACCOUNTING)
  6606.             bcatcstr(tmp, " no-accounting");
  6607.           if (appconn->s_params.flags & NO_SCRIPT)
  6608.             bcatcstr(tmp, " no-script");
  6609.           if (appconn->s_params.flags & UAM_INJECT_URL)
  6610.             bcatcstr(tmp, " inject");
  6611.           if (appconn->s_params.flags & UAM_CLEAR_URL)
  6612.             bcatcstr(tmp, " clear-url");
  6613.           bcatcstr(tmp, "\n");
  6614.           bconcat(s, tmp);
  6615.  
  6616. #ifdef ENABLE_PROXYVSA
  6617.           bassignformat(tmp, "%20s: %d\n",
  6618.                         "vsa length",
  6619.                         (int)appconn->s_state.redir.vsalen);
  6620.           bconcat(s, tmp);
  6621. #endif
  6622.  
  6623. #ifdef ENABLE_SESSGARDEN
  6624.           if (appconn->s_params.pass_through_count > 0) {
  6625.             char mask[32];
  6626.             pass_through *pt;
  6627.             int i;
  6628.  
  6629.             bassignformat(tmp,
  6630.                           "%20s: %d\n",
  6631.                           "garden entries",
  6632.                           appconn->s_params.pass_through_count);
  6633.             bconcat(s, tmp);
  6634.  
  6635.             for (i = 0; i < appconn->s_params.pass_through_count; i++) {
  6636.               pt = &appconn->s_params.pass_throughs[i];
  6637.  
  6638.               strlcpy(mask, inet_ntoa(pt->mask), sizeof(mask));
  6639.  
  6640.               bassignformat(tmp,
  6641.                             "%20s: host=%-16s mask=%-16s proto=%-3d port=%-3d"
  6642. #ifdef ENABLE_GARDENEXT
  6643.                             " expiry=%-3d"
  6644. #endif
  6645.                             "\n", "",
  6646.                             inet_ntoa(pt->host), mask,
  6647.                             pt->proto, pt->port
  6648. #ifdef ENABLE_GARDENEXT
  6649.                             , pt->expiry ? pt->expiry - mainclock_now() : 0
  6650. #endif
  6651.                             );
  6652.               bconcat(s, tmp);
  6653.             }
  6654.           }
  6655. #endif
  6656.  
  6657.           bdestroy(tmp);
  6658.         }
  6659.       }
  6660.       break;
  6661. #endif
  6662.  
  6663.     case CMDSOCK_ADD_GARDEN:
  6664.     case CMDSOCK_REM_GARDEN:
  6665.       {
  6666.         char remove = (req->type == CMDSOCK_REM_GARDEN);
  6667. #ifdef ENABLE_SESSGARDEN
  6668.         uint8_t z[PKT_ETH_ALEN];
  6669.         memset(z, 0, PKT_ETH_ALEN);
  6670.  
  6671.         if (_options.debug)
  6672.           syslog(LOG_DEBUG, "%s(%d): looking to %s to garden ip=%s/sessionid=%s", __FUNCTION__, __LINE__,
  6673.                  remove ? "remove" : "add", inet_ntoa(req->ip), req->d.sess.sessionid);
  6674.  
  6675.         if (req->ip.s_addr || memcmp(req->mac, z, PKT_ETH_ALEN)) {
  6676.           struct app_conn_t *appconn = firstusedconn;
  6677.  
  6678.           while (appconn) {
  6679.             if (appconn->inuse &&
  6680.                 ( (req->ip.s_addr != 0 && appconn->hisip.s_addr == req->ip.s_addr) ||
  6681.                   (!memcmp(appconn->hismac, req->mac, PKT_ETH_ALEN))
  6682.                   ) ) {
  6683.  
  6684.               if (_options.debug)
  6685.                 syslog(LOG_DEBUG, "%s(%d): remote %s garden for session %s", __FUNCTION__, __LINE__,
  6686.                        remove ? "rem" : "add", appconn->s_state.sessionid);
  6687.  
  6688. #ifdef HAVE_PATRICIA
  6689.               if (appconn->ptree == NULL)
  6690.                 appconn->ptree = patricia_new (32);
  6691. #endif
  6692.  
  6693.               pass_throughs_from_string(appconn->s_params.pass_throughs,
  6694.                                         SESSION_PASS_THROUGH_MAX,
  6695.                                         &appconn->s_params.pass_through_count,
  6696.                                         req->d.data, 1, remove
  6697. #ifdef HAVE_PATRICIA
  6698.                                         , appconn->ptree
  6699. #endif
  6700.                                         );
  6701.               break;
  6702.             }
  6703.             appconn = appconn->next;
  6704.           }
  6705.         } else {
  6706. #endif
  6707.           pass_throughs_from_string(dhcp->pass_throughs,
  6708.                                     MAX_PASS_THROUGHS,
  6709.                                     &dhcp->num_pass_throughs,
  6710.                                     req->d.data, 1, remove
  6711. #ifdef HAVE_PATRICIA
  6712.                                     , dhcp->ptree_dyn
  6713. #endif
  6714.                                     );
  6715. #ifdef ENABLE_SESSGARDEN
  6716.         }
  6717. #endif
  6718.       }
  6719.       break;
  6720.  
  6721.     case CMDSOCK_LOGOUT:
  6722.       {
  6723.         struct app_conn_t *appconn = find_app_conn(req, 0);
  6724.  
  6725.         if (_options.debug)
  6726.           syslog(LOG_DEBUG, "%s(%d): looking to logout session %s", __FUNCTION__, __LINE__,
  6727.                  inet_ntoa(req->ip));
  6728.  
  6729.         if (appconn) {
  6730.           if (_options.debug)
  6731.             syslog(LOG_DEBUG, "%s(%d): found %s %s", __FUNCTION__, __LINE__,
  6732.                    inet_ntoa(appconn->hisip), appconn->s_state.sessionid);
  6733.  
  6734.           terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_ADMIN_RESET);
  6735.         }
  6736.       }
  6737.       break;
  6738.  
  6739.     case CMDSOCK_LIST_IPPOOL:
  6740.       ippool_print(sock, ippool);
  6741.       break;
  6742.  
  6743.     case CMDSOCK_LIST_GARDEN:
  6744.       garden_print(sock);
  6745.       break;
  6746.  
  6747.     case CMDSOCK_LIST_RADQUEUE:
  6748.       radius_printqueue(sock, radius);
  6749.       break;
  6750.  
  6751.     case CMDSOCK_LIST:
  6752.       {
  6753.         int listfmt = (req->options & CMDSOCK_OPT_JSON) ?
  6754.             LIST_JSON_FMT : LIST_LONG_FMT;
  6755.  
  6756.         struct app_conn_t *appconn=0;
  6757.         struct dhcp_conn_t *dhcpconn=0;
  6758.  
  6759.         int crt = 0;
  6760.  
  6761. #ifdef ENABLE_JSON
  6762.         if (listfmt == LIST_JSON_FMT) {
  6763.           bcatcstr(s, "{ \"sessions\":[");
  6764.         }
  6765. #endif
  6766.  
  6767.         appconn = find_app_conn(req, &crt);
  6768.         if (appconn) {
  6769. #ifdef ENABLE_LAYER3
  6770.           if (!_options.layer3)
  6771. #endif
  6772.             dhcpconn = (struct dhcp_conn_t *)appconn->dnlink;
  6773.  
  6774.           chilli_print(s, listfmt, appconn, dhcpconn);
  6775.  
  6776.         } else if (!crt) {
  6777. #ifdef ENABLE_LAYER3
  6778.           if (_options.layer3) {
  6779.             for (appconn = firstusedconn; appconn;
  6780.                  appconn = appconn->next) {
  6781.               chilli_print(s, listfmt, appconn, 0);
  6782.             }
  6783.           } else {
  6784. #endif
  6785.             if (dhcp) {
  6786.               dhcpconn = dhcp->firstusedconn;
  6787.               while (dhcpconn) {
  6788.                 chilli_print(s, listfmt, 0, dhcpconn);
  6789.                 dhcpconn = dhcpconn->next;
  6790.               }
  6791.             }
  6792. #ifdef ENABLE_LAYER3
  6793.           }
  6794. #endif
  6795.         }
  6796.  
  6797. #ifdef ENABLE_JSON
  6798.         if (listfmt == LIST_JSON_FMT) {
  6799.           bcatcstr(s, "]}");
  6800.         }
  6801. #endif
  6802.       }
  6803.       break;
  6804.  
  6805.     case CMDSOCK_DHCP_LIST:
  6806.       if (dhcp) {
  6807.         int listfmt = req->options & CMDSOCK_OPT_JSON ?
  6808.             LIST_JSON_FMT : LIST_SHORT_FMT;
  6809.  
  6810.         struct dhcp_conn_t *conn;
  6811.  
  6812. #ifdef ENABLE_JSON
  6813.         if (listfmt == LIST_JSON_FMT) {
  6814.           bcatcstr(s, "{ \"sessions\":[");
  6815.         }
  6816. #endif
  6817.         conn = dhcp->firstusedconn;
  6818.         while (conn) {
  6819.           chilli_print(s, listfmt, 0, conn);
  6820.           conn = conn->next;
  6821.         }
  6822. #ifdef ENABLE_JSON
  6823.         if (listfmt == LIST_JSON_FMT) {
  6824.           bcatcstr(s, "]}");
  6825.         }
  6826. #endif
  6827.       }
  6828.       break;
  6829.  
  6830.     case CMDSOCK_DHCP_DROP:
  6831.       if (dhcp)
  6832.         dhcp_block_mac(dhcp, req->mac);
  6833.       break;
  6834.  
  6835.     case CMDSOCK_DHCP_RELEASE:
  6836.       if (dhcp)
  6837.         dhcp_release_mac(dhcp, req->mac,
  6838.                          RADIUS_TERMINATE_CAUSE_ADMIN_RESET);
  6839.       break;
  6840.  
  6841. #ifdef ENABLE_MULTIROUTE
  6842.     case CMDSOCK_ROUTE_SET:
  6843.     case CMDSOCK_ROUTE_GW:
  6844.       {
  6845.         if (req->type == CMDSOCK_ROUTE_GW) {
  6846.           if (_options.debug)
  6847.             syslog(LOG_DEBUG, "%s(%d): setting route for idx %d", __FUNCTION__, __LINE__, req->d.sess.params.routeidx);
  6848.           copy_mac6(tun(tun, req->d.sess.params.routeidx).gwaddr, req->mac);
  6849.         } else {
  6850.           struct dhcp_conn_t *conn = dhcp->firstusedconn;
  6851.           if (_options.debug)
  6852.             syslog(LOG_DEBUG, "%s(%d): looking to alter session %s", __FUNCTION__, __LINE__, inet_ntoa(req->ip));
  6853.           while (conn && conn->inuse) {
  6854.             if (conn->peer) {
  6855.               struct app_conn_t * appconn = (struct app_conn_t*)conn->peer;
  6856.               if (!memcmp(appconn->hismac, req->mac, 6)) {
  6857.                 if (_options.debug)
  6858.                   syslog(LOG_DEBUG, "%s(%d): routeidx %s %d", __FUNCTION__, __LINE__,
  6859.                          appconn->s_state.sessionid,
  6860.                          req->d.sess.params.routeidx);
  6861.                 appconn->s_params.routeidx = req->d.sess.params.routeidx;
  6862.                 break;
  6863.               }
  6864.             }
  6865.             conn = conn->next;
  6866.           }
  6867.         }
  6868.       }
  6869.       /* drop through */
  6870.     case CMDSOCK_ROUTE:
  6871.       {
  6872.         int i;
  6873.         bstring b = bfromcstr("routes:\n");
  6874.         int err = 0;
  6875.         if (safe_write(sock, b->data, b->slen) == b->slen) {
  6876.           for (i=0; !err && i<tun->_interface_count; i++) {
  6877.             char gw[56];
  6878.  
  6879.             strlcpy(gw, inet_ntoa(tun->_interfaces[i].gateway), sizeof(gw));
  6880.  
  6881.             bassignformat(b, "idx: %d dev: %s %s "MAC_FMT" "
  6882.                           "%s "MAC_FMT"%s\n",
  6883.                           i, tun->_interfaces[i].devname,
  6884.                           inet_ntoa(tun->_interfaces[i].address),
  6885.                           MAC_ARG(tun->_interfaces[i].hwaddr),
  6886.                           gw,
  6887.                           MAC_ARG(tun->_interfaces[i].gwaddr),
  6888.                           i == 0 ? " (tun/tap)":"");
  6889.  
  6890.             if (safe_write(sock, b->data, b->slen) < 0)
  6891.               err = 1;
  6892.           }
  6893.  
  6894.           if (!err) {
  6895.             struct dhcp_conn_t *conn = dhcp->firstusedconn;
  6896.             bassignformat(b, "subscribers:\n");
  6897.             if (safe_write(sock, b->data, b->slen) == b->slen) {
  6898.               while (conn) {
  6899.                 struct app_conn_t *appconn = (struct app_conn_t *)conn->peer;
  6900.  
  6901.                 bassignformat(b, "mac: "MAC_FMT" -> idx: %d\n",
  6902.                               MAC_ARG(appconn->hismac),
  6903.                               appconn->s_params.routeidx);
  6904.  
  6905.                 if (safe_write(sock, b->data, b->slen) < 0)
  6906.                   break;
  6907.  
  6908.                 conn = conn->next;
  6909.               }
  6910.             }
  6911.           }
  6912.         }
  6913.         bdestroy(b);
  6914.       }
  6915.       rtmon_print_ifaces(&_rtmon, sock);
  6916.       rtmon_print_routes(&_rtmon, sock);
  6917.       break;
  6918. #endif
  6919.  
  6920.     case CMDSOCK_LOGIN:
  6921.     case CMDSOCK_UPDATE:
  6922.     case CMDSOCK_AUTHORIZE:
  6923.       if (dhcp) {
  6924.         struct app_conn_t *appconn = find_app_conn(req, 0);
  6925.         if (appconn) {
  6926.           char *uname = req->d.sess.username;
  6927.  
  6928.           if (_options.debug)
  6929.             syslog(LOG_DEBUG, "%s(%d): remotely authorized session %s", __FUNCTION__, __LINE__,
  6930.                    appconn->s_state.sessionid);
  6931.  
  6932.           memcpy(&appconn->s_params, &req->d.sess.params,
  6933.                  sizeof(req->d.sess.params));
  6934.  
  6935.           if (uname[0])
  6936.             strlcpy(appconn->s_state.redir.username,
  6937.                     uname, USERNAMESIZE);
  6938.  
  6939.           session_param_defaults(&appconn->s_params);
  6940.  
  6941. #ifdef ENABLE_LEAKYBUCKET
  6942.           leaky_bucket_init(appconn);
  6943. #endif
  6944.  
  6945.           switch(req->type) {
  6946.             case CMDSOCK_LOGIN:
  6947.               auth_radius(appconn, uname, req->d.sess.password, 0, 0);
  6948.               break;
  6949.             case CMDSOCK_AUTHORIZE:
  6950.               dnprot_accept(appconn);
  6951.               break;
  6952.             case CMDSOCK_UPDATE:
  6953.               break;
  6954.           }
  6955.         }
  6956.       }
  6957.       break;
  6958.  
  6959.  
  6960. #if defined(ENABLE_LOCATION) && defined(HAVE_AVL)
  6961.     case CMDSOCK_LISTLOC:
  6962.     case CMDSOCK_LISTLOCSUM:
  6963.       location_printlist(s, req->d.sess.location,
  6964.              (req->options & CMDSOCK_OPT_JSON),
  6965.              (req->type == CMDSOCK_LISTLOC));
  6966.       break;
  6967. #endif
  6968.  
  6969.     case CMDSOCK_RELOAD:
  6970.       _sigusr1(SIGUSR1);
  6971.       break;
  6972.  
  6973. #ifdef ENABLE_STATFILE
  6974.     case CMDSOCK_STATUSFILE:
  6975.       printstatus();
  6976.       break;
  6977. #endif
  6978.  
  6979. #ifdef ENABLE_CLUSTER
  6980.     case CMDSOCK_PEERS:
  6981.       print_peers(s);
  6982.       break;
  6983.  
  6984.     case CMDSOCK_PEER_SET:
  6985.       get_chilli_peer(-1)->state = PEER_STATE_ACTIVE;
  6986.       dhcp_peer_update(1);
  6987.       break;
  6988. #endif
  6989.  
  6990.     case CMDSOCK_PROCS:
  6991.       child_print(s);
  6992.       break;
  6993.  
  6994.     default:
  6995.       {
  6996.         char unknown = 1;
  6997. #ifdef ENABLE_MODULES
  6998.         int i;
  6999.         for (i=0; i < MAX_MODULES; i++) {
  7000.           if (!_options.modules[i].name[0]) break;
  7001.           if (_options.modules[i].ctx) {
  7002.             struct chilli_module *m =
  7003.                 (struct chilli_module *)_options.modules[i].ctx;
  7004.             if (m->cmdsock_handler) {
  7005.               switch (m->cmdsock_handler(req, s, sock)) {
  7006.                 case CHILLI_CMDSOCK_OK:
  7007.                   unknown = 0;
  7008.                   break;
  7009.               }
  7010.             }
  7011.           }
  7012.         }
  7013. #endif
  7014.         if (unknown) {
  7015.           syslog(LOG_ERR, "unknown cmdsock command");
  7016.           safe_close(sock);
  7017.           return -1;
  7018.         }
  7019.       }
  7020.   }
  7021.  
  7022.   return 0;
  7023. }
  7024. #endif
  7025.  
  7026. #ifdef ENABLE_CHILLIQUERY
  7027. static int cmdsock_accept(void *nullData, int sock) {
  7028.   struct sockaddr_un remote;
  7029.   struct cmdsock_request req;
  7030.  
  7031.   bstring s = 0;
  7032.   socklen_t len;
  7033.   int csock;
  7034.   int rval = 0;
  7035.  
  7036. #if(_debug_)
  7037.   if (_options.debug)
  7038.     syslog(LOG_DEBUG, "%s(%d): Processing cmdsock request...", __FUNCTION__, __LINE__);
  7039. #endif
  7040.  
  7041.   len = sizeof(remote);
  7042.   if ((csock = safe_accept(sock, (struct sockaddr *)&remote, &len)) == -1) {
  7043.     syslog(LOG_ERR, "%s: cmdsock_accept()/accept()", strerror(errno));
  7044.     return -1;
  7045.   }
  7046.  
  7047.   if (safe_read(csock, &req, sizeof(req)) != sizeof(req)) {
  7048.     syslog(LOG_ERR, "%s: cmdsock_accept()/read()", strerror(errno));
  7049.     safe_close(csock);
  7050.     return -1;
  7051.   }
  7052.  
  7053.   s = bfromcstr("");
  7054.   if (s == NULL) {
  7055.     syslog(LOG_ERR, "bfromstr(): memory allocation error");
  7056.     safe_close(csock);
  7057.     return -1;
  7058.   }
  7059.  
  7060.   rval = chilli_cmd(&req, s, csock);
  7061.  
  7062.   if (net_write(csock, s->data, s->slen) < 0)
  7063.     syslog(LOG_ERR, "%s: write()", strerror(errno));
  7064.  
  7065.   bdestroy(s);
  7066.   shutdown(csock, 2);
  7067.   safe_close(csock);
  7068.  
  7069.   return rval;
  7070. }
  7071. #endif
  7072.  
  7073. #if XXX_IO_DAEMON
  7074. int chilli_io(int fd_ctrl_r, int fd_ctrl_w, int fd_pkt_r, int fd_pkt_w) {
  7075.   int maxfd = 0;
  7076.   fd_set fds;
  7077.   int status;
  7078.  
  7079.   while (1) {
  7080.     fd_zero(&fds);
  7081.  
  7082.     fd_set(fd_ctrl_r, &fds);
  7083.     fd_set(fd_ctrl_w, &fds);
  7084.     fd_set(fd_pkt_r, &fds);
  7085.     fd_set(fd_pkt_w, &fds);
  7086.  
  7087.     if  ((status = select(maxfd + 1, &fds, NULL, NULL, NULL)) == -1) {
  7088.       if (EINTR != errno) {
  7089.     syslog(LOG_ERR, "select() returned -1!");
  7090.       }
  7091.     }
  7092.  
  7093.     if (status > 0) {
  7094.       if (fd_isset(fd_ctrl_r, &fds)) {
  7095.       }
  7096.       if (fd_isset(fd_ctrl_w, &fds)) {
  7097.       }
  7098.       if (fd_isset(fd_pkt_r, &fds)) {
  7099.       }
  7100.       if (fd_isset(fd_pkt_w, &fds)) {
  7101.       }
  7102.     } else {
  7103.       syslog(LOG_ERR, "%s: problem in select", strerror(errno));
  7104.       break;
  7105.     }
  7106.   }
  7107.  
  7108.   exit(1);
  7109. }
  7110. #endif
  7111.  
  7112. #ifdef USING_IPC_UNIX
  7113. int static redir_msg(struct redir_t *this) {
  7114.   struct redir_msg_t msg;
  7115.   struct sockaddr_un remote;
  7116.   socklen_t len = sizeof(remote);
  7117.   int socket = safe_accept(this->msgfd, (struct sockaddr *)&remote, &len);
  7118.   if (socket > 0) {
  7119.     int msgresult = safe_read(socket, &msg, sizeof(msg));
  7120.     if (msgresult == sizeof(msg)) {
  7121.       if (msg.mtype == REDIR_MSG_STATUS_TYPE) {
  7122.     struct redir_conn_t conn;
  7123.     memset(&conn, 0, sizeof(conn));
  7124.     if (cb_redir_getstate(redir,
  7125.                   &msg.mdata.address,
  7126.                   &msg.mdata.baddress,
  7127.                   &conn) != -1) {
  7128.       if (safe_write(socket, &conn, sizeof(conn)) < 0) {
  7129.         syslog(LOG_ERR, "%s: redir_msg writing", strerror(errno));
  7130.       }
  7131.     }
  7132.       } else {
  7133.     uam_msg(&msg);
  7134.       }
  7135.     } else if (msgresult == -1) {
  7136.       syslog(LOG_ERR, "%s: redir_msg read", strerror(errno));
  7137.     } else {
  7138.       syslog(LOG_ERR, "invalid size %d", msgresult);
  7139.     }
  7140.     safe_close(socket);
  7141.   }
  7142.   return 0;
  7143. }
  7144. #endif
  7145.  
  7146. #ifdef ENABLE_MULTIROUTE
  7147. int chilli_getconn_byroute(struct app_conn_t **conn, int idx) {
  7148.  
  7149.   struct app_conn_t *appconn = firstusedconn;
  7150.  
  7151.   while (appconn) {
  7152.  
  7153.     if (appconn->s_params.routeidx == idx) {
  7154.       *conn = appconn;
  7155.       return 0;
  7156.     }
  7157.  
  7158.     appconn = appconn->next;
  7159.   }
  7160.  
  7161.   return 1;
  7162. }
  7163.  
  7164. static int rtmon_proc_route(struct rtmon_t *rtmon,
  7165.                 struct rtmon_iface *iface,
  7166.                 struct rtmon_route *route) {
  7167.   int i;
  7168.   for (i=0; i < tun->_interface_count; i++) {
  7169.     if (tun->_interfaces[i].ifindex == route->if_index) {
  7170.       memcpy(tun->_interfaces[i].gwaddr, route->gwaddr, sizeof(tun->_interfaces[i].gwaddr));
  7171.       tun->_interfaces[i].gateway.s_addr = route->gateway.s_addr;
  7172.     }
  7173.   }
  7174.  
  7175.   return 0;
  7176. }
  7177.  
  7178. static int rtmon_accept(struct rtmon_t *rtmon, int idx) {
  7179.   if (rtmon_read_event(rtmon))
  7180.     syslog(LOG_ERR, "%s: error reading netlink message", strerror(errno));
  7181.   return 0;
  7182. }
  7183. #endif
  7184.  
  7185. static inline void macauth_reserved() {
  7186.   struct dhcp_conn_t *conn = dhcp->firstusedconn;
  7187.   struct app_conn_t *appconn;
  7188.  
  7189.   while (conn) {
  7190.     if (conn->is_reserved && conn->peer) {
  7191.       appconn = (struct app_conn_t *)conn->peer;
  7192.       if (!appconn->s_state.authenticated) {
  7193.     auth_radius((struct app_conn_t *)conn->peer, 0, 0, 0, 0);
  7194.       }
  7195.     }
  7196.     conn = conn->next;
  7197.   }
  7198. }
  7199.  
  7200. #ifdef ENABLE_LAYER3
  7201. static int session_timeout() {
  7202.   struct app_conn_t *conn = firstusedconn;
  7203.  
  7204.   while (conn) {
  7205.     struct app_conn_t *check_conn = conn;
  7206.     conn = conn->next;
  7207.     if (mainclock_diff(check_conn->s_state.last_up_time) >
  7208.     _options.lease + _options.leaseplus) {
  7209.       if (_options.debug)
  7210.         syslog(LOG_DEBUG, "%s(%d): Session timeout: Removing connection", __FUNCTION__, __LINE__);
  7211.       session_disconnect(check_conn, 0, RADIUS_TERMINATE_CAUSE_LOST_CARRIER);
  7212.     }
  7213.   }
  7214.  
  7215.   return 0;
  7216. }
  7217. #endif
  7218.  
  7219. int chilli_main(int argc, char **argv) {
  7220.   select_ctx sctx;
  7221.   int status;
  7222.  
  7223.   /*  struct itimerval itval; */
  7224.   int lastSecond = 0;
  7225.  
  7226. #ifdef ENABLE_CHILLIQUERY
  7227.   int cmdsock = -1;
  7228. #endif
  7229.  
  7230.   pid_t cpid = getpid();
  7231.  
  7232. #ifdef USING_IPC_MSG
  7233.   struct redir_msg_t msg;
  7234.   int msgresult;
  7235. #endif
  7236.  
  7237. #if XXX_IO_DAEMON
  7238.   pid_t chilli_fork = 0;
  7239.   int is_slave = 0;
  7240.  
  7241.   int ctrl_main_to_io[2];  /* 0/1 read/write - control messages from main -> io */
  7242.   int ctrl_io_to_main[2];  /* 0/1 read/write - control messages from io -> main */
  7243.   int pkt_main_to_io[2];
  7244.   int pkt_io_to_main[2];
  7245. #endif
  7246.  
  7247.   int i;
  7248.  
  7249.   int keep_going = 1;
  7250.   int reload_config = 0;
  7251.  
  7252.   int syslog_options = LOG_PID;
  7253.   int syslog_debug_options = 0;
  7254.   char *syslog_ident = NULL;
  7255.  
  7256. #ifdef LOG_PERROR
  7257.   syslog_debug_options = LOG_PERROR;
  7258. #endif
  7259.  
  7260.   syslog_ident = basename(argv[0]);
  7261.  
  7262.   /* Start out also logging to stderr until we load options. */
  7263.   openlog(syslog_ident, syslog_options|syslog_debug_options, LOG_DAEMON);
  7264.  
  7265.   options_init();
  7266.  
  7267.   /* Process options given in configuration file and command line */
  7268.   if (process_options(argc, argv, 0))
  7269.     exit(1);
  7270.  
  7271.   /* foreground                                                   */
  7272.   /* If flag not given run as a daemon                            */
  7273.   if (!_options.foreground) {
  7274.     FILE *fp = NULL;
  7275.     if (!(fp = freopen("/dev/null", "w", stdout))) {
  7276.       syslog(LOG_ERR, "freopen()");
  7277.     } else {
  7278.       fclose(fp);
  7279.       fp = NULL;
  7280.     }
  7281.     if (!(fp = freopen("/dev/null", "w", stderr))) {
  7282.       syslog(LOG_ERR, "freopen()");
  7283.     } else {
  7284.       fclose(fp);
  7285.       fp = NULL;
  7286.     }
  7287.     if (!(fp = freopen("/dev/null", "r", stdin))) {
  7288.       syslog(LOG_ERR, "freopen()");
  7289.     } else {
  7290.       fclose(fp);
  7291.       fp = NULL;
  7292.     }
  7293. #if defined (__FreeBSD__)  || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
  7294.     if (fork() > 0) {
  7295.       exit(0);
  7296. #else
  7297.       if (daemon(1, 1)) {
  7298.         syslog(LOG_ERR, "daemon() failed!");
  7299. #endif
  7300.       }
  7301.       else {
  7302.  
  7303.         /*
  7304.          *  We switched PID when we forked.
  7305.          *  To keep things nice and tity, lets move the
  7306.          *  binary configuration file to the new directory.
  7307.          *
  7308.          *  TODO: This process isn't ideal. But, the goal remains
  7309.          *  that we don't need cmdline.o in the running chilli. We may
  7310.          *  want to move away from gengetopt as it isn't exactly the most
  7311.          *  flexible or light-weight.
  7312.          */
  7313.  
  7314.         mode_t process_mask = umask(0077);
  7315.         char file[128];
  7316.         char file2[128];
  7317.         int ok;
  7318.  
  7319.         pid_t new_pid = getpid();
  7320.  
  7321.         bstring bt = bfromcstr("");
  7322.  
  7323.         /*
  7324.          * Format the filename of the current (cpid) and new binconfig files.
  7325.          */
  7326.         chilli_binconfig(file, sizeof(file), cpid);
  7327.         chilli_binconfig(file2, sizeof(file2), new_pid);
  7328.  
  7329.         /*
  7330.          * Reset the binconfig option and save current setttings.
  7331.          */
  7332.         _options.binconfig = file2;
  7333.         ok = options_save(file2, bt);
  7334.  
  7335.         if (!ok) {
  7336.           syslog(LOG_ERR, "%s: could not save configuration options! [%s]", strerror(errno), file2);
  7337.           exit(1);
  7338.         }
  7339.  
  7340.         /*
  7341.          * Reset binconfig (since file2 is a local variable)
  7342.          */
  7343.         _options.binconfig = 0;
  7344.         umask(process_mask);
  7345.  
  7346.         bdestroy(bt);
  7347.  
  7348.         if (!options_binload(file2)) {
  7349.           syslog(LOG_ERR, "%s: could not reload configuration! [%s]", strerror(errno), file2);
  7350.           exit(1);
  7351.         }
  7352.       }
  7353.     }
  7354.  
  7355. #ifdef LOG_NFACILITIES
  7356.     if (_options.logfacility < 0 || _options.logfacility > LOG_NFACILITIES)
  7357.       _options.logfacility= LOG_FAC(LOG_DAEMON);
  7358. #endif
  7359.  
  7360.     closelog();
  7361.  
  7362.     if (_options.debug)
  7363.       syslog_options |= syslog_debug_options;
  7364.     openlog(syslog_ident, syslog_options, (_options.logfacility<<3));
  7365.     if (!_options.debug)
  7366.       setlogmask(LOG_UPTO(_options.loglevel));
  7367.  
  7368.     chilli_signals(&keep_going, &reload_config);
  7369.  
  7370. #if XXX_IO_DAEMON
  7371.     pipe(ctrl_main_to_io);
  7372.     pipe(ctrl_io_to_main);
  7373.     pipe(pkt_main_to_io);
  7374.     pipe(pkt_io_to_main);
  7375.  
  7376.     chilli_fork = chilli_fork(CHILLI_PROC_DAEMON, "[chilli-io]");
  7377.     is_slave = chilli_fork > 0;
  7378.     if (chilli_fork < 0) perror("fork()");
  7379.     if (chilli_fork == 0)
  7380.       /* kick off io daemon */
  7381.       return chilli_io(ctrl_main_to_io[0],
  7382.                        ctrl_io_to_main[1],
  7383.                        pkt_main_to_io[0],
  7384.                        pkt_io_to_main[1]);
  7385. #endif
  7386.  
  7387.     chilli_pid = getpid();
  7388.  
  7389.     /* This has to be done after we have our final pid */
  7390.     log_pid((_options.pidfile && *_options.pidfile) ? _options.pidfile : DEFPIDFILE);
  7391.  
  7392. #ifdef ENABLE_UAMANYIP
  7393.     /* setup IPv4LL/APIPA network ip and mask for uamanyip exception */
  7394.     inet_aton("169.254.0.0", &ipv4ll_ip);
  7395.     inet_aton("255.255.0.0", &ipv4ll_mask);
  7396. #endif
  7397. #ifdef ENABLE_SSDP
  7398.     ssdp.s_addr = inet_addr(SSDP_MCAST_ADDR);
  7399. #endif
  7400.  
  7401.     syslog(LOG_INFO, "CoovaChilli %s. "
  7402.            "Copyright 2002-2005 Mondru AB. Licensed under GPL. "
  7403.            "Copyright 2006-2012 David Bird (Coova Technologies). "
  7404.            "Licensed under GPL. "
  7405.            "See http://coova.github.io/ for details.", VERSION);
  7406.  
  7407.     memset(&sctx, 0, sizeof(sctx));
  7408.  
  7409. #ifdef HAVE_LIBRT
  7410.     memset(&startup_real, 0, sizeof(startup_real));
  7411.     memset(&startup_mono, 0, sizeof(startup_mono));
  7412.     if (clock_gettime(CLOCK_REALTIME, &startup_real) < 0) {
  7413.       syslog(LOG_ERR, "%s: getting startup (realtime) time", strerror(errno));
  7414.     }
  7415.     if (_options.debug)
  7416.       syslog(LOG_DEBUG, "%s(%d): clock realtime sec %ld nsec %ld", __FUNCTION__, __LINE__, startup_real.tv_sec, startup_real.tv_nsec);
  7417. #ifdef CLOCK_MONOTONIC
  7418.     if (clock_gettime(CLOCK_MONOTONIC, &startup_mono) < 0) {
  7419.       syslog(LOG_ERR, "%s: getting startup (monotonic) time", strerror(errno));
  7420.     }
  7421.     if (_options.debug)
  7422.       syslog(LOG_DEBUG, "%s(%d): clock monotonic sec %ld nsec %ld", __FUNCTION__, __LINE__, startup_mono.tv_sec, startup_mono.tv_nsec);
  7423. #endif
  7424. #endif
  7425.  
  7426.     start_tick = mainclock_tick();
  7427.  
  7428.     /* Create a tunnel interface */
  7429.     if (tun_new(&tun)) {
  7430.       syslog(LOG_ERR, "Failed to create tun");
  7431.       exit(1);
  7432.     }
  7433.  
  7434.     tun_setaddr(tun,
  7435.                 &_options.uamlisten,
  7436.                 &_options.uamlisten,
  7437.                 &_options.mask);
  7438.  
  7439.     tun_set_cb_ind(tun, cb_tun_ind);
  7440.  
  7441.     if (_options.ipup)
  7442.       tun_runscript(tun, _options.ipup, 0);
  7443.  
  7444.     /* Allocate ippool for dynamic IP address allocation */
  7445.     if (ippool_new(&ippool,
  7446.                    _options.dynip,
  7447.                    _options.dhcpstart,
  7448.                    _options.dhcpend,
  7449.                    _options.statip,
  7450.                    _options.allowdyn,
  7451.                    _options.allowstat)) {
  7452.       syslog(LOG_ERR, "Failed to allocate IP pool!");
  7453.       exit(1);
  7454.     }
  7455.  
  7456.     /* Create an instance of dhcp */
  7457.     if (dhcp_new(&dhcp,
  7458.                  _options.max_clients,
  7459.                  _options.dhcphashsize,
  7460.                  _options.dhcpif,
  7461.                  _options.dhcpusemac,
  7462.                  _options.dhcpmac, 1,
  7463.                  &_options.dhcplisten, _options.lease, 1,
  7464.                  &_options.uamlisten, _options.uamport,
  7465.                  _options.noc2c)) {
  7466.       syslog(LOG_ERR, "Failed to create dhcp listener on %s", _options.dhcpif);
  7467.       exit(1);
  7468.     }
  7469.  
  7470.     dhcp_set_cb_request(dhcp, cb_dhcp_request);
  7471.     dhcp_set_cb_connect(dhcp, cb_dhcp_connect);
  7472.     dhcp_set_cb_disconnect(dhcp, cb_dhcp_disconnect);
  7473.     dhcp_set_cb_data_ind(dhcp, cb_dhcp_data_ind);
  7474. #ifdef ENABLE_EAPOL
  7475.     dhcp_set_cb_eap_ind(dhcp, cb_dhcp_eap_ind);
  7476. #endif
  7477.  
  7478.     if (dhcp_set(dhcp,
  7479.                  _options.ethers,
  7480.                  (_options.debug & DEBUG_DHCP))) {
  7481.       syslog(LOG_ERR, "Failed to set DHCP parameters");
  7482.       exit(1);
  7483.     }
  7484.  
  7485.     /* Create an instance of radius */
  7486.     if (radius_new(&radius,
  7487.                    &_options.radiuslisten,
  7488.                    _options.coaport,
  7489.                    _options.coanoipcheck, 1) ||
  7490.         radius_init_q(radius, _options.radiusqsize)) {
  7491.       syslog(LOG_ERR, "Failed to create radius");
  7492.       return -1;
  7493.     }
  7494.  
  7495.     radius_set(radius, dhcp ? dhcp->rawif[0].hwaddr : 0,
  7496.                (_options.debug & DEBUG_RADIUS));
  7497.  
  7498.     radius_set_cb_auth_conf(radius, cb_radius_auth_conf);
  7499. #ifdef ENABLE_COA
  7500.     radius_set_cb_coa_ind(radius, cb_radius_coa_ind);
  7501. #endif
  7502. #ifdef ENABLE_RADPROXY
  7503.     radius_set_cb_ind(radius, cb_radius_ind);
  7504. #endif
  7505.  
  7506.     if (_options.acct_update)
  7507.       radius_set_cb_acct_conf(radius, cb_radius_acct_conf);
  7508.  
  7509.     /* Initialise connections */
  7510.     initconn();
  7511.  
  7512.     /* Create an instance of redir */
  7513.     if (redir_new(&redir, &_options.uamlisten, _options.uamport,
  7514. #ifdef ENABLE_UAMUIPORT
  7515.                   _options.uamuiport
  7516. #else
  7517.                   0
  7518. #endif
  7519.                   )) {
  7520.       syslog(LOG_ERR, "Failed to create redir");
  7521.       return -1;
  7522.     }
  7523.  
  7524.     if (!_options.redir && redir_listen(redir)) {
  7525.       syslog(LOG_ERR, "Failed to create redir listen");
  7526.       return -1;
  7527.     }
  7528.  
  7529.     if (redir_ipc(redir)) {
  7530.       syslog(LOG_ERR, "Failed to create redir IPC");
  7531.       return -1;
  7532.     }
  7533.  
  7534.     redir_set(redir, dhcp->rawif[0].hwaddr, (_options.debug));
  7535.  
  7536.     /* not really needed for chilliredir */
  7537.     redir_set_cb_getstate(redir, cb_redir_getstate);
  7538.  
  7539. #ifdef ENABLE_CHILLIQUERY
  7540.     if (_options.cmdsocket) {
  7541.       cmdsock = cmdsock_init();
  7542.     } else {
  7543.       cmdsock = cmdsock_port_init();
  7544.     }
  7545.     if (cmdsock < 0) {
  7546.       syslog(LOG_ERR, "%s: Failed to initialize chilli query socket", strerror(errno));
  7547.       return -1;
  7548.     }
  7549. #endif
  7550.  
  7551.     if (_options.radsec) {
  7552. #ifdef ENABLE_CHILLIRADSEC
  7553.       launch_chilliradsec();
  7554. #else
  7555.       syslog(LOG_ERR, "Feature is not supported; use --enable-chilliradsec");
  7556.       _options.radsec = 0;
  7557. #endif
  7558.     } else if (_options.uamaaaurl) {
  7559. #ifdef ENABLE_CHILLIPROXY
  7560.       launch_chilliproxy();
  7561. #else
  7562.       syslog(LOG_ERR, "Feature is not supported; use --enable-chilliproxy");
  7563. #endif
  7564.     }
  7565.  
  7566.     if (_options.redir) {
  7567. #ifdef ENABLE_CHILLIREDIR
  7568.       launch_chilliredir();
  7569. #else
  7570.       syslog(LOG_ERR, "Feature is not supported; use --enable-chilliredir");
  7571.       _options.redir = 0;
  7572. #endif
  7573.     }
  7574.  
  7575. #if(_debug_)
  7576.     if (_options.debug)
  7577.       syslog(LOG_DEBUG, "%s(%d): Waiting for client request...", __FUNCTION__, __LINE__);
  7578. #endif
  7579.  
  7580.     /*
  7581.      * Administrative-User session
  7582.      */
  7583.     memset(&admin_session, 0, sizeof(admin_session));
  7584.  
  7585. #ifdef ENABLE_BINSTATFILE
  7586.     if (loadstatus() != 0) /* Only indicate a fresh start-up if we didn't load keepalive sessions */
  7587. #endif
  7588.     {
  7589. #ifdef ENABLE_ACCOUNTING_ONOFF
  7590.       acct_req(ACCT_USER, &admin_session, RADIUS_STATUS_TYPE_ACCOUNTING_ON);
  7591. #endif
  7592. #ifdef HAVE_NETFILTER_COOVA
  7593.       if (_options.kname) {
  7594.         kmod_coova_clear();
  7595.       }
  7596. #endif
  7597.     }
  7598.  
  7599.     if (_options.ethers && *_options.ethers && _options.macauth)
  7600.       macauth_reserved();
  7601.  
  7602.     if (_options.adminuser) {
  7603.       admin_session.is_adminsession = 1;
  7604.       strlcpy(admin_session.s_state.redir.username,
  7605.               _options.adminuser,
  7606.               sizeof(admin_session.s_state.redir.username));
  7607.       set_sessionid(&admin_session, 0);
  7608.       chilli_auth_radius(radius);
  7609.     }
  7610.  
  7611. #ifdef ENABLE_UAMDOMAINFILE
  7612.     garden_load_domainfile();
  7613. #endif
  7614.  
  7615. #ifdef HAVE_PATRICIA
  7616.     garden_patricia_reload();
  7617. #endif
  7618.  
  7619. #ifdef ENABLE_LOCATION
  7620.     location_init();
  7621. #endif
  7622.  
  7623.     /******************************************************************/
  7624.     /* Main select loop                                               */
  7625.     /******************************************************************/
  7626.  
  7627.     if (_options.gid && setgid(_options.gid)) {
  7628.       syslog(LOG_ERR, "%d setgid(%d) failed while running with gid = %d",
  7629.              errno, _options.gid, getgid());
  7630.     }
  7631.  
  7632.     if (_options.uid && setuid(_options.uid)) {
  7633.       syslog(LOG_ERR, "%d setuid(%d) failed while running with uid = %d",
  7634.              errno, _options.uid, getuid());
  7635.     }
  7636.  
  7637.     if (net_select_init(&sctx))
  7638.       syslog(LOG_ERR, "%s: select init", strerror(errno));
  7639.  
  7640. #ifdef ENABLE_MULTIROUTE
  7641.     tun->sctx = &sctx;
  7642.     for (i=0; i < tun->_interface_count; i++)
  7643.       net_select_reg(&sctx,
  7644.                      (tun)->_interfaces[i].fd,
  7645.                      SELECT_READ, (select_callback) tun_decaps,
  7646.                      tun, i);
  7647. #else
  7648.     net_select_reg(&sctx,
  7649.                    (tun)->_tuntap.fd,
  7650.                    SELECT_READ, (select_callback) tun_decaps,
  7651.                    tun, 0);
  7652. #endif
  7653.  
  7654.     net_select_reg(&sctx, selfpipe_init(),
  7655.                    SELECT_READ, (select_callback)chilli_handle_signal,
  7656.                    0, 0);
  7657.  
  7658.     net_select_reg(&sctx, radius->fd, SELECT_READ,
  7659.                    (select_callback)radius_decaps, radius, 0);
  7660.  
  7661. #ifdef ENABLE_RADPROXY
  7662.     if (radius->proxyfd)
  7663.       net_select_reg(&sctx, radius->proxyfd, SELECT_READ,
  7664.                      (select_callback)radius_proxy_ind, radius, 0);
  7665. #endif
  7666.  
  7667. #if defined(__linux__)
  7668.     net_select_reg(&sctx, dhcp->relayfd, SELECT_READ,
  7669.                    (select_callback)dhcp_relay_decaps, dhcp, 0);
  7670.  
  7671.     for (i=0; i < MAX_RAWIF && dhcp->rawif[i].fd > 0; i++) {
  7672.       net_select_reg(&sctx, dhcp->rawif[i].fd, SELECT_READ,
  7673.                      (select_callback)dhcp_decaps, dhcp, i);
  7674.  
  7675.       dhcp->rawif[i].sctx = &sctx;
  7676.     }
  7677.  
  7678. #ifdef HAVE_NETFILTER_QUEUE
  7679.     if (dhcp->qif_in.fd && dhcp->qif_out.fd) {
  7680.       net_select_reg(&sctx, dhcp->qif_in.fd, SELECT_READ,
  7681.                      (select_callback)dhcp_decaps, dhcp, 1);
  7682.  
  7683.       net_select_reg(&sctx, dhcp->qif_out.fd, SELECT_READ,
  7684.                      (select_callback)dhcp_decaps, dhcp, 2);
  7685.     }
  7686. #endif
  7687.  
  7688. #elif defined (__FreeBSD__)  || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
  7689.     for (i=0; i < MAX_RAWIF && dhcp->rawif[i].fd > 0; i++) {
  7690.       net_select_reg(&sctx, dhcp->rawif[i].fd, SELECT_READ,
  7691.                      (select_callback)dhcp_receive, dhcp, i);
  7692.     }
  7693. #endif
  7694.  
  7695. #ifdef USING_IPC_UNIX
  7696.     net_select_reg(&sctx, redir->msgfd, SELECT_READ,
  7697.                    (select_callback)redir_msg, redir, 0);
  7698. #endif
  7699.  
  7700.     if (!_options.redir) {
  7701.       net_select_reg(&sctx, redir->fd[0], SELECT_READ,
  7702.                      (select_callback)redir_accept, redir, 0);
  7703.       net_select_reg(&sctx, redir->fd[1], SELECT_READ,
  7704.                      (select_callback)redir_accept, redir, 1);
  7705.     }
  7706.  
  7707. #ifdef ENABLE_MULTIROUTE
  7708.     if (!rtmon_init(&_rtmon, rtmon_proc_route)) {
  7709.       net_select_reg(&sctx, _rtmon.fd, SELECT_READ,
  7710.                      (select_callback)rtmon_accept, &_rtmon, 0);
  7711.     }
  7712. #endif
  7713.  
  7714. #ifdef ENABLE_CHILLIQUERY
  7715.     net_select_reg(&sctx, cmdsock, SELECT_READ,
  7716.                    (select_callback)cmdsock_accept, 0, cmdsock);
  7717. #endif
  7718.  
  7719.     mainclock_tick();
  7720.     while (keep_going) {
  7721.  
  7722.       if (reload_config) {
  7723.  
  7724.         reload_options(argc, argv);
  7725.  
  7726.         reload_config = 0;
  7727.  
  7728.         /* Reinit DHCP parameters */
  7729.         if (dhcp) {
  7730.           dhcp_set(dhcp,
  7731.                    _options.ethers,
  7732.                    (_options.debug & DEBUG_DHCP));
  7733.         }
  7734.  
  7735.         /* Reinit RADIUS parameters */
  7736.         radius_set(radius, dhcp->rawif[0].hwaddr,
  7737.                    (_options.debug & DEBUG_RADIUS));
  7738.  
  7739.         /* Reinit Redir parameters */
  7740.         redir_set(redir, dhcp->rawif[0].hwaddr, _options.debug);
  7741.  
  7742. #ifdef HAVE_PATRICIA
  7743.         garden_patricia_reload();
  7744. #endif
  7745.  
  7746. #ifdef ENABLE_UAMDOMAINFILE
  7747.         garden_load_domainfile();
  7748. #endif
  7749.       }
  7750.  
  7751.       if (do_interval) {
  7752.         reprocess_options(argc, argv);
  7753.  
  7754.         do_interval = 0;
  7755.  
  7756.         if (_options.adminuser)
  7757.           chilli_auth_radius(radius);
  7758.       }
  7759.  
  7760.       if (lastSecond != mainclock.tv_sec) {
  7761.         /*
  7762.          *  Every second, more or less
  7763.          */
  7764.         radius_timeout(radius);
  7765.  
  7766.         if (dhcp)
  7767.           dhcp_timeout(dhcp);
  7768.  
  7769. #ifdef ENABLE_LAYER3
  7770.         if (_options.layer3)
  7771.           session_timeout();
  7772. #endif
  7773.  
  7774.         checkconn();
  7775.         lastSecond = mainclock.tv_sec;
  7776.  
  7777. #ifdef ENABLE_CLUSTER
  7778.         dhcp_peer_update(0);
  7779. #endif
  7780.       }
  7781.  
  7782.       if (net_select_prepare(&sctx))
  7783.         syslog(LOG_ERR, "%s: select prepare", strerror(errno));
  7784.  
  7785.       status = net_select(&sctx);
  7786.  
  7787.       mainclock_tick();
  7788.  
  7789. #ifdef USING_IPC_MSG
  7790.       if ((msgresult =
  7791.            TEMP_FAILURE_RETRY(msgrcv(redir->msgid, (void *)&msg, sizeof(msg.mdata), 0, IPC_NOWAIT)))  == -1) {
  7792.         if ((errno != EAGAIN) && (errno != ENOMSG))
  7793.           syslog(LOG_ERR, "%s: msgrcv() failed!", strerror(errno));
  7794.       }
  7795.  
  7796.       if (msgresult > 0)
  7797.         uam_msg(&msg);
  7798. #endif
  7799.  
  7800.       if (status > 0) {
  7801.  
  7802.         net_run_selected(&sctx, status);
  7803.  
  7804.       }
  7805.  
  7806. #ifdef USING_MMAP
  7807.  
  7808.       net_run(&dhcp->rawif[0]);
  7809.  
  7810. #ifdef ENABLE_MULTIROUTE
  7811.       if (tun) {
  7812.         for (i=0; i < (tun)->_interface_count; i++) {
  7813.           net_run(&(tun)->_interfaces[i]);
  7814.         }
  7815.       }
  7816. #endif
  7817.  
  7818. #endif
  7819.  
  7820.     } /* while(keep_going) */
  7821.  
  7822.     syslog(LOG_INFO, "CoovaChilli shutting down");
  7823.  
  7824.     if (_options.seskeepalive) {
  7825. #ifdef ENABLE_BINSTATFILE
  7826.       if (printstatus() != 0)
  7827.         syslog(LOG_ERR, "%s: could not save status file", strerror(errno));
  7828. #else
  7829.       syslog(LOG_WARNING, "Not stopping sessions! seskeepalive should be used with compile option --enable-binstatusfile");
  7830. #endif
  7831.     } else {
  7832.       killconn();
  7833. #ifdef ENABLE_STATFILE
  7834.       if (printstatus() != 0)
  7835.         syslog(LOG_ERR, "%s: could not save status file", strerror(errno));
  7836. #endif
  7837.     }
  7838.  
  7839.     child_killall(SIGTERM);
  7840.  
  7841.     if (_options.ipdown)
  7842.       tun_runscript(tun, _options.ipdown, 1);
  7843.  
  7844.     if (redir)
  7845.       redir_free(redir);
  7846.  
  7847.     if (radius)
  7848.       radius_free(radius);
  7849.  
  7850.     if (dhcp)
  7851.       dhcp_free(dhcp);
  7852.  
  7853.     if (tun)
  7854.       tun_free(tun);
  7855.  
  7856.     if (ippool)
  7857.       ippool_free(ippool);
  7858.  
  7859.     /*
  7860.      *  Terminate not-so-nicely
  7861.      */
  7862.  
  7863. #ifdef ENABLE_CHILLIQUERY
  7864.     cmdsock_shutdown();
  7865. #endif
  7866.  
  7867. #ifdef ENABLE_CHILLIREDIR
  7868.     if (redir_pid > 0) {
  7869.       kill(redir_pid, SIGTERM);
  7870.     }
  7871. #endif
  7872. #ifdef ENABLE_CHILLIPROXY
  7873.     if (proxy_pid > 0) {
  7874.       kill(proxy_pid, SIGTERM);
  7875.     }
  7876. #endif
  7877. #ifdef ENABLE_CHILLIRADSEC
  7878.     if (radsec_pid > 0) {
  7879.       kill(radsec_pid, SIGTERM);
  7880.     }
  7881. #endif
  7882.  
  7883. #ifdef ENABLE_UAMDOMAINFILE
  7884.     garden_free_domainfile();
  7885. #endif
  7886.  
  7887.     selfpipe_finish();
  7888.  
  7889.     /* child_killall(SIGKILL);*/
  7890.  
  7891.     options_cleanup();
  7892.  
  7893.     return 0;
  7894.   }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement