Annotation of embedaddon/coova-chilli/src/chilli.c, revision 1.1.1.1

1.1       misho       1: /* 
                      2:  *
                      3:  * chilli - ChilliSpot.org. A Wireless LAN Access Point Controller.
                      4:  * Copyright (C) 2003, 2004, 2005 Mondru AB.
                      5:  * Copyright (C) 2006 PicoPoint B.V.
                      6:  * Copyright (c) 2007-2008 David Bird <david@coova.com>
                      7:  *
                      8:  * The contents of this file may be used under the terms of the GNU
                      9:  * General Public License Version 2, provided that the above copyright
                     10:  * notice and this permission notice is included in all copies or
                     11:  * substantial portions of the software.
                     12:  * 
                     13:  */
                     14: 
                     15: #include "system.h"
                     16: #include "tun.h"
                     17: #include "ippool.h"
                     18: #include "radius.h"
                     19: #include "radius_wispr.h"
                     20: #include "radius_chillispot.h"
                     21: #include "redir.h"
                     22: #include "syserr.h"
                     23: #include "dhcp.h"
                     24: #include "cmdline.h"
                     25: #include "chilli.h"
                     26: #include "options.h"
                     27: #include "cmdsock.h"
                     28: #include "net.h"
                     29: 
                     30: struct tun_t *tun;                /* TUN instance            */
                     31: struct ippool_t *ippool;          /* Pool of IP addresses */
                     32: struct radius_t *radius;          /* Radius client instance */
                     33: struct dhcp_t *dhcp = NULL;       /* DHCP instance */
                     34: struct redir_t *redir = NULL;     /* Redir instance */
                     35: 
                     36: int connections=0;
                     37: struct app_conn_t *firstfreeconn=0; /* First free in linked list */
                     38: struct app_conn_t *lastfreeconn=0;  /* Last free in linked list */
                     39: struct app_conn_t *firstusedconn=0; /* First used in linked list */
                     40: struct app_conn_t *lastusedconn=0;  /* Last used in linked list */
                     41: 
                     42: extern struct app_conn_t admin_session;
                     43: 
                     44: time_t mainclock;
                     45: time_t checktime;
                     46: time_t rereadtime;
                     47: 
                     48: static int keep_going = 1;
                     49: /*static int do_timeouts = 1;*/
                     50: static int do_sighup = 0;
                     51: 
                     52: /* some IPv4LL/APIPA(rfc 3927) specific stuff for uamanyip */
                     53: struct in_addr ipv4ll_ip;
                     54: struct in_addr ipv4ll_mask;
                     55: 
                     56: /* Forward declarations */
                     57: static int acct_req(struct app_conn_t *conn, uint8_t status_type);
                     58: 
                     59: /* Fireman catches falling childs and eliminates zombies */
                     60: static void fireman(int signum) { 
                     61:   while (wait3(NULL, WNOHANG, NULL) > 0);
                     62: }
                     63: 
                     64: /* Termination handler for clean shutdown */
                     65: static void termination_handler(int signum) {
                     66:   if (options.debug) log_dbg("SIGTERM received!\n");
                     67:   keep_going = 0;
                     68: }
                     69: 
                     70: /* Alarm handler for general house keeping 
                     71: void static alarm_handler(int signum) {
                     72:   if (options.debug) log_dbg("SIGALRM received!\n");
                     73:   do_timeouts = 1;
                     74: }*/
                     75: 
                     76: /* Sighup handler for rereading configuration file */
                     77: static void sighup_handler(int signum) {
                     78:   if (options.debug) log_dbg("SIGHUP received!\n");
                     79:   do_sighup = 1;
                     80: }
                     81: 
                     82: 
                     83: static void set_sessionid(struct app_conn_t *appconn) {
                     84:   snprintf(appconn->s_state.sessionid, sizeof(appconn->s_state.sessionid), 
                     85:           "%.8x%.8x", (int) mainclock, appconn->unit);
                     86:   /*log_dbg("!!!! RESET CLASSLEN !!!!");*/
                     87:   appconn->s_state.redir.classlen = 0;
                     88: }
                     89: 
                     90: /* Used to write process ID to file. Assume someone else will delete */
                     91: void static log_pid(char *pidfile) {
                     92:   FILE *file;
                     93:   mode_t oldmask;
                     94: 
                     95:   oldmask = umask(022);
                     96:   file = fopen(pidfile, "w");
                     97:   umask(oldmask);
                     98:   if(!file) return;
                     99:   fprintf(file, "%d\n", getpid());
                    100:   fclose(file);
                    101: }
                    102: 
                    103: #ifdef LEAKY_BUCKET
                    104: /* Perform leaky bucket on up- and downlink traffic */
                    105: int static leaky_bucket(struct app_conn_t *conn, uint64_t octetsup, uint64_t octetsdown) {
                    106:   
                    107:   time_t timenow = mainclock;
                    108:   uint64_t timediff; 
                    109:   int result = 0;
                    110: 
                    111:   timediff = timenow - conn->s_state.last_time;
                    112: 
                    113:   if (options.debug && (conn->s_params.bandwidthmaxup || 
                    114:                        conn->s_params.bandwidthmaxdown))
                    115:     log_dbg("Leaky bucket timediff: %lld, bucketup: %lld, bucketdown: %lld, up: %lld, down: %lld", 
                    116:            timediff, conn->s_state.bucketup, conn->s_state.bucketdown, 
                    117:            octetsup, octetsdown);
                    118: 
                    119:   if (conn->s_params.bandwidthmaxup) {
                    120:     /* Subtract what the leak since last time we visited */
                    121:     if (conn->s_state.bucketup > ((timediff * conn->s_params.bandwidthmaxup) / 8)) {
                    122:       conn->s_state.bucketup -= (timediff * conn->s_params.bandwidthmaxup) / 8;
                    123:     }
                    124:     else {
                    125:       conn->s_state.bucketup = 0;
                    126:     }
                    127:     
                    128:     if ((conn->s_state.bucketup + octetsup) > conn->s_state.bucketupsize) {
                    129:       if (options.debug) log_dbg("Leaky bucket deleting uplink packet");
                    130:       result = -1;
                    131:     }
                    132:     else {
                    133:       conn->s_state.bucketup += octetsup;
                    134:     }
                    135:   }
                    136: 
                    137:   if (conn->s_params.bandwidthmaxdown) {
                    138:     if (conn->s_state.bucketdown > ((timediff * conn->s_params.bandwidthmaxdown) / 8)) {
                    139:       conn->s_state.bucketdown -= (timediff * conn->s_params.bandwidthmaxdown) / 8;
                    140:     }
                    141:     else {
                    142:       conn->s_state.bucketdown = 0;
                    143:     }
                    144:     
                    145:     if ((conn->s_state.bucketdown + octetsdown) > conn->s_state.bucketdownsize) {
                    146:       if (options.debug) log_dbg("Leaky bucket deleting downlink packet");
                    147:       result = -1;
                    148:     }
                    149:     else {
                    150:       conn->s_state.bucketdown += octetsdown;
                    151:     }
                    152:   }
                    153: 
                    154:   conn->s_state.last_time = timenow;
                    155:     
                    156:   return result;
                    157: }
                    158: #endif
                    159: 
                    160: 
                    161: /* Run external script */
                    162: #define VAL_STRING   0
                    163: #define VAL_IN_ADDR  1
                    164: #define VAL_MAC_ADDR 2
                    165: #define VAL_ULONG    3
                    166: #define VAL_ULONG64  4
                    167: #define VAL_USHORT   5
                    168: 
                    169: int set_env(char *name, char type, void *value, int len) {
                    170:   char *v=0;
                    171:   char s[1024];
                    172: 
                    173:   memset(s,0,sizeof(s));
                    174: 
                    175:   switch(type) {
                    176: 
                    177:   case VAL_IN_ADDR:
                    178:     strncpy(s, inet_ntoa(*(struct in_addr *)value), sizeof(s)); 
                    179:     v = s;
                    180:     break;
                    181: 
                    182:   case VAL_MAC_ADDR:
                    183:     {
                    184:       uint8_t * mac = (uint8_t*)value;
                    185:       snprintf(s, sizeof(s)-1, "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",
                    186:               mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
                    187:       v = s;
                    188:     }
                    189:     break;
                    190: 
                    191:   case VAL_ULONG:
                    192:     snprintf(s, sizeof(s)-1, "%ld", (long int)*(uint32_t *)value);
                    193:     v = s;
                    194:     break;
                    195: 
                    196:   case VAL_ULONG64:
                    197:     snprintf(s, sizeof(s)-1, "%ld", (long int)*(uint64_t *)value);
                    198:     v = s;
                    199:     break;
                    200: 
                    201:   case VAL_USHORT:
                    202:     snprintf(s, sizeof(s)-1, "%d", (int)(*(uint16_t *)value));
                    203:     v = s;
                    204:     break;
                    205: 
                    206:   case VAL_STRING:
                    207:     if (len != 0) {
                    208:       if (len >= sizeof(s)) {
                    209:        return -1;
                    210:       }
                    211:       strncpy(s, (char*)value, len);
                    212:       s[len] = 0;
                    213:       v = s;
                    214:     } else {
                    215:       v = (char*)value;
                    216:     }
                    217:     break;
                    218:   }
                    219: 
                    220:   if (name != NULL && v != NULL) {
                    221:     if (setenv(name, v, 1) != 0) {
                    222:       log_err(errno, "setenv(%s, %s, 1) did not return 0!", name, v);
                    223:       return -1;
                    224:     }
                    225:   }
                    226: 
                    227:   return 0;
                    228: }
                    229: 
                    230: int runscript(struct app_conn_t *appconn, char* script) {  
                    231:   int status;
                    232: 
                    233:   if ((status = fork()) < 0) {
                    234:     log_err(errno,
                    235:            "fork() returned -1!");
                    236:     return 0;
                    237:   }
                    238: 
                    239:   if (status > 0) { /* Parent */
                    240:     return 0; 
                    241:   }
                    242: 
                    243: /*
                    244:   if (clearenv() != 0) {
                    245:     log_err(errno,
                    246:            "clearenv() did not return 0!");
                    247:     exit(0);
                    248:   }
                    249: */
                    250: 
                    251:   set_env("DEV", VAL_STRING, tun->_interfaces[0].devname, 0);
                    252:   set_env("NET", VAL_IN_ADDR, &appconn->net, 0);
                    253:   set_env("MASK", VAL_IN_ADDR, &appconn->mask, 0);
                    254:   set_env("ADDR", VAL_IN_ADDR, &appconn->ourip, 0);
                    255:   set_env("USER_NAME", VAL_STRING, appconn->s_state.redir.username, 0);
                    256:   set_env("NAS_IP_ADDRESS", VAL_IN_ADDR,&options.radiuslisten, 0);
                    257:   set_env("SERVICE_TYPE", VAL_STRING, "1", 0);
                    258:   set_env("FRAMED_IP_ADDRESS", VAL_IN_ADDR, &appconn->hisip, 0);
                    259:   set_env("FILTER_ID", VAL_STRING, appconn->s_params.filteridbuf, 0);
                    260:   set_env("STATE", VAL_STRING, appconn->s_state.redir.statebuf, appconn->s_state.redir.statelen);
                    261:   set_env("CLASS", VAL_STRING, appconn->s_state.redir.classbuf, appconn->s_state.redir.classlen);
                    262:   set_env("SESSION_TIMEOUT", VAL_ULONG64, &appconn->s_params.sessiontimeout, 0);
                    263:   set_env("IDLE_TIMEOUT", VAL_ULONG, &appconn->s_params.idletimeout, 0);
                    264:   set_env("CALLING_STATION_ID", VAL_MAC_ADDR, appconn->hismac, 0);
                    265:   set_env("CALLED_STATION_ID", VAL_MAC_ADDR, appconn->ourmac, 0);
                    266:   set_env("NAS_ID", VAL_STRING, options.radiusnasid, 0);
                    267:   set_env("NAS_PORT_TYPE", VAL_STRING, "19", 0);
                    268:   set_env("ACCT_SESSION_ID", VAL_STRING, appconn->s_state.sessionid, 0);
                    269:   set_env("ACCT_INTERIM_INTERVAL", VAL_USHORT, &appconn->s_params.interim_interval, 0);
                    270:   set_env("WISPR_LOCATION_ID", VAL_STRING, options.radiuslocationid, 0);
                    271:   set_env("WISPR_LOCATION_NAME", VAL_STRING, options.radiuslocationname, 0);
                    272:   set_env("WISPR_BANDWIDTH_MAX_UP", VAL_ULONG, &appconn->s_params.bandwidthmaxup, 0);
                    273:   set_env("WISPR_BANDWIDTH_MAX_DOWN", VAL_ULONG, &appconn->s_params.bandwidthmaxdown, 0);
                    274:   /*set_env("WISPR-SESSION_TERMINATE_TIME", VAL_USHORT, &appconn->sessionterminatetime, 0);*/
                    275:   set_env("CHILLISPOT_MAX_INPUT_OCTETS", VAL_ULONG64, &appconn->s_params.maxinputoctets, 0);
                    276:   set_env("CHILLISPOT_MAX_OUTPUT_OCTETS", VAL_ULONG64, &appconn->s_params.maxoutputoctets, 0);
                    277:   set_env("CHILLISPOT_MAX_TOTAL_OCTETS", VAL_ULONG64, &appconn->s_params.maxtotaloctets, 0);
                    278: 
                    279:   if (execl(script, script, (char *) 0) != 0) {
                    280:       log_err(errno,
                    281:              "execl() did not return 0!");
                    282:       exit(0);
                    283:   }
                    284: 
                    285:   exit(0);
                    286: }
                    287: 
                    288: /***********************************************************
                    289:  *
                    290:  * Functions handling uplink protocol authentication.
                    291:  * Called in response to radius access request response.
                    292:  *
                    293:  ***********************************************************/
                    294: 
                    295: static int newip(struct ippoolm_t **ipm, struct in_addr *hisip) {
                    296:   if (ippool_newip(ippool, ipm, hisip, 1)) {
                    297:     if (ippool_newip(ippool, ipm, hisip, 0)) {
                    298:       log_err(0, "Failed to allocate either static or dynamic IP address");
                    299:       return -1;
                    300:     }
                    301:   }
                    302:   return 0;
                    303: }
                    304: 
                    305: 
                    306: /* 
                    307:  * A few functions to manage connections 
                    308:  */
                    309: 
                    310: int static initconn()
                    311: {
                    312:   checktime = rereadtime = mainclock;
                    313:   return 0;
                    314: }
                    315: 
                    316: int static newconn(struct app_conn_t **conn) {
                    317:   int n;
                    318: 
                    319:   if (!firstfreeconn) {
                    320: 
                    321:     if (connections == APP_NUM_CONN) {
                    322:       log_err(0, "reached max connections!");
                    323:       return -1;
                    324:     }
                    325: 
                    326:     n = ++connections;
                    327: 
                    328:     if (!(*conn = calloc(1, sizeof(struct app_conn_t)))) {
                    329:       log_err(0, "Out of memory!");
                    330:       return -1;
                    331:     }
                    332: 
                    333:   } else {
                    334: 
                    335:     *conn = firstfreeconn;
                    336:     n = (*conn)->unit;
                    337: 
                    338:     /* Remove from link of free */
                    339:     if (firstfreeconn->next) {
                    340:       firstfreeconn->next->prev = NULL;
                    341:       firstfreeconn = firstfreeconn->next;
                    342:     }
                    343:     else { /* Took the last one */
                    344:       firstfreeconn = NULL; 
                    345:       lastfreeconn = NULL;
                    346:     }
                    347: 
                    348:     /* Initialise structures */
                    349:     memset(*conn, 0, sizeof(struct app_conn_t));
                    350:   }
                    351: 
                    352:   /* Insert into link of used */
                    353:   if (firstusedconn) {
                    354:     firstusedconn->prev = *conn;
                    355:     (*conn)->next = firstusedconn;
                    356:   }
                    357:   else { /* First insert */
                    358:     lastusedconn = *conn;
                    359:   }
                    360:   
                    361:   firstusedconn = *conn;
                    362:   
                    363:   (*conn)->inuse = 1;
                    364:   (*conn)->unit = n;
                    365:   
                    366:   return 0; /* Success */
                    367: }
                    368: 
                    369: int static freeconn(struct app_conn_t *conn) {
                    370:   int n = conn->unit;
                    371: 
                    372:   /* Remove from link of used */
                    373:   if ((conn->next) && (conn->prev)) {
                    374:     conn->next->prev = conn->prev;
                    375:     conn->prev->next = conn->next;
                    376:   }
                    377:   else if (conn->next) { /* && prev == 0 */
                    378:     conn->next->prev = NULL;
                    379:     firstusedconn = conn->next;
                    380:   }
                    381:   else if (conn->prev) { /* && next == 0 */
                    382:     conn->prev->next = NULL;
                    383:     lastusedconn = conn->prev;
                    384:   }
                    385:   else { /* if ((next == 0) && (prev == 0)) */
                    386:     firstusedconn = NULL;
                    387:     lastusedconn = NULL;
                    388:   }
                    389:   
                    390:   /* Initialise structures */
                    391:   memset(conn, 0, sizeof(struct app_conn_t));
                    392:   conn->unit = n;
                    393:   
                    394:   /* Insert into link of free */
                    395:   if (firstfreeconn) {
                    396:     firstfreeconn->prev = conn;
                    397:   }
                    398:   else { /* First insert */
                    399:     lastfreeconn = conn;
                    400:   }
                    401: 
                    402:   conn->next = firstfreeconn;
                    403:   firstfreeconn = conn;
                    404: 
                    405:   return 0;
                    406: }
                    407: 
                    408: int static getconn(struct app_conn_t **conn, uint32_t nasip, uint32_t nasport) {
                    409:   struct app_conn_t *appconn;
                    410:   
                    411:   /* Count the number of used connections */
                    412:   appconn = firstusedconn;
                    413:   while (appconn) {
                    414:     if (!appconn->inuse) {
                    415:       log_err(0, "Connection with inuse == 0!");
                    416:     }
                    417:     if ((appconn->nasip == nasip) && (appconn->nasport == nasport)) {
                    418:       *conn = appconn;
                    419:       return 0;
                    420:     }
                    421:     appconn = appconn->next;
                    422:   }
                    423: 
                    424:   return -1; /* Not found */
                    425: }
                    426: 
                    427: int static dnprot_terminate(struct app_conn_t *appconn) {
                    428:   appconn->s_state.authenticated = 0;
                    429:   printstatus(appconn);
                    430:   switch (appconn->dnprot) {
                    431:   case DNPROT_WPA:
                    432:   case DNPROT_EAPOL:
                    433:     if (appconn->dnlink)
                    434:       ((struct dhcp_conn_t*) appconn->dnlink)->authstate = DHCP_AUTH_NONE;
                    435:     return 0;
                    436:   case DNPROT_MAC:
                    437:   case DNPROT_UAM:
                    438:   case DNPROT_DHCP_NONE:
                    439:   case DNPROT_NULL:
                    440:     if (appconn->dnlink)
                    441:       ((struct dhcp_conn_t*) appconn->dnlink)->authstate = DHCP_AUTH_DNAT;
                    442:     return 0;
                    443:   default: 
                    444:     log_err(0, "Unknown downlink protocol"); 
                    445:     return 0;
                    446:   }
                    447: }
                    448: 
                    449: 
                    450: 
                    451: /* Check for:
                    452:  * - Session-Timeout
                    453:  * - Idle-Timeout
                    454:  * - Interim-Interim accounting
                    455:  * - Reread configuration file and DNS entries
                    456:  */
                    457: 
                    458: void session_interval(struct app_conn_t *conn) {
                    459:   time_t timenow = mainclock;
                    460:   uint32_t sessiontime;
                    461:   uint32_t idletime;
                    462:   uint32_t interimtime;
                    463: 
                    464:   sessiontime = timenow - conn->s_state.start_time;
                    465:   idletime    = timenow - conn->s_state.last_time;
                    466:   interimtime = timenow - conn->s_state.interim_time;
                    467:   
                    468:   if ((conn->s_params.sessiontimeout) &&
                    469:       (sessiontime > conn->s_params.sessiontimeout)) {
                    470:     terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
                    471:   }
                    472:   else if ((conn->s_params.sessionterminatetime) && 
                    473:           (timenow > conn->s_params.sessionterminatetime)) {
                    474:     terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
                    475:   }
                    476:   else if ((conn->s_params.idletimeout) && 
                    477:           (idletime > conn->s_params.idletimeout)) {
                    478:     terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_IDLE_TIMEOUT);
                    479:   }
                    480:   else if ((conn->s_params.maxinputoctets) &&
                    481:           (conn->s_state.input_octets > conn->s_params.maxinputoctets)) {
                    482:     terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
                    483:   }
                    484:   else if ((conn->s_params.maxoutputoctets) &&
                    485:           (conn->s_state.output_octets > conn->s_params.maxoutputoctets)) {
                    486:     terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
                    487:   }
                    488:   else if ((conn->s_params.maxtotaloctets) &&
                    489:           ((conn->s_state.input_octets + conn->s_state.output_octets) > 
                    490:            conn->s_params.maxtotaloctets)) {
                    491:     terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_SESSION_TIMEOUT);
                    492:   }
                    493:   else if ((conn->s_params.interim_interval) &&
                    494:           (interimtime > conn->s_params.interim_interval)) {
                    495:     acct_req(conn, RADIUS_STATUS_TYPE_INTERIM_UPDATE);
                    496:   }
                    497: }
                    498: 
                    499: int static checkconn()
                    500: {
                    501:   time_t timenow = mainclock;
                    502:   struct app_conn_t *conn;
                    503:   struct dhcp_conn_t* dhcpconn;
                    504:   uint32_t checkdiff;
                    505:   uint32_t rereaddiff;
                    506: 
                    507:   checkdiff = timenow - checktime;
                    508: 
                    509:   if (checkdiff < CHECK_INTERVAL)
                    510:     return 0;
                    511: 
                    512:   checktime = timenow;
                    513:   
                    514:   if (admin_session.s_state.authenticated) {
                    515:     session_interval(&admin_session);
                    516:   }
                    517: 
                    518:   for (conn = firstusedconn; conn; conn=conn->next) {
                    519:     if ((conn->inuse != 0) && (conn->s_state.authenticated == 1)) {
                    520:       if (!(dhcpconn = (struct dhcp_conn_t *)conn->dnlink)) {
                    521:        log_err(0, "No downlink protocol");
                    522:        return -1;
                    523:       }
                    524:       session_interval(conn);
                    525:     }
                    526:   }
                    527:   
                    528:   /* Reread configuration file and recheck DNS */
                    529:   if (options.interval) {
                    530:     rereaddiff = timenow - rereadtime;
                    531:     if (rereaddiff >= options.interval) {
                    532:       rereadtime = timenow;
                    533:       do_sighup = 1;
                    534:     }
                    535:   }
                    536:   
                    537:   return 0;
                    538: }
                    539: 
                    540: /* Kill all connections and send Radius Acct Stop */
                    541: int static killconn()
                    542: {
                    543:   struct app_conn_t *conn;
                    544: 
                    545:   for (conn = firstusedconn; conn; conn=conn->next) {
                    546:     if ((conn->inuse != 0) && (conn->s_state.authenticated == 1)) {
                    547:       terminate_appconn(conn, RADIUS_TERMINATE_CAUSE_NAS_REBOOT);
                    548:     }
                    549:   }
                    550: 
                    551:   if (admin_session.s_state.authenticated) {
                    552:     admin_session.s_state.terminate_cause = RADIUS_TERMINATE_CAUSE_NAS_REBOOT;
                    553:     acct_req(&admin_session, RADIUS_STATUS_TYPE_STOP);
                    554:   }
                    555: 
                    556:   acct_req(&admin_session, RADIUS_STATUS_TYPE_ACCOUNTING_OFF);
                    557: 
                    558:   return 0;
                    559: }
                    560: 
                    561: /* Compare a MAC address to the addresses given in the macallowed option */
                    562: int static maccmp(unsigned char *mac) {
                    563:   int i; 
                    564: 
                    565:   for (i=0; i<options.macoklen; i++)
                    566:     if (!memcmp(mac, options.macok[i], PKT_ETH_ALEN))
                    567:       return 0;
                    568: 
                    569:   return -1;
                    570: }
                    571: 
                    572: int static macauth_radius(struct app_conn_t *appconn, 
                    573:                          struct dhcp_fullpacket_t *dhcp_pkt, size_t dhcp_len) {
                    574:   struct dhcp_conn_t *dhcpconn = (struct dhcp_conn_t *)appconn->dnlink;
                    575:   struct radius_packet_t radius_pack;
                    576:   char mac[MACSTRLEN+1];
                    577: 
                    578:   log_dbg("Starting mac radius authentication");
                    579: 
                    580:   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REQUEST)) {
                    581:     log_err(0, "radius_default_pack() failed");
                    582:     return -1;
                    583:   }
                    584:   
                    585:   /* Include his MAC address */
                    586:   snprintf(mac, MACSTRLEN+1, "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",
                    587:           dhcpconn->hismac[0], dhcpconn->hismac[1],
                    588:           dhcpconn->hismac[2], dhcpconn->hismac[3],
                    589:           dhcpconn->hismac[4], dhcpconn->hismac[5]);
                    590: 
                    591:   strncpy(appconn->s_state.redir.username, mac, USERNAMESIZE);
                    592: 
                    593:   if (options.macsuffix)
                    594:     strncat(appconn->s_state.redir.username, options.macsuffix, USERNAMESIZE);
                    595: 
                    596:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
                    597:                 (uint8_t*) appconn->s_state.redir.username, 
                    598:                 strlen(appconn->s_state.redir.username));
                    599:   
                    600:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0,
                    601:                 (uint8_t*) (options.macpasswd ? options.macpasswd : appconn->s_state.redir.username), 
                    602:                 options.macpasswd ? strlen(options.macpasswd) : strlen(appconn->s_state.redir.username));
                    603:   
                    604:   appconn->authtype = PAP_PASSWORD;
                    605:   
                    606:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0,
                    607:                 (uint8_t*) mac, MACSTRLEN);
                    608:   
                    609:   radius_addcalledstation(radius, &radius_pack);
                    610: 
                    611:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT, 0, 0,
                    612:                 appconn->unit, NULL, 0);
                    613: 
                    614:   radius_addnasip(radius, &radius_pack);
                    615: 
                    616:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_SERVICE_TYPE, 0, 0,
                    617:                 RADIUS_SERVICE_TYPE_LOGIN, NULL, 0); /* WISPr_V1.0 */
                    618:   
                    619:   /* Include NAS-Identifier if given in configuration options */
                    620:   if (options.radiusnasid)
                    621:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_IDENTIFIER, 0, 0, 0,
                    622:                   (uint8_t*) options.radiusnasid, strlen(options.radiusnasid));
                    623: 
                    624:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_SESSION_ID, 0, 0, 0,
                    625:                 (uint8_t*) appconn->s_state.sessionid, REDIR_SESSIONID_LEN-1);
                    626: 
                    627:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT_TYPE, 0, 0,
                    628:                 options.radiusnasporttype, NULL, 0);
                    629: 
                    630: 
                    631:   if (options.radiuslocationid)
                    632:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
                    633:                   RADIUS_VENDOR_WISPR, RADIUS_ATTR_WISPR_LOCATION_ID, 0,
                    634:                   (uint8_t*) options.radiuslocationid, 
                    635:                   strlen(options.radiuslocationid));
                    636: 
                    637:   if (options.radiuslocationname)
                    638:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
                    639:                   RADIUS_VENDOR_WISPR, RADIUS_ATTR_WISPR_LOCATION_NAME, 0,
                    640:                   (uint8_t*) options.radiuslocationname, 
                    641:                   strlen(options.radiuslocationname));
                    642: 
                    643:   if (options.dhcpradius && dhcp_pkt) {
                    644:     struct dhcp_tag_t *tag = 0;
                    645: 
                    646: #define maptag(OPT,VSA)\
                    647:     if (!dhcp_gettag(&dhcp_pkt->dhcp, ntohs(dhcp_pkt->udph.len)-PKT_UDP_HLEN, &tag, OPT)) { \
                    648:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC, \
                    649:                     RADIUS_VENDOR_CHILLISPOT, VSA, 0, (uint8_t *) tag->v, tag->l); } 
                    650:     /*
                    651:      *  Mapping of DHCP options to RADIUS Vendor Specific Attributes
                    652:      */
                    653:     maptag( DHCP_OPTION_PARAMETER_REQUEST_LIST,  RADIUS_ATTR_CHILLISPOT_DHCP_PARAMETER_REQUEST_LIST );
                    654:     maptag( DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, RADIUS_ATTR_CHILLISPOT_DHCP_VENDOR_CLASS_ID );
                    655:     maptag( DHCP_OPTION_CLIENT_IDENTIFIER,       RADIUS_ATTR_CHILLISPOT_DHCP_CLIENT_ID );
                    656:     maptag( DHCP_OPTION_CLIENT_FQDN,             RADIUS_ATTR_CHILLISPOT_DHCP_CLIENT_FQDN );
                    657:     maptag( DHCP_OPTION_HOSTNAME,                RADIUS_ATTR_CHILLISPOT_DHCP_HOSTNAME );
                    658: #undef maptag
                    659:   }
                    660:   
                    661:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, 
                    662:                 0, 0, 0, NULL, RADIUS_MD5LEN);
                    663: 
                    664:   return radius_req(radius, &radius_pack, appconn);
                    665: }
                    666: 
                    667: 
                    668: /*********************************************************
                    669:  *
                    670:  * radius proxy functions
                    671:  * Used to send a response to a received radius request
                    672:  *
                    673:  *********************************************************/
                    674: 
                    675: /* Reply with an access reject */
                    676: int static radius_access_reject(struct app_conn_t *conn) {
                    677:   struct radius_packet_t radius_pack;
                    678: 
                    679:   conn->radiuswait = 0;
                    680: 
                    681:   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REJECT)) {
                    682:     log_err(0, "radius_default_pack() failed");
                    683:     return -1;
                    684:   }
                    685: 
                    686:   radius_pack.id = conn->radiusid;
                    687:   radius_resp(radius, &radius_pack, &conn->radiuspeer, conn->authenticator);
                    688:   return 0;
                    689: }
                    690: 
                    691: /* Reply with an access challenge */
                    692: int static radius_access_challenge(struct app_conn_t *conn) {
                    693:   struct radius_packet_t radius_pack;
                    694:   size_t offset = 0;
                    695:   size_t eaplen = 0;
                    696: 
                    697:   conn->radiuswait = 0;
                    698: 
                    699:   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_CHALLENGE)){
                    700:     log_err(0, "radius_default_pack() failed");
                    701:     return -1;
                    702:   }
                    703: 
                    704:   radius_pack.id = conn->radiusid;
                    705: 
                    706:   /* Include EAP */
                    707:   do {
                    708:     if ((conn->challen - offset) > RADIUS_ATTR_VLEN)
                    709:       eaplen = RADIUS_ATTR_VLEN;
                    710:     else
                    711:       eaplen = conn->challen - offset;
                    712: 
                    713:     if (radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
                    714:                       conn->chal + offset, eaplen)) {
                    715:       log_err(0, "radius_default_pack() failed");
                    716:       return -1;
                    717:     }
                    718:     offset += eaplen;
                    719:   } while (offset < conn->challen);
                    720:   
                    721:   if (conn->s_state.redir.statelen) {
                    722:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_STATE, 0, 0, 0,
                    723:                   conn->s_state.redir.statebuf,
                    724:                   conn->s_state.redir.statelen);
                    725:   }
                    726:   
                    727:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, 
                    728:                 0, 0, 0, NULL, RADIUS_MD5LEN);
                    729:   
                    730:   radius_resp(radius, &radius_pack, &conn->radiuspeer, conn->authenticator);
                    731:   return 0;
                    732: }
                    733: 
                    734: /* Send off an access accept */
                    735: 
                    736: int static radius_access_accept(struct app_conn_t *conn) {
                    737:   struct radius_packet_t radius_pack;
                    738:   size_t offset = 0;
                    739:   size_t eaplen = 0;
                    740: 
                    741:   uint8_t mppekey[RADIUS_ATTR_VLEN];
                    742:   size_t mppelen;
                    743: 
                    744:   conn->radiuswait = 0;
                    745: 
                    746:   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_ACCEPT)) {
                    747:     log_err(0, "radius_default_pack() failed");
                    748:     return -1;
                    749:   }
                    750: 
                    751:   radius_pack.id = conn->radiusid;
                    752: 
                    753:   /* Include EAP (if present) */
                    754:   offset = 0;
                    755:   while (offset < conn->challen) {
                    756:     if ((conn->challen - offset) > RADIUS_ATTR_VLEN)
                    757:       eaplen = RADIUS_ATTR_VLEN;
                    758:     else
                    759:       eaplen = conn->challen - offset;
                    760: 
                    761:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
                    762:                   conn->chal + offset, eaplen);
                    763: 
                    764:     offset += eaplen;
                    765:   }
                    766: 
                    767:   if (conn->sendlen) {
                    768:     radius_keyencode(radius, mppekey, RADIUS_ATTR_VLEN,
                    769:                     &mppelen, conn->sendkey,
                    770:                     conn->sendlen, conn->authenticator,
                    771:                     radius->proxysecret, radius->proxysecretlen);
                    772: 
                    773:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
                    774:                   RADIUS_VENDOR_MS, RADIUS_ATTR_MS_MPPE_SEND_KEY, 0,
                    775:                   (uint8_t *)mppekey, mppelen);
                    776:   }
                    777: 
                    778:   if (conn->recvlen) {
                    779:     radius_keyencode(radius, mppekey, RADIUS_ATTR_VLEN,
                    780:                     &mppelen, conn->recvkey,
                    781:                     conn->recvlen, conn->authenticator,
                    782:                     radius->proxysecret, radius->proxysecretlen);
                    783:     
                    784:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
                    785:                   RADIUS_VENDOR_MS, RADIUS_ATTR_MS_MPPE_RECV_KEY, 0,
                    786:                   (uint8_t *)mppekey, mppelen);
                    787:   }
                    788:   
                    789:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, 
                    790:                 0, 0, 0, NULL, RADIUS_MD5LEN);
                    791: 
                    792:   radius_resp(radius, &radius_pack, &conn->radiuspeer, conn->authenticator);
                    793:   return 0;
                    794: }
                    795: 
                    796: 
                    797: /*********************************************************
                    798:  *
                    799:  * radius accounting functions
                    800:  * Used to send accounting request to radius server
                    801:  *
                    802:  *********************************************************/
                    803: 
                    804: static int acct_req(struct app_conn_t *conn, uint8_t status_type)
                    805: {
                    806:   struct radius_packet_t radius_pack;
                    807:   char mac[MACSTRLEN+1];
                    808:   char portid[16+1];
                    809:   time_t timenow;
                    810:   uint32_t timediff;
                    811: 
                    812:   if (RADIUS_STATUS_TYPE_START == status_type) {
                    813:     conn->s_state.start_time = mainclock;
                    814:     conn->s_state.interim_time = mainclock;
                    815:     conn->s_state.last_time = mainclock;
                    816:     conn->s_state.input_packets = 0;
                    817:     conn->s_state.output_packets = 0;
                    818:     conn->s_state.input_octets = 0;
                    819:     conn->s_state.output_octets = 0;
                    820:   }
                    821: 
                    822:   if (RADIUS_STATUS_TYPE_INTERIM_UPDATE == status_type) {
                    823:     conn->s_state.interim_time = mainclock;
                    824:   }
                    825: 
                    826:   if (radius_default_pack(radius, &radius_pack, 
                    827:                          RADIUS_CODE_ACCOUNTING_REQUEST)) {
                    828:     log_err(0, "radius_default_pack() failed");
                    829:     return -1;
                    830:   }
                    831: 
                    832:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_STATUS_TYPE, 0, 0,
                    833:                 status_type, NULL, 0);
                    834: 
                    835:   if (RADIUS_STATUS_TYPE_ACCOUNTING_ON != status_type &&
                    836:       RADIUS_STATUS_TYPE_ACCOUNTING_OFF != status_type) {
                    837: 
                    838:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
                    839:                   (uint8_t*) conn->s_state.redir.username, 
                    840:                   strlen(conn->s_state.redir.username));
                    841:     
                    842:     if (conn->s_state.redir.classlen) {
                    843:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_CLASS, 0, 0, 0,
                    844:                     conn->s_state.redir.classbuf,
                    845:                     conn->s_state.redir.classlen);
                    846:     }
                    847: 
                    848:     if (conn->is_adminsession) {
                    849:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_SERVICE_TYPE, 0, 0,
                    850:                     RADIUS_SERVICE_TYPE_ADMIN_USER, NULL, 0); 
                    851:     } else {
                    852:       snprintf(mac, MACSTRLEN+1, "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",
                    853:               conn->hismac[0], conn->hismac[1],
                    854:               conn->hismac[2], conn->hismac[3],
                    855:               conn->hismac[4], conn->hismac[5]);
                    856:       
                    857:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0,
                    858:                     (uint8_t*) mac, MACSTRLEN);
                    859:       
                    860:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT_TYPE, 0, 0,
                    861:                     options.radiusnasporttype, NULL, 0);
                    862:       
                    863:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT, 0, 0,
                    864:                     conn->unit, NULL, 0);
                    865: 
                    866:       snprintf(portid, 16+1, "%.8d", conn->unit);
                    867:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT_ID, 0, 0, 0,
                    868:                     (uint8_t*) portid, strlen(portid));
                    869: 
                    870:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_FRAMED_IP_ADDRESS, 0, 0,
                    871:                     ntohl(conn->hisip.s_addr), NULL, 0);
                    872:       
                    873:     }
                    874:     
                    875:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_SESSION_ID, 0, 0, 0,
                    876:                   (uint8_t*) conn->s_state.sessionid, REDIR_SESSIONID_LEN-1);
                    877:     
                    878:   }
                    879: 
                    880:   radius_addnasip(radius, &radius_pack);
                    881: 
                    882:   radius_addcalledstation(radius, &radius_pack);
                    883: 
                    884: 
                    885:   /* Include NAS-Identifier if given in configuration options */
                    886:   if (options.radiusnasid)
                    887:     (void) radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_IDENTIFIER, 0, 0, 0,
                    888:                   (uint8_t*) options.radiusnasid, 
                    889:                   strlen(options.radiusnasid));
                    890: 
                    891:   /*
                    892:   (void) radius_addattr(radius, &radius_pack, RADIUS_ATTR_FRAMED_MTU, 0, 0,
                    893:   conn->mtu, NULL, 0);*/
                    894: 
                    895:   if ((status_type == RADIUS_STATUS_TYPE_STOP) ||
                    896:       (status_type == RADIUS_STATUS_TYPE_INTERIM_UPDATE)) {
                    897: 
                    898:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_INPUT_OCTETS, 0, 0,
                    899:                   (uint32_t) conn->s_state.input_octets, NULL, 0);
                    900:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_OUTPUT_OCTETS, 0, 0,
                    901:                   (uint32_t) conn->s_state.output_octets, NULL, 0);
                    902: 
                    903:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, 
                    904:                   0, 0, (uint32_t) (conn->s_state.input_octets >> 32), NULL, 0);
                    905:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, 
                    906:                   0, 0, (uint32_t) (conn->s_state.output_octets >> 32), NULL, 0);
                    907: 
                    908:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_INPUT_PACKETS, 0, 0,
                    909:                   conn->s_state.input_packets, NULL, 0);
                    910:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_OUTPUT_PACKETS, 0, 0,
                    911:                   conn->s_state.output_packets, NULL, 0);
                    912: 
                    913:     timenow = mainclock;
                    914:     timediff = timenow - conn->s_state.start_time;
                    915: 
                    916:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_SESSION_TIME, 0, 0,
                    917:                   timediff, NULL, 0);  
                    918:   }
                    919: 
                    920:   if (options.radiuslocationid)
                    921:     (void) radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
                    922:                   RADIUS_VENDOR_WISPR, RADIUS_ATTR_WISPR_LOCATION_ID, 0,
                    923:                   (uint8_t*) options.radiuslocationid,
                    924:                   strlen(options.radiuslocationid));
                    925: 
                    926:   if (options.radiuslocationname)
                    927:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
                    928:                   RADIUS_VENDOR_WISPR, RADIUS_ATTR_WISPR_LOCATION_NAME, 0,
                    929:                   (uint8_t*) options.radiuslocationname, 
                    930:                   strlen(options.radiuslocationname));
                    931: 
                    932: 
                    933:   if (status_type == RADIUS_STATUS_TYPE_STOP ||
                    934:       status_type == RADIUS_STATUS_TYPE_ACCOUNTING_OFF) {
                    935: 
                    936:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_ACCT_TERMINATE_CAUSE, 
                    937:                   0, 0, conn->s_state.terminate_cause, NULL, 0);
                    938: 
                    939:     if (status_type == RADIUS_STATUS_TYPE_STOP) {
                    940:       /* TODO: This probably belongs somewhere else */
                    941:       if (options.condown) {
                    942:        if (options.debug)
                    943:          log_dbg("Calling connection down script: %s\n",options.condown);
                    944:        runscript(conn, options.condown);
                    945:       }
                    946:     }
                    947:   }
                    948:   
                    949:   radius_req(radius, &radius_pack, conn);
                    950:   
                    951:   return 0;
                    952: }
                    953: 
                    954: 
                    955: 
                    956: /***********************************************************
                    957:  *
                    958:  * Functions handling downlink protocol authentication.
                    959:  * Called in response to radius access request response.
                    960:  *
                    961:  ***********************************************************/
                    962: 
                    963: int static dnprot_reject(struct app_conn_t *appconn) {
                    964:   struct dhcp_conn_t* dhcpconn = NULL;
                    965:   /*struct ippoolm_t *ipm;*/
                    966: 
                    967:   switch (appconn->dnprot) {
                    968: 
                    969:   case DNPROT_EAPOL:
                    970:     if (!(dhcpconn = (struct dhcp_conn_t*) appconn->dnlink)) {
                    971:       log_err(0, "No downlink protocol");
                    972:       return 0;
                    973:     }
                    974: 
                    975:     dhcp_sendEAPreject(dhcpconn, NULL, 0);
                    976:     return 0;
                    977: 
                    978:   case DNPROT_UAM:
                    979:     log_err(0, "Rejecting UAM");
                    980:     return 0;
                    981: 
                    982:   case DNPROT_WPA:
                    983:     return radius_access_reject(appconn);
                    984: 
                    985:   case DNPROT_MAC:
                    986:     /* remove the username since we're not logged in */
                    987:     if (!appconn->s_state.authenticated)
                    988:       strncpy(appconn->s_state.redir.username, "-", USERNAMESIZE);
                    989: 
                    990:     if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
                    991:       log_err(0, "No downlink protocol");
                    992:       return 0;
                    993:     }
                    994: 
                    995:     if (options.macauthdeny) {
                    996:       dhcpconn->authstate = DHCP_AUTH_DROP;
                    997:       appconn->dnprot = DNPROT_NULL;
                    998:     }
                    999:     else {
                   1000:       dhcpconn->authstate = DHCP_AUTH_NONE;
                   1001:       appconn->dnprot = DNPROT_UAM;
                   1002:     }
                   1003: 
                   1004:     return 0;    
                   1005: 
                   1006:   case DNPROT_NULL:
                   1007:     return 0;
                   1008: 
                   1009:   default:
                   1010:     log_err(0, "Unknown downlink protocol");
                   1011:     return 0;
                   1012:   }
                   1013: }
                   1014: 
                   1015: int static dnprot_challenge(struct app_conn_t *appconn) {
                   1016:   struct dhcp_conn_t* dhcpconn = NULL;
                   1017: 
                   1018:   switch (appconn->dnprot) {
                   1019: 
                   1020:   case DNPROT_EAPOL:
                   1021:     if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
                   1022:       log_err(0, "No downlink protocol");
                   1023:       return 0;
                   1024:     }
                   1025: 
                   1026:     dhcp_sendEAP(dhcpconn, appconn->chal, appconn->challen);
                   1027:     break;
                   1028: 
                   1029:   case DNPROT_NULL:
                   1030:   case DNPROT_UAM:
                   1031:   case DNPROT_MAC:
                   1032:     break;
                   1033: 
                   1034:   case DNPROT_WPA:
                   1035:     radius_access_challenge(appconn);
                   1036:     break;
                   1037: 
                   1038:   default:
                   1039:     log_err(0, "Unknown downlink protocol");
                   1040:   }
                   1041: 
                   1042:   return 0;
                   1043: }
                   1044: 
                   1045: int static dnprot_accept(struct app_conn_t *appconn) {
                   1046:   struct dhcp_conn_t* dhcpconn = NULL;
                   1047:   
                   1048:   if (appconn->is_adminsession) return 0;
                   1049: 
                   1050:   if (!appconn->hisip.s_addr) {
                   1051:     log_err(0, "IP address not allocated");
                   1052:     return 0;
                   1053:   }
                   1054: 
                   1055:   switch (appconn->dnprot) {
                   1056:   case DNPROT_EAPOL:
                   1057:     if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
                   1058:       log_err(0, "No downlink protocol");
                   1059:       return 0;
                   1060:     }
                   1061: 
                   1062:     dhcp_set_addrs(dhcpconn, 
                   1063:                   &appconn->hisip, &appconn->mask,
                   1064:                   &appconn->ourip, &appconn->mask,
                   1065:                   &appconn->dns1, &appconn->dns2,
                   1066:                   options.domain);
                   1067:     
                   1068:     /* This is the one and only place eapol authentication is accepted */
                   1069: 
                   1070:     dhcpconn->authstate = DHCP_AUTH_PASS;
                   1071: 
                   1072:     /* Tell client it was successful */
                   1073:     dhcp_sendEAP(dhcpconn, appconn->chal, appconn->challen);
                   1074: 
                   1075:     log_warn(0, "Do not know how to set encryption keys on this platform!");
                   1076:     break;
                   1077: 
                   1078:   case DNPROT_UAM:
                   1079:     if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
                   1080:       log_err(0, "No downlink protocol");
                   1081:       return 0;
                   1082:     }
                   1083: 
                   1084:     dhcp_set_addrs(dhcpconn, 
                   1085:                   &appconn->hisip, &appconn->mask,
                   1086:                   &appconn->ourip, &appconn->mask,
                   1087:                   &appconn->dns1, &appconn->dns2,
                   1088:                   options.domain);
                   1089: 
                   1090:     /* This is the one and only place UAM authentication is accepted */
                   1091:     dhcpconn->authstate = DHCP_AUTH_PASS;
                   1092:     appconn->s_params.flags &= ~REQUIRE_UAM_AUTH;
                   1093:     break;
                   1094: 
                   1095:   case DNPROT_WPA:
                   1096:     if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
                   1097:       log_err(0, "No downlink protocol");
                   1098:       return 0;
                   1099:     }
                   1100: 
                   1101:     dhcp_set_addrs(dhcpconn, 
                   1102:                   &appconn->hisip, &appconn->mask, 
                   1103:                   &appconn->ourip, &appconn->mask, 
                   1104:                   &appconn->dns1, &appconn->dns2,
                   1105:                   options.domain);
                   1106:     
                   1107:     /* This is the one and only place WPA authentication is accepted */
                   1108:     if (appconn->s_params.flags & REQUIRE_UAM_AUTH) {
                   1109:       appconn->dnprot = DNPROT_DHCP_NONE;
                   1110:       dhcpconn->authstate = DHCP_AUTH_NONE;
                   1111:     }
                   1112:     else {
                   1113:       dhcpconn->authstate = DHCP_AUTH_PASS;
                   1114:     }
                   1115:     
                   1116:     /* Tell access point it was successful */
                   1117:     radius_access_accept(appconn);
                   1118: 
                   1119:     break;
                   1120: 
                   1121:   case DNPROT_MAC:
                   1122:     if (!(dhcpconn = (struct dhcp_conn_t *)appconn->dnlink)) {
                   1123:       log_err(0, "No downlink protocol");
                   1124:       return 0;
                   1125:     }
                   1126: 
                   1127:     dhcp_set_addrs(dhcpconn, 
                   1128:                   &appconn->hisip, &appconn->mask, 
                   1129:                   &appconn->ourip, &appconn->mask, 
                   1130:                   &appconn->dns1, &appconn->dns2,
                   1131:                   options.domain);
                   1132:     
                   1133:     dhcpconn->authstate = DHCP_AUTH_PASS;
                   1134:     break;
                   1135: 
                   1136:   case DNPROT_NULL:
                   1137:   case DNPROT_DHCP_NONE:
                   1138:     return 0;
                   1139: 
                   1140:   default:
                   1141:     log_err(0, "Unknown downlink protocol");
                   1142:     return 0;
                   1143:   }
                   1144: 
                   1145:   if (appconn->s_params.flags & REQUIRE_UAM_SPLASH)
                   1146:     dhcpconn->authstate = DHCP_AUTH_SPLASH;
                   1147:   
                   1148:   if (!(appconn->s_params.flags & REQUIRE_UAM_AUTH)) {
                   1149:     /* This is the one and only place state is switched to authenticated */
                   1150:     appconn->s_state.authenticated = 1;
                   1151:     
                   1152:     /* Run connection up script */
                   1153:     if (options.conup) {
                   1154:       if (options.debug) log_dbg("Calling connection up script: %s\n", options.conup);
                   1155:       runscript(appconn, options.conup);
                   1156:     }
                   1157:     
                   1158:     printstatus(appconn);
                   1159:     
                   1160:     if (!(appconn->s_params.flags & IS_UAM_REAUTH))
                   1161:       acct_req(appconn, RADIUS_STATUS_TYPE_START);
                   1162:   }
                   1163:   
                   1164:   appconn->s_params.flags &= ~IS_UAM_REAUTH;
                   1165:   return 0;
                   1166: }
                   1167: 
                   1168: 
                   1169: /*
                   1170:  * Tun callbacks
                   1171:  *
                   1172:  * Called from the tun_decaps function. This method is passed either
                   1173:  * a Ethernet frame or an IP packet. 
                   1174:  */
                   1175: 
                   1176: int cb_tun_ind(struct tun_t *tun, void *pack, size_t len, int idx) {
                   1177:   struct in_addr dst;
                   1178:   struct ippoolm_t *ipm;
                   1179:   struct app_conn_t *appconn;
                   1180:   struct pkt_ipphdr_t *ipph;
                   1181: 
                   1182:   int ethhdr = !!(tun(tun, idx).flags & NET_ETHHDR);
                   1183: 
                   1184:   if (ethhdr) {
                   1185:     struct pkt_ethhdr_t *ethh = (struct pkt_ethhdr_t *)pack;
                   1186:     uint16_t prot = ntohs(ethh->prot);
                   1187: 
                   1188:     ipph = (struct pkt_ipphdr_t *)((char *)pack + PKT_ETH_HLEN);
                   1189: 
                   1190:     if (prot == PKT_ETH_PROTO_ARP) {
                   1191:       /*
                   1192:        * send arp reply with us being target
                   1193:        */
                   1194:       struct arp_fullpacket_t *p = (struct arp_fullpacket_t *)pack;
                   1195:       struct arp_fullpacket_t packet;
                   1196:       struct in_addr reqaddr;
                   1197:       size_t length = sizeof(packet);
                   1198:       
                   1199:       log_dbg("arp: dst=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x src=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x prot=%.4x\n",
                   1200:              ethh->dst[0],ethh->dst[1],ethh->dst[2],ethh->dst[3],ethh->dst[4],ethh->dst[5],
                   1201:              ethh->src[0],ethh->src[1],ethh->src[2],ethh->src[3],ethh->src[4],ethh->src[5],
                   1202:              ntohs(ethh->prot));
                   1203:       
                   1204:       /* Get local copy */
                   1205:       memcpy(&reqaddr.s_addr, p->arp.tpa, PKT_IP_ALEN);
                   1206:       
                   1207:       if (ippool_getip(ippool, &ipm, &reqaddr)) {
                   1208:        if (options.debug) 
                   1209:            log_dbg("ARP for unknown IP %s\n", inet_ntoa(reqaddr));
                   1210:        return 0;
                   1211:       }
                   1212:       
                   1213:       if ((appconn  = (struct app_conn_t *)ipm->peer) == NULL ||
                   1214:          (appconn->dnlink) == NULL) {
                   1215:        log_err(0, "No peer protocol defined for ARP request");
                   1216:        return 0;
                   1217:       }
                   1218:       
                   1219:       /* Get packet default values */
                   1220:       memset(&packet, 0, sizeof(packet));
                   1221:       
                   1222:       /* ARP Payload */
                   1223:       packet.arp.hrd = htons(DHCP_HTYPE_ETH);
                   1224:       packet.arp.pro = htons(PKT_ETH_PROTO_IP);
                   1225:       packet.arp.hln = PKT_ETH_ALEN;
                   1226:       packet.arp.pln = PKT_IP_ALEN;
                   1227:       packet.arp.op  = htons(DHCP_ARP_REPLY);
                   1228:       
                   1229:       /* Source address */
                   1230:       /*memcpy(packet.arp.sha, dhcp->arp_hwaddr, PKT_ETH_ALEN);
                   1231:        memcpy(packet.arp.spa, &dhcp->ourip.s_addr, PKT_IP_ALEN);*/
                   1232:       /*memcpy(packet.arp.sha, appconn->hismac, PKT_ETH_ALEN);*/
                   1233:       memcpy(packet.arp.sha, tun->_interfaces[0].hwaddr, PKT_ETH_ALEN);
                   1234:       memcpy(packet.arp.spa, &appconn->hisip.s_addr, PKT_IP_ALEN);
                   1235:        
                   1236:       /* Target address */
                   1237:       /*memcpy(packet.arp.tha, &appconn->hismac, PKT_ETH_ALEN);
                   1238:        memcpy(packet.arp.tpa, &appconn->hisip.s_addr, PKT_IP_ALEN); */
                   1239:       memcpy(packet.arp.tha, p->arp.sha, PKT_ETH_ALEN);
                   1240:       memcpy(packet.arp.tpa, p->arp.spa, PKT_IP_ALEN);
                   1241:       
                   1242:       /* Ethernet header */
                   1243:       memcpy(packet.ethh.dst, p->ethh.src, PKT_ETH_ALEN);
                   1244:       memcpy(packet.ethh.src, dhcp->ipif.hwaddr, PKT_ETH_ALEN);
                   1245:       packet.ethh.prot = htons(PKT_ETH_PROTO_ARP);
                   1246:       
                   1247:       return tun_encaps(tun, &packet, length, idx);
                   1248:     }
                   1249:   } else {
                   1250:     ipph = (struct pkt_ipphdr_t *)pack;
                   1251:   }
                   1252: 
                   1253:   /*if (options.debug) 
                   1254:     log_dbg("cb_tun_ind. Packet received: Forwarding to link layer");*/
                   1255: 
                   1256:   dst.s_addr = ipph->daddr;
                   1257: 
                   1258:   if (ippool_getip(ippool, &ipm, &dst)) {
                   1259:     if (options.debug) 
                   1260:       log_dbg("dropping packet with unknown destination: %s", inet_ntoa(dst));
                   1261:     return 0;
                   1262:   }
                   1263:   
                   1264:   if ((appconn = (struct app_conn_t *)ipm->peer) == NULL ||
                   1265:       (appconn->dnlink) == NULL) {
                   1266:     log_err(0, "No peer protocol defined");
                   1267:     return 0;
                   1268:   }
                   1269:   
                   1270:   /* If the ip src is uamlisten and psrc is uamport we won't call leaky_bucket */
                   1271:   if ( ! (ipph->saddr  == options.uamlisten.s_addr && 
                   1272:          (ipph->sport == htons(options.uamport) ||
                   1273:           ipph->sport == htons(options.uamuiport)))) {
                   1274:     if (appconn->s_state.authenticated == 1) {
                   1275: 
                   1276: #ifndef LEAKY_BUCKET
                   1277:       appconn->s_state.last_time = mainclock;
                   1278: #endif
                   1279: 
                   1280: #ifdef LEAKY_BUCKET
                   1281: #ifndef COUNT_DOWNLINK_DROP
                   1282:     if (leaky_bucket(appconn, 0, len)) return 0;
                   1283: #endif
                   1284: #endif
                   1285:     if (options.swapoctets) {
                   1286:       appconn->s_state.output_packets++;
                   1287:       appconn->s_state.output_octets += len;
                   1288:       if (admin_session.s_state.authenticated) {
                   1289:        admin_session.s_state.output_packets++;
                   1290:        admin_session.s_state.output_octets+=len;
                   1291:       }
                   1292:     } else {
                   1293:       appconn->s_state.input_packets++;
                   1294:       appconn->s_state.input_octets += len;
                   1295:       if (admin_session.s_state.authenticated) {
                   1296:        admin_session.s_state.input_packets++;
                   1297:        admin_session.s_state.input_octets+=len;
                   1298:       }
                   1299:     }
                   1300: #ifdef LEAKY_BUCKET
                   1301: #ifdef COUNT_DOWNLINK_DROP
                   1302:     if (leaky_bucket(appconn, 0, len)) return 0;
                   1303: #endif
                   1304: #endif
                   1305:     }
                   1306:   }
                   1307: 
                   1308:   switch (appconn->dnprot) {
                   1309:   case DNPROT_NULL:
                   1310:   case DNPROT_DHCP_NONE:
                   1311:     break;
                   1312: 
                   1313:   case DNPROT_UAM:
                   1314:   case DNPROT_WPA:
                   1315:   case DNPROT_MAC:
                   1316:   case DNPROT_EAPOL:
                   1317:     dhcp_data_req((struct dhcp_conn_t *)appconn->dnlink, pack, len, ethhdr);
                   1318:     break;
                   1319: 
                   1320:   default:
                   1321:     log_err(0, "Unknown downlink protocol: %d", appconn->dnprot);
                   1322:     break;
                   1323:   }
                   1324: 
                   1325:   return 0;
                   1326: }
                   1327: 
                   1328: 
                   1329: /*********************************************************
                   1330:  *
                   1331:  * Redir callbacks
                   1332:  *
                   1333:  *********************************************************/
                   1334: 
                   1335: int cb_redir_getstate(struct redir_t *redir, struct in_addr *addr,
                   1336:                      struct redir_conn_t *conn) {
                   1337:   struct ippoolm_t *ipm;
                   1338:   struct app_conn_t *appconn;
                   1339:   struct dhcp_conn_t *dhcpconn;
                   1340: 
                   1341:   if (ippool_getip(ippool, &ipm, addr)) {
                   1342:     return -1;
                   1343:   }
                   1344:   
                   1345:   if ( (appconn  = (struct app_conn_t *)ipm->peer)        == NULL || 
                   1346:        (dhcpconn = (struct dhcp_conn_t *)appconn->dnlink) == NULL ) {
                   1347:     log_warn(0, "No peer protocol defined");
                   1348:     return -1;
                   1349:   }
                   1350:   
                   1351:   conn->nasip = options.radiuslisten;
                   1352:   conn->nasport = appconn->unit;
                   1353:   memcpy(conn->hismac, dhcpconn->hismac, PKT_ETH_ALEN);
                   1354:   memcpy(conn->ourmac, dhcpconn->ourmac, PKT_ETH_ALEN);
                   1355:   conn->ourip = appconn->ourip;
                   1356:   conn->hisip = appconn->hisip;
                   1357: 
                   1358:   memcpy(&conn->s_params, &appconn->s_params, sizeof(appconn->s_params));
                   1359:   memcpy(&conn->s_state,  &appconn->s_state,  sizeof(appconn->s_state));
                   1360: 
                   1361:   /* reset state */
                   1362:   appconn->uamexit=0;
                   1363: 
                   1364:   return conn->s_state.authenticated == 1;
                   1365: }
                   1366: 
                   1367: 
                   1368: /*********************************************************
                   1369:  *
                   1370:  * Functions supporting radius callbacks
                   1371:  *
                   1372:  *********************************************************/
                   1373: 
                   1374: /* Handle an accounting request */
                   1375: int accounting_request(struct radius_packet_t *pack,
                   1376:                       struct sockaddr_in *peer) {
                   1377:   struct radius_attr_t *hismacattr = NULL;
                   1378:   struct radius_attr_t *typeattr = NULL;
                   1379:   struct radius_attr_t *nasipattr = NULL;
                   1380:   struct radius_attr_t *nasportattr = NULL;
                   1381:   struct radius_packet_t radius_pack;
                   1382:   struct app_conn_t *appconn = NULL;
                   1383:   struct dhcp_conn_t *dhcpconn = NULL;
                   1384:   uint8_t hismac[PKT_ETH_ALEN];
                   1385:   char macstr[RADIUS_ATTR_VLEN];
                   1386:   size_t macstrlen;
                   1387:   unsigned int temp[PKT_ETH_ALEN];
                   1388:   uint32_t nasip = 0;
                   1389:   uint32_t nasport = 0;
                   1390:   int i;
                   1391: 
                   1392: 
                   1393:   if (radius_default_pack(radius, &radius_pack, 
                   1394:                          RADIUS_CODE_ACCOUNTING_RESPONSE)) {
                   1395:     log_err(0, "radius_default_pack() failed");
                   1396:     return -1;
                   1397:   }
                   1398:   radius_pack.id = pack->id;
                   1399:   
                   1400:   /* Status type */
                   1401:   if (radius_getattr(pack, &typeattr, RADIUS_ATTR_ACCT_STATUS_TYPE, 0, 0, 0)) {
                   1402:     log_err(0, "Status type is missing from radius request");
                   1403:     radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1404:     return 0;
                   1405:   }
                   1406: 
                   1407:   if (typeattr->v.i != htonl(RADIUS_STATUS_TYPE_STOP)) {
                   1408:     radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1409:     return 0;
                   1410:   }
                   1411: 
                   1412: 
                   1413:   /* NAS IP */
                   1414:   if (!radius_getattr(pack, &nasipattr, RADIUS_ATTR_NAS_IP_ADDRESS, 0, 0, 0)) {
                   1415:     if ((nasipattr->l-2) != sizeof(appconn->nasip)) {
                   1416:       log_err(0, "Wrong length of NAS IP address");
                   1417:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1418:     }
                   1419:     nasip = nasipattr->v.i;
                   1420:   }
                   1421:   
                   1422:   /* NAS PORT */
                   1423:   if (!radius_getattr(pack, &nasportattr, RADIUS_ATTR_NAS_PORT, 0, 0, 0)) {
                   1424:     if ((nasportattr->l-2) != sizeof(appconn->nasport)) {
                   1425:       log_err(0, "Wrong length of NAS port");
                   1426:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1427:     }
                   1428:     nasport = nasportattr->v.i;
                   1429:   }
                   1430:   
                   1431:   /* Calling Station ID (MAC Address) */
                   1432:   if (!radius_getattr(pack, &hismacattr, RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0)) {
                   1433:     if (options.debug) {
                   1434:       log_dbg("Calling Station ID is: %.*s", hismacattr->l-2, hismacattr->v.t);
                   1435:     }
                   1436:     if ((macstrlen = (size_t)hismacattr->l-2) >= (RADIUS_ATTR_VLEN-1)) {
                   1437:       log_err(0, "Wrong length of called station ID");
                   1438:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1439:     }
                   1440:     memcpy(macstr, hismacattr->v.t, macstrlen);
                   1441:     macstr[macstrlen] = 0;
                   1442:     
                   1443:     /* Replace anything but hex with space */
                   1444:     for (i=0; i<macstrlen; i++) 
                   1445:       if (!isxdigit(macstr[i])) macstr[i] = 0x20;
                   1446:     
                   1447:     if (sscanf (macstr, "%2x %2x %2x %2x %2x %2x",
                   1448:                &temp[0], &temp[1], &temp[2], 
                   1449:                &temp[3], &temp[4], &temp[5]) != 6) {
                   1450:       log_err(0,
                   1451:              "Failed to convert Calling Station ID to MAC Address");
                   1452:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1453:     }
                   1454:     
                   1455:     for(i = 0; i < PKT_ETH_ALEN; i++) 
                   1456:       hismac[i] = temp[i];
                   1457:   }
                   1458: 
                   1459:   if (hismacattr) { /* Look for mac address.*/
                   1460:     if (dhcp_hashget(dhcp, &dhcpconn, hismac)) {
                   1461:       log_err(0, "Unknown connection");
                   1462:       radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1463:       return 0;
                   1464:     }
                   1465:     if (!(dhcpconn->peer) || !((struct app_conn_t *)dhcpconn->peer)->uplink) {
                   1466:       log_err(0,"No peer protocol defined");
                   1467:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1468:     }
                   1469:     appconn = (struct app_conn_t*) dhcpconn->peer;
                   1470:   }
                   1471:   else if (nasipattr && nasportattr) { /* Look for NAS IP / Port */
                   1472:     if (getconn(&appconn, nasip, nasport)) {
                   1473:       log_err(0, "Unknown connection");
                   1474:       radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1475:       return 0;
                   1476:     }
                   1477:   }
                   1478:   else {
                   1479:     log_err(0,
                   1480:            "Calling Station ID or NAS IP/Port is missing from radius request");
                   1481:     radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1482:     return 0;
                   1483:   }
                   1484:   
                   1485:   /* Silently ignore radius request if allready processing one */
                   1486:   if (appconn->radiuswait) {
                   1487:     if (appconn->radiuswait == 2) {
                   1488:       log_dbg("Giving up on previous packet.. not dropping this one");
                   1489:       appconn->radiuswait=0;
                   1490:     } else {
                   1491:       log_dbg("Dropping RADIUS while waiting");
                   1492:       appconn->radiuswait++;
                   1493:       return 0;
                   1494:     }
                   1495:   }
                   1496:   
                   1497:   /* TODO: Check validity of pointers */
                   1498:   
                   1499:   switch (appconn->dnprot) {
                   1500:   case DNPROT_UAM:
                   1501:     log_err(0,"Auth stop received for UAM");
                   1502:     break;
                   1503:   case DNPROT_WPA:
                   1504:     dhcpconn = (struct dhcp_conn_t*) appconn->dnlink;
                   1505:     if (!dhcpconn) {
                   1506:       log_err(0,"No downlink protocol");
                   1507:       return 0;
                   1508:     }
                   1509:     /* Connection is simply deleted */
                   1510:     dhcp_freeconn(dhcpconn, RADIUS_TERMINATE_CAUSE_LOST_CARRIER);
                   1511:     break;
                   1512:   default:
                   1513:     log_err(0,"Unhandled downlink protocol %d", appconn->dnprot);
                   1514:     radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1515:     return 0;
                   1516:   }
                   1517: 
                   1518:   radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1519: 
                   1520:   return 0;
                   1521: }
                   1522: 
                   1523: 
                   1524: int access_request(struct radius_packet_t *pack,
                   1525:                   struct sockaddr_in *peer) {
                   1526:   int n;
                   1527:   struct radius_packet_t radius_pack;
                   1528: 
                   1529:   struct ippoolm_t *ipm = NULL;
                   1530: 
                   1531:   struct radius_attr_t *hisipattr = NULL;
                   1532:   struct radius_attr_t *nasipattr = NULL;
                   1533:   struct radius_attr_t *nasportattr = NULL;
                   1534:   struct radius_attr_t *hismacattr = NULL;
                   1535:   struct radius_attr_t *uidattr = NULL;
                   1536:   struct radius_attr_t *pwdattr = NULL;
                   1537:   struct radius_attr_t *eapattr = NULL;
                   1538: 
                   1539:   struct in_addr hisip;
                   1540:   char pwd[RADIUS_ATTR_VLEN];
                   1541:   size_t pwdlen;
                   1542:   uint8_t hismac[PKT_ETH_ALEN];
                   1543:   char macstr[RADIUS_ATTR_VLEN];
                   1544:   size_t macstrlen;
                   1545:   unsigned int temp[PKT_ETH_ALEN];
                   1546:   char mac[MACSTRLEN+1];
                   1547:   int i;
                   1548: 
                   1549:   struct app_conn_t *appconn = NULL;
                   1550:   struct dhcp_conn_t *dhcpconn = NULL;
                   1551: 
                   1552:   uint8_t resp[EAP_LEN];         /* EAP response */
                   1553:   size_t resplen;                /* Length of EAP response */
                   1554: 
                   1555:   size_t offset = 0;
                   1556:   size_t eaplen = 0;
                   1557:   int instance = 0;
                   1558: 
                   1559:   if (options.debug) 
                   1560:     log_dbg("RADIUS Access-Request received");
                   1561: 
                   1562:   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REJECT)) {
                   1563:     log_err(0, "radius_default_pack() failed");
                   1564:     return -1;
                   1565:   }
                   1566: 
                   1567:   radius_pack.id = pack->id;
                   1568: 
                   1569:   /* User is identified by either IP address OR MAC address */
                   1570:   
                   1571:   /* Framed IP address (Conditional) */
                   1572:   if (!radius_getattr(pack, &hisipattr, RADIUS_ATTR_FRAMED_IP_ADDRESS, 0, 0, 0)) {
                   1573:     if (options.debug) {
                   1574:       log_dbg("Framed IP address is: ");
                   1575:       for (n=0; n<hisipattr->l-2; n++) log_dbg("%.2x", hisipattr->v.t[n]); 
                   1576:       log_dbg("\n");
                   1577:     }
                   1578:     if ((hisipattr->l-2) != sizeof(hisip.s_addr)) {
                   1579:       log_err(0, "Wrong length of framed IP address");
                   1580:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1581:     }
                   1582:     hisip.s_addr = hisipattr->v.i;
                   1583:   }
                   1584: 
                   1585:   /* Calling Station ID: MAC Address (Conditional) */
                   1586:   if (!radius_getattr(pack, &hismacattr, RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0)) {
                   1587:     if (options.debug) {
                   1588:       log_dbg("Calling Station ID is: %.*s", hismacattr->l-2, hismacattr->v.t);
                   1589:     }
                   1590:     if ((macstrlen = (size_t)hismacattr->l-2) >= (RADIUS_ATTR_VLEN-1)) {
                   1591:       log_err(0, "Wrong length of called station ID");
                   1592:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1593:     }
                   1594:     memcpy(macstr, hismacattr->v.t, macstrlen);
                   1595:     macstr[macstrlen] = 0;
                   1596: 
                   1597:     /* Replace anything but hex with space */
                   1598:     for (i=0; i<macstrlen; i++) 
                   1599:       if (!isxdigit(macstr[i])) macstr[i] = 0x20;
                   1600: 
                   1601:     if (sscanf (macstr, "%2x %2x %2x %2x %2x %2x",
                   1602:                &temp[0], &temp[1], &temp[2], 
                   1603:                &temp[3], &temp[4], &temp[5]) != 6) {
                   1604:       log_err(0, "Failed to convert Calling Station ID to MAC Address");
                   1605:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1606:     }
                   1607:     
                   1608:     for(i = 0; i < PKT_ETH_ALEN; i++) 
                   1609:       hismac[i] = temp[i];
                   1610:   }
                   1611: 
                   1612:   /* Framed IP address or MAC Address must be given in request */
                   1613:   if ((!hisipattr) && (!hismacattr)) {
                   1614:     log_err(0, "Framed IP address or Calling Station ID is missing from radius request");
                   1615:     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1616:   }
                   1617: 
                   1618:   /* Username (Mandatory) */
                   1619:   if (radius_getattr(pack, &uidattr, RADIUS_ATTR_USER_NAME, 0, 0, 0)) {
                   1620:     log_err(0, "User-Name is missing from radius request");
                   1621:     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1622:   } 
                   1623: 
                   1624:   if (hisipattr) { /* Find user based on IP address */
                   1625:     if (ippool_getip(ippool, &ipm, &hisip)) {
                   1626:       log_err(0, "RADIUS-Request: IP Address not found");
                   1627:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1628:     }
                   1629:     
                   1630:     if ((appconn  = (struct app_conn_t *)ipm->peer)        == NULL || 
                   1631:        (dhcpconn = (struct dhcp_conn_t *)appconn->dnlink) == NULL) {
                   1632:       log_err(0, "RADIUS-Request: No peer protocol defined");
                   1633:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1634:     }
                   1635:   }
                   1636:   else if (hismacattr) { /* Look for mac address. If not found allocate new */
                   1637:     if (dhcp_hashget(dhcp, &dhcpconn, hismac)) {
                   1638:       if (dhcp_newconn(dhcp, &dhcpconn, hismac)) {
                   1639:        log_err(0, "Out of connections");
                   1640:        return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1641:       }
                   1642:     }
                   1643:     if (!(dhcpconn->peer)) {
                   1644:       log_err(0, "No peer protocol defined");
                   1645:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1646:     }
                   1647:     appconn = (struct app_conn_t *)dhcpconn->peer;
                   1648:     /*if (appconn->dnprot == DNPROT_DHCP_NONE)
                   1649:     appconn->dnprot = DNPROT_WPA;*/
                   1650:   }
                   1651:   else {
                   1652:     log_err(0, "Framed IP address or Calling Station ID is missing from radius request");
                   1653:     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1654:   }
                   1655: 
                   1656:   /* Silently ignore radius request if allready processing one */
                   1657:   if (appconn->radiuswait) {
                   1658:     if (appconn->radiuswait == 2) {
                   1659:       log_dbg("Giving up on previous packet.. not dropping this one");
                   1660:       appconn->radiuswait=0;
                   1661:     } else {
                   1662:       log_dbg("Dropping RADIUS while waiting");
                   1663:       appconn->radiuswait++;
                   1664:       return 0;
                   1665:     }
                   1666:   }
                   1667:   
                   1668:   /* Password */
                   1669:   if (!radius_getattr(pack, &pwdattr, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0)) {
                   1670:     if (radius_pwdecode(radius, (uint8_t*) pwd, RADIUS_ATTR_VLEN, &pwdlen, 
                   1671:                        pwdattr->v.t, pwdattr->l-2, pack->authenticator,
                   1672:                        radius->proxysecret,
                   1673:                        radius->proxysecretlen)) {
                   1674:       log_err(0, "radius_pwdecode() failed");
                   1675:       return -1;
                   1676:     }
                   1677:     if (options.debug) log_dbg("Password is: %s\n", pwd);
                   1678:   }
                   1679: 
                   1680:   /* Get EAP message */
                   1681:   resplen = 0;
                   1682:   do {
                   1683:     eapattr=NULL;
                   1684:     if (!radius_getattr(pack, &eapattr, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 
                   1685:                        instance++)) {
                   1686:       if ((resplen + (size_t)eapattr->l-2) > EAP_LEN) {
                   1687:        log(LOG_INFO, "EAP message too long");
                   1688:        return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1689:       }
                   1690:       memcpy(resp + resplen, eapattr->v.t, (size_t)eapattr->l-2);
                   1691:       resplen += (size_t)eapattr->l-2;
                   1692:     }
                   1693:   } while (eapattr);
                   1694:   
                   1695: 
                   1696:   /* Passwd or EAP must be given in request */
                   1697:   if ((!pwdattr) && (!resplen)) {
                   1698:     log_err(0, "Password or EAP meaasge is missing from radius request");
                   1699:     return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1700:   }
                   1701: 
                   1702:   /* ChilliSpot Notes:
                   1703:      Dublicate logins should be allowed as it might be the terminal
                   1704:      moving from one access point to another. It is however
                   1705:      unacceptable to login with another username on top of an allready
                   1706:      existing connection 
                   1707: 
                   1708:      TODO: New username should be allowed, but should result in
                   1709:      a accounting stop message for the old connection.
                   1710:      this does however pose a denial of service attack possibility 
                   1711:   
                   1712:      If allready logged in send back accept message with username
                   1713:      TODO ? Should this be a reject: Dont login twice ? 
                   1714:   */
                   1715: 
                   1716:   /* Terminate previous session if trying to login with another username */
                   1717:   if ((appconn->s_state.authenticated == 1) && 
                   1718:       ((strlen(appconn->s_state.redir.username) != uidattr->l-2) ||
                   1719:        (memcmp(appconn->s_state.redir.username, uidattr->v.t, uidattr->l-2)))) {
                   1720:     terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_USER_REQUEST);
                   1721:     /* DWB: But, let's not reject someone who is trying to authenticate under
                   1722:        a new (potentially) valid account - that is for the up-stream RADIUS to discern
                   1723:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);*/
                   1724:   }
                   1725: 
                   1726:   /* Radius auth only for DHCP */
                   1727:   /*if ((appconn->dnprot != DNPROT_UAM) && (appconn->dnprot != DNPROT_WPA))  { */
                   1728:     /*return radius_resp(radius, &radius_pack, peer, pack->authenticator);*/
                   1729:   appconn->dnprot = DNPROT_WPA;
                   1730:   /*  }*/
                   1731: 
                   1732:   /* NAS IP */
                   1733:   if (!radius_getattr(pack, &nasipattr, RADIUS_ATTR_NAS_IP_ADDRESS, 0, 0, 0)) {
                   1734:     if ((nasipattr->l-2) != sizeof(appconn->nasip)) {
                   1735:       log_err(0, "Wrong length of NAS IP address");
                   1736:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1737:     }
                   1738:     appconn->nasip = nasipattr->v.i;
                   1739:   }
                   1740: 
                   1741:   /* NAS PORT */
                   1742:   if (!radius_getattr(pack, &nasportattr, RADIUS_ATTR_NAS_PORT, 0, 0, 0)) {
                   1743:     if ((nasportattr->l-2) != sizeof(appconn->nasport)) {
                   1744:       log_err(0, "Wrong length of NAS port");
                   1745:       return radius_resp(radius, &radius_pack, peer, pack->authenticator);
                   1746:     }
                   1747:     appconn->nasport = nasportattr->v.i;
                   1748:   }
                   1749: 
                   1750:   /* Store parameters for later use */
                   1751:   if (uidattr->l-2<=USERNAMESIZE) {
                   1752:     strncpy(appconn->s_state.redir.username, 
                   1753:            (char *)uidattr->v.t, uidattr->l-2);
                   1754:   }
                   1755: 
                   1756:   appconn->radiuswait = 1;
                   1757:   appconn->radiusid = pack->id;
                   1758: 
                   1759:   if (pwdattr)
                   1760:     appconn->authtype = PAP_PASSWORD;
                   1761:   else
                   1762:     appconn->authtype = EAP_MESSAGE;
                   1763: 
                   1764:   memcpy(&appconn->radiuspeer, peer, sizeof(*peer));
                   1765:   memcpy(appconn->authenticator, pack->authenticator, RADIUS_AUTHLEN);
                   1766:   memcpy(appconn->hismac, dhcpconn->hismac, PKT_ETH_ALEN);
                   1767:   memcpy(appconn->ourmac, dhcpconn->ourmac, PKT_ETH_ALEN);
                   1768: 
                   1769:   /* Build up radius request */
                   1770:   radius_pack.code = RADIUS_CODE_ACCESS_REQUEST;
                   1771:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
                   1772:                 uidattr->v.t, uidattr->l - 2);
                   1773: 
                   1774:   if (appconn->s_state.redir.statelen) {
                   1775:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_STATE, 0, 0, 0,
                   1776:                   appconn->s_state.redir.statebuf,
                   1777:                   appconn->s_state.redir.statelen);
                   1778:   }
                   1779: 
                   1780:   if (pwdattr)
                   1781:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0,
                   1782:                   (uint8_t*) pwd, pwdlen);
                   1783: 
                   1784:   /* Include EAP (if present) */
                   1785:   offset = 0;
                   1786:   while (offset < resplen) {
                   1787: 
                   1788:     if ((resplen - offset) > RADIUS_ATTR_VLEN)
                   1789:       eaplen = RADIUS_ATTR_VLEN;
                   1790:     else
                   1791:       eaplen = resplen - offset;
                   1792: 
                   1793:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
                   1794:                   resp + offset, eaplen);
                   1795: 
                   1796:     offset += eaplen;
                   1797:   } 
                   1798: 
                   1799:   if (resplen) {
                   1800:     if (options.wpaguests)
                   1801:       radius_addattr(radius, &radius_pack, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1802:                     RADIUS_VENDOR_CHILLISPOT, RADIUS_ATTR_CHILLISPOT_CONFIG, 
                   1803:                     0, (uint8_t*)"allow-wpa-guests", 16);
                   1804: 
                   1805:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, 
                   1806:                   0, 0, 0, NULL, RADIUS_MD5LEN);
                   1807:   }
                   1808: 
                   1809:   /* Include his MAC address */
                   1810:   snprintf(mac, MACSTRLEN+1, "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",
                   1811:           appconn->hismac[0], appconn->hismac[1],
                   1812:           appconn->hismac[2], appconn->hismac[3],
                   1813:           appconn->hismac[4], appconn->hismac[5]);
                   1814:   
                   1815:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0,
                   1816:                 (uint8_t*) mac, MACSTRLEN);
                   1817:   
                   1818:   radius_addcalledstation(radius, &radius_pack);
                   1819:   
                   1820:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT_TYPE, 0, 0,
                   1821:                 options.radiusnasporttype, NULL, 0);
                   1822:   
                   1823:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT, 0, 0,
                   1824:                 appconn->unit, NULL, 0);
                   1825:   
                   1826:   radius_addnasip(radius, &radius_pack);
                   1827:   
                   1828:   /* Include NAS-Identifier if given in configuration options */
                   1829:   if (options.radiusnasid)
                   1830:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_IDENTIFIER, 0, 0, 0,
                   1831:                   (uint8_t*) options.radiusnasid, strlen(options.radiusnasid));
                   1832:   
                   1833:   return radius_req(radius, &radius_pack, appconn);
                   1834: }
                   1835: 
                   1836: 
                   1837: /*********************************************************
                   1838:  *
                   1839:  * radius proxy callback functions (request from radius server)
                   1840:  *
                   1841:  *********************************************************/
                   1842: 
                   1843: /* Radius callback when radius request has been received */
                   1844: int cb_radius_ind(struct radius_t *rp, struct radius_packet_t *pack,
                   1845:                  struct sockaddr_in *peer) {
                   1846: 
                   1847:   if (rp != radius) {
                   1848:     log_err(0, "Radius callback from unknown instance");
                   1849:     return 0;
                   1850:   }
                   1851:   
                   1852:   switch (pack->code) {
                   1853:   case RADIUS_CODE_ACCOUNTING_REQUEST: /* TODO: Exclude ??? */
                   1854:     return accounting_request(pack, peer);
                   1855:   case RADIUS_CODE_ACCESS_REQUEST:
                   1856:     return access_request(pack, peer);
                   1857:   default:
                   1858:     log_err(0, "Unsupported radius request received: %d", pack->code);
                   1859:     return 0;
                   1860:   }
                   1861: }
                   1862: 
                   1863: 
                   1864: int upprot_getip(struct app_conn_t *appconn, 
                   1865:                 struct in_addr *hisip, int statip) {
                   1866:   struct ippoolm_t *ipm;
                   1867: 
                   1868:   /* If IP address is allready allocated: Fill it in */
                   1869:   /* This should only happen for UAM */
                   1870:   /* TODO */
                   1871:   if (appconn->uplink) {
                   1872:     ipm = (struct ippoolm_t *)appconn->uplink;
                   1873:   }
                   1874:   else {
                   1875:     /* Allocate static or dynamic IP address */
                   1876: 
                   1877:     if (newip(&ipm, hisip))
                   1878:       return dnprot_reject(appconn);
                   1879: 
                   1880:     appconn->hisip.s_addr = ipm->addr.s_addr;
                   1881: 
                   1882:     /* TODO: Too many "listen" and "our" addresses having around */
                   1883:     appconn->ourip.s_addr = options.dhcplisten.s_addr;
                   1884:     
                   1885:     appconn->uplink = ipm;
                   1886:     ipm->peer = appconn; 
                   1887:   }
                   1888: 
                   1889:   return dnprot_accept(appconn);
                   1890: 
                   1891: }
                   1892: 
                   1893: void config_radius_session(struct session_params *params, struct radius_packet_t *pack, int reconfig) {
                   1894:   struct radius_attr_t *attr = NULL;
                   1895: 
                   1896:   /* Session timeout */
                   1897:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_SESSION_TIMEOUT, 0, 0, 0))
                   1898:     params->sessiontimeout = ntohl(attr->v.i);
                   1899:   else if (!reconfig)
                   1900:     params->sessiontimeout = 0;
                   1901: 
                   1902:   /* Idle timeout */
                   1903:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_IDLE_TIMEOUT, 0, 0, 0))
                   1904:     params->idletimeout = ntohl(attr->v.i);
                   1905:   else if (!reconfig) 
                   1906:     params->idletimeout = 0;
                   1907: 
                   1908:   /* Filter ID */
                   1909:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_FILTER_ID, 0, 0, 0)) {
                   1910:     params->filteridlen = attr->l-2;
                   1911:     memcpy(params->filteridbuf, attr->v.t, attr->l-2);
                   1912:     params->filteridbuf[attr->l-2] = 0;
                   1913:   }
                   1914:   else if (!reconfig) {
                   1915:     params->filteridlen = 0;
                   1916:     params->filteridbuf[0] = 0;
                   1917:   }
                   1918: 
                   1919:   /* Interim interval */
                   1920:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, 0, 0, 0)) {
                   1921:     params->interim_interval = ntohl(attr->v.i);
                   1922:     if (params->interim_interval < 60) {
                   1923:       log_err(0, "Received too small radius Acct-Interim-Interval: %d; resettings to default.",
                   1924:              params->interim_interval);
                   1925:       params->interim_interval = options.definteriminterval;
                   1926:     } 
                   1927:   }
                   1928:   else if (!reconfig)
                   1929:     params->interim_interval = 0;
                   1930: 
                   1931:   /* Bandwidth up */
                   1932:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1933:                      RADIUS_VENDOR_WISPR, 
                   1934:                      RADIUS_ATTR_WISPR_BANDWIDTH_MAX_UP, 0))
                   1935:     params->bandwidthmaxup = ntohl(attr->v.i);
                   1936:   else if (!reconfig)
                   1937:     params->bandwidthmaxup = 0;
                   1938:   
                   1939:   /* Bandwidth down */
                   1940:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1941:                      RADIUS_VENDOR_WISPR, 
                   1942:                      RADIUS_ATTR_WISPR_BANDWIDTH_MAX_DOWN, 0))
                   1943:     params->bandwidthmaxdown = ntohl(attr->v.i);
                   1944:   else if (!reconfig)
                   1945:     params->bandwidthmaxdown = 0;
                   1946: 
                   1947: #ifdef RADIUS_ATTR_CHILLISPOT_BANDWIDTH_MAX_UP
                   1948:   /* Bandwidth up */
                   1949:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1950:                      RADIUS_VENDOR_CHILLISPOT, 
                   1951:                      RADIUS_ATTR_CHILLISPOT_BANDWIDTH_MAX_UP, 0))
                   1952:     params->bandwidthmaxup = ntohl(attr->v.i) * 1000;
                   1953: #endif
                   1954: 
                   1955: #ifdef RADIUS_ATTR_CHILLISPOT_BANDWIDTH_MAX_DOWN
                   1956:   /* Bandwidth down */
                   1957:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1958:                      RADIUS_VENDOR_CHILLISPOT, 
                   1959:                      RADIUS_ATTR_CHILLISPOT_BANDWIDTH_MAX_DOWN, 0))
                   1960:     params->bandwidthmaxdown = ntohl(attr->v.i) * 1000;
                   1961: #endif
                   1962: 
                   1963:   /* Max input octets */
                   1964:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1965:                      RADIUS_VENDOR_CHILLISPOT, 
                   1966:                      RADIUS_ATTR_CHILLISPOT_MAX_INPUT_OCTETS, 0))
                   1967:     params->maxinputoctets = ntohl(attr->v.i);
                   1968:   else if (!reconfig)
                   1969:     params->maxinputoctets = 0;
                   1970: 
                   1971:   /* Max output octets */
                   1972:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1973:                      RADIUS_VENDOR_CHILLISPOT, 
                   1974:                      RADIUS_ATTR_CHILLISPOT_MAX_OUTPUT_OCTETS, 0))
                   1975:     params->maxoutputoctets = ntohl(attr->v.i);
                   1976:   else if (!reconfig)
                   1977:     params->maxoutputoctets = 0;
                   1978: 
                   1979:   /* Max total octets */
                   1980:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   1981:                      RADIUS_VENDOR_CHILLISPOT, 
                   1982:                      RADIUS_ATTR_CHILLISPOT_MAX_TOTAL_OCTETS, 0))
                   1983:     params->maxtotaloctets = ntohl(attr->v.i);
                   1984:   else if (!reconfig)
                   1985:     params->maxtotaloctets = 0;
                   1986: 
                   1987:   /* Route Index, look-up by interface name */
                   1988:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC, 
                   1989:                      RADIUS_VENDOR_CHILLISPOT, 
                   1990:                      RADIUS_ATTR_CHILLISPOT_ROUTE_TO_INTERFACE, 0)) {
                   1991:     char name[256];
                   1992:     memcpy(name, attr->v.t, attr->l-2);
                   1993:     name[attr->l-2] = 0;
                   1994:     params->routeidx = tun_name2idx(tun, name);
                   1995:   }
                   1996:   else if (!reconfig) {
                   1997:     params->routeidx = tun->routeidx;
                   1998:   }
                   1999: 
                   2000:   {
                   2001:     const char *uamauth = "require-uam-auth";
                   2002:     const char *uamallowed = "uamallowed=";
                   2003:     const char *splash = "splash";
                   2004:     size_t offset = 0;
                   2005:     int is_splash = 0;
                   2006: 
                   2007:     /* Always reset the per session passthroughs */
                   2008:     params->pass_through_count = 0;
                   2009: 
                   2010:     while (!radius_getnextattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2011:                               RADIUS_VENDOR_CHILLISPOT, RADIUS_ATTR_CHILLISPOT_CONFIG, 
                   2012:                               0, &offset)) { 
                   2013:       size_t len = (size_t)attr->l-2;
                   2014:       char *val = (char *)attr->v.t;
                   2015: 
                   2016:       if (options.wpaguests && len == strlen(uamauth) && !memcmp(val, uamauth, len)) {
                   2017:        log_dbg("received wpaguests");
                   2018:        params->flags |= REQUIRE_UAM_AUTH;
                   2019:       } 
                   2020:       else if (len == strlen(splash) && !memcmp(val, splash, strlen(splash))) {
                   2021:        log_dbg("received splash response");
                   2022:        params->flags |= REQUIRE_UAM_SPLASH;
                   2023:        is_splash = 1;
                   2024:       }
                   2025:       else if (len > strlen(uamallowed) && !memcmp(val, uamallowed, strlen(uamallowed))) {
                   2026:        val[len]=0;
                   2027:        pass_throughs_from_string(params->pass_throughs,
                   2028:                                  SESSION_PASS_THROUGH_MAX,
                   2029:                                  &params->pass_through_count,
                   2030:                                  val + strlen(uamallowed));
                   2031:       }
                   2032:     }
                   2033: 
                   2034:     offset = 0;
                   2035:     params->url[0]=0;
                   2036:     while (!radius_getnextattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2037:                               RADIUS_VENDOR_WISPR, RADIUS_ATTR_WISPR_REDIRECTION_URL, 
                   2038:                               0, &offset)) { 
                   2039:       size_t clen, nlen = (size_t)attr->l-2;
                   2040:       char *url = (char*)attr->v.t;
                   2041:       clen = strlen((char*)params->url);
                   2042: 
                   2043:       if (clen + nlen > sizeof(params->url)-1) 
                   2044:        nlen = sizeof(params->url)-clen-1;
                   2045: 
                   2046:       strncpy((char*)(params->url + clen), url, nlen);
                   2047:       params->url[nlen+clen]=0;
                   2048: 
                   2049:       if (!splash)
                   2050:        params->flags |= REQUIRE_REDIRECT;
                   2051:     }
                   2052:   }
                   2053: 
                   2054:   /* Session-Terminate-Time */
                   2055:   if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2056:                      RADIUS_VENDOR_WISPR,
                   2057:                      RADIUS_ATTR_WISPR_SESSION_TERMINATE_TIME, 0)) {
                   2058:     char attrs[RADIUS_ATTR_VLEN+1];
                   2059:     struct tm stt;
                   2060:     int tzhour, tzmin;
                   2061:     char *tz;
                   2062:     int result;
                   2063: 
                   2064:     memcpy(attrs, attr->v.t, attr->l-2);
                   2065:     attrs[attr->l-2] = 0;
                   2066: 
                   2067:     memset(&stt, 0, sizeof(stt));
                   2068: 
                   2069:     result = sscanf(attrs, "%d-%d-%dT%d:%d:%d %d:%d",
                   2070:                    &stt.tm_year, &stt.tm_mon, &stt.tm_mday,
                   2071:                    &stt.tm_hour, &stt.tm_min, &stt.tm_sec,
                   2072:                    &tzhour, &tzmin);
                   2073: 
                   2074:     if (result == 8) { /* Timezone */
                   2075:       /* tzhour and tzmin is hours and minutes east of GMT */
                   2076:       /* timezone is defined as seconds west of GMT. Excludes DST */
                   2077:       stt.tm_year -= 1900;
                   2078:       stt.tm_mon  -= 1;
                   2079:       stt.tm_hour -= tzhour; /* Adjust for timezone */
                   2080:       stt.tm_min  -= tzmin;  /* Adjust for timezone */
                   2081:       /*      stt.tm_hour += daylight;*/
                   2082:       /*stt.tm_min  -= (timezone / 60);*/
                   2083:       tz = getenv("TZ");
                   2084:       setenv("TZ", "", 1); /* Set environment to UTC */
                   2085:       tzset();
                   2086:       params->sessionterminatetime = mktime(&stt);
                   2087:       if (tz) 
                   2088:        setenv("TZ", tz, 1); 
                   2089:       else
                   2090:        unsetenv("TZ");
                   2091:       tzset();
                   2092:     }
                   2093:     else if (result >= 6) { /* Local time */
                   2094:       tzset();
                   2095:       stt.tm_year -= 1900;
                   2096:       stt.tm_mon  -= 1;
                   2097:       stt.tm_isdst = -1; /*daylight;*/
                   2098:       params->sessionterminatetime = mktime(&stt);
                   2099:     }
                   2100:     else {
                   2101:       params->sessionterminatetime = 0;
                   2102:       log(LOG_WARNING, "Illegal WISPr-Session-Terminate-Time received: %s", attrs);
                   2103:     }
                   2104:   }
                   2105:   else if (!reconfig)
                   2106:     params->sessionterminatetime = 0;
                   2107: }
                   2108: 
                   2109: static int chilliauth_cb(struct radius_t *radius,
                   2110:                         struct radius_packet_t *pack,
                   2111:                         struct radius_packet_t *pack_req, void *cbp) {
                   2112:   struct radius_attr_t *attr = NULL;
                   2113:   size_t offset = 0;
                   2114: 
                   2115:   if (!pack) { 
                   2116:     log_err(0, "Radius request timed out");
                   2117:     return 0;
                   2118:   }
                   2119: 
                   2120:   if ((pack->code != RADIUS_CODE_ACCESS_REJECT) && 
                   2121:       (pack->code != RADIUS_CODE_ACCESS_CHALLENGE) &&
                   2122:       (pack->code != RADIUS_CODE_ACCESS_ACCEPT)) {
                   2123:     log_err(0, "Unknown radius access reply code %d", pack->code);
                   2124:     return 0;
                   2125:   }
                   2126: 
                   2127:   /* ACCESS-ACCEPT */
                   2128:   if (pack->code != RADIUS_CODE_ACCESS_ACCEPT) {
                   2129:     log_err(0, "Administrative-User Login Failed");
                   2130:     return 0;
                   2131:   }
                   2132: 
                   2133:   while (!radius_getnextattr(pack, &attr, 
                   2134:                             RADIUS_ATTR_VENDOR_SPECIFIC,
                   2135:                             RADIUS_VENDOR_CHILLISPOT,
                   2136:                             RADIUS_ATTR_CHILLISPOT_CONFIG, 
                   2137:                             0, &offset)) {
                   2138:     char value[RADIUS_ATTR_VLEN+1] = "";
                   2139:     strncpy(value, (const char *)attr->v.t, attr->l - 2);
                   2140: 
                   2141:     /* build the command line argv here and pass to config parser! */
                   2142:     /* XXX */
                   2143:     printf("%s\n", value);
                   2144:   }
                   2145: 
                   2146:   if (!admin_session.s_state.authenticated) {
                   2147:     admin_session.s_state.authenticated = 1;
                   2148:     acct_req(&admin_session, RADIUS_STATUS_TYPE_START);
                   2149:   }
                   2150: 
                   2151:   return 0;
                   2152: }
                   2153: 
                   2154: int cb_radius_acct_conf(struct radius_t *radius, 
                   2155:                        struct radius_packet_t *pack,
                   2156:                        struct radius_packet_t *pack_req, void *cbp) {
                   2157:   struct app_conn_t *appconn = (struct app_conn_t*) cbp;
                   2158:   if (!appconn) {
                   2159:     log_err(0,"No peer protocol defined");
                   2160:     return 0;
                   2161:   }
                   2162:   config_radius_session(&appconn->s_params, pack, 1); /*XXX*/
                   2163:   return 0;
                   2164: }
                   2165: 
                   2166: /*********************************************************
                   2167:  *
                   2168:  * radius callback functions (response from radius server)
                   2169:  *
                   2170:  *********************************************************/
                   2171: 
                   2172: /* Radius callback when access accept/reject/challenge has been received */
                   2173: int cb_radius_auth_conf(struct radius_t *radius, 
                   2174:                        struct radius_packet_t *pack,
                   2175:                        struct radius_packet_t *pack_req, void *cbp) {
                   2176:   struct radius_attr_t *hisipattr = NULL;
                   2177:   struct radius_attr_t *lmntattr = NULL;
                   2178:   struct radius_attr_t *sendattr = NULL;
                   2179:   struct radius_attr_t *recvattr = NULL;
                   2180:   struct radius_attr_t *succattr = NULL;
                   2181:   struct radius_attr_t *policyattr = NULL;
                   2182:   struct radius_attr_t *typesattr = NULL;
                   2183: 
                   2184:   struct radius_attr_t *eapattr = NULL;
                   2185:   struct radius_attr_t *stateattr = NULL;
                   2186:   struct radius_attr_t *classattr = NULL;
                   2187: 
                   2188:   int instance = 0;
                   2189:   struct in_addr *hisip = NULL;
                   2190:   int statip = 0;
                   2191: 
                   2192:   struct app_conn_t *appconn = (struct app_conn_t*) cbp;
                   2193: 
                   2194:   if (options.debug)
                   2195:     log_dbg("Received access request confirmation from radius server\n");
                   2196:   
                   2197:   if (!appconn) {
                   2198:     log_err(0,"No peer protocol defined");
                   2199:     return 0;
                   2200:   }
                   2201: 
                   2202:   /* Initialise */
                   2203:   appconn->s_state.redir.statelen = 0;
                   2204:   appconn->challen  = 0;
                   2205:   appconn->sendlen  = 0;
                   2206:   appconn->recvlen  = 0;
                   2207:   appconn->lmntlen  = 0;
                   2208:   
                   2209: 
                   2210:   if (!pack) { /* Timeout */
                   2211:     log_err(0, "Radius request timed out");
                   2212:     return dnprot_reject(appconn);
                   2213:   }
                   2214: 
                   2215:   /* ACCESS-REJECT */
                   2216:   if (pack->code == RADIUS_CODE_ACCESS_REJECT) {
                   2217:     if (options.debug)
                   2218:       log_dbg("Received access reject from radius server");
                   2219:     config_radius_session(&appconn->s_params, pack, 0); /*XXX*/
                   2220:     return dnprot_reject(appconn);
                   2221:   }
                   2222: 
                   2223:   /* Get State */
                   2224:   if (!radius_getattr(pack, &stateattr, RADIUS_ATTR_STATE, 0, 0, 0)) {
                   2225:     appconn->s_state.redir.statelen = stateattr->l-2;
                   2226:     memcpy(appconn->s_state.redir.statebuf, stateattr->v.t, stateattr->l-2);
                   2227:   }
                   2228: 
                   2229:   /* ACCESS-CHALLENGE */
                   2230:   if (pack->code == RADIUS_CODE_ACCESS_CHALLENGE) {
                   2231:     if (options.debug)
                   2232:       log_dbg("Received access challenge from radius server");
                   2233: 
                   2234:     /* Get EAP message */
                   2235:     appconn->challen = 0;
                   2236:     do {
                   2237:       eapattr=NULL;
                   2238:       if (!radius_getattr(pack, &eapattr, RADIUS_ATTR_EAP_MESSAGE, 0, 0, instance++)) {
                   2239:        if ((appconn->challen + eapattr->l-2) > EAP_LEN) {
                   2240:          log(LOG_INFO, "EAP message too long");
                   2241:          return dnprot_reject(appconn);
                   2242:        }
                   2243:        memcpy(appconn->chal+appconn->challen, eapattr->v.t, eapattr->l-2);
                   2244:        appconn->challen += eapattr->l-2;
                   2245:       }
                   2246:     } while (eapattr);
                   2247:     
                   2248:     if (!appconn->challen) {
                   2249:       log(LOG_INFO, "No EAP message found");
                   2250:       return dnprot_reject(appconn);
                   2251:     }
                   2252:     
                   2253:     return dnprot_challenge(appconn);
                   2254:   }
                   2255:   
                   2256:   /* ACCESS-ACCEPT */
                   2257:   if (pack->code != RADIUS_CODE_ACCESS_ACCEPT) {
                   2258:     log_err(0, "Unknown code of radius access request confirmation");
                   2259:     return dnprot_reject(appconn);
                   2260:   }
                   2261: 
                   2262:   /* Class */
                   2263:   if (!radius_getattr(pack, &classattr, RADIUS_ATTR_CLASS, 0, 0, 0)) {
                   2264:     appconn->s_state.redir.classlen = classattr->l-2;
                   2265:     memcpy(appconn->s_state.redir.classbuf, classattr->v.t, classattr->l-2);
                   2266:     /*log_dbg("!!!! CLASSLEN = %d !!!!", appconn->s_state.redir.classlen);*/
                   2267:   }
                   2268:   else {
                   2269:     /*log_dbg("!!!! RESET CLASSLEN !!!!");*/
                   2270:     appconn->s_state.redir.classlen = 0;
                   2271:   }
                   2272: 
                   2273:   /* Framed IP address (Optional) */
                   2274:   if (!radius_getattr(pack, &hisipattr, RADIUS_ATTR_FRAMED_IP_ADDRESS, 0, 0, 0)) {
                   2275:     if ((hisipattr->l-2) != sizeof(struct in_addr)) {
                   2276:       log_err(0, "Wrong length of framed IP address");
                   2277:       return dnprot_reject(appconn);
                   2278:     }
                   2279:     hisip = (struct in_addr*) &(hisipattr->v.i);
                   2280:     statip = 1;
                   2281:   }
                   2282:   else {
                   2283:     hisip = (struct in_addr*) &appconn->reqip.s_addr;
                   2284:   }
                   2285: 
                   2286:   config_radius_session(&appconn->s_params, pack, 0);
                   2287: 
                   2288:   if (options.dhcpradius) {
                   2289:     struct dhcp_conn_t *dhcpconn = (struct dhcp_conn_t *)appconn->dnlink;
                   2290:     struct radius_attr_t *attr = NULL;
                   2291:     if (dhcpconn) {
                   2292:       if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC, RADIUS_VENDOR_CHILLISPOT, 
                   2293:                          RADIUS_ATTR_CHILLISPOT_DHCP_SERVER_NAME, 0)) {
                   2294:        memcpy(dhcpconn->dhcp_opts.sname, attr->v.t, attr->l-2);
                   2295:       }
                   2296:       if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC, RADIUS_VENDOR_CHILLISPOT, 
                   2297:                          RADIUS_ATTR_CHILLISPOT_DHCP_FILENAME, 0)) {
                   2298:        memcpy(dhcpconn->dhcp_opts.file, attr->v.t, attr->l-2);
                   2299:       }
                   2300:       if (!radius_getattr(pack, &attr, RADIUS_ATTR_VENDOR_SPECIFIC, RADIUS_VENDOR_CHILLISPOT, 
                   2301:                          RADIUS_ATTR_CHILLISPOT_DHCP_OPTION, 0)) {
                   2302:        memcpy(dhcpconn->dhcp_opts.options, attr->v.t, 
                   2303:               dhcpconn->dhcp_opts.option_length = attr->l-2);
                   2304:       }
                   2305:     }
                   2306:   }
                   2307: 
                   2308:   if (appconn->s_params.sessionterminatetime) {
                   2309:     time_t timenow = mainclock;
                   2310:     if (timenow > appconn->s_params.sessionterminatetime) {
                   2311:       log(LOG_WARNING, "WISPr-Session-Terminate-Time in the past received, rejecting");
                   2312:       return dnprot_reject(appconn);
                   2313:     }
                   2314:   }
                   2315: 
                   2316: #ifdef LEAKY_BUCKET
                   2317:   if (appconn->s_params.bandwidthmaxup) {
                   2318: #ifdef BUCKET_SIZE
                   2319:     appconn->s_state.bucketupsize = BUCKET_SIZE;
                   2320: #else
                   2321:     appconn->s_state.bucketupsize = appconn->s_params.bandwidthmaxup / 8000 * BUCKET_TIME;
                   2322:     if (appconn->s_state.bucketupsize < BUCKET_SIZE_MIN) 
                   2323:       appconn->s_state.bucketupsize = BUCKET_SIZE_MIN;
                   2324: #endif
                   2325:   }
                   2326: #endif
                   2327:   
                   2328: #ifdef LEAKY_BUCKET
                   2329:   if (appconn->s_params.bandwidthmaxdown) {
                   2330: #ifdef BUCKET_SIZE
                   2331:     appconn->s_state.bucketdownsize = BUCKET_SIZE;
                   2332: #else
                   2333:     appconn->s_state.bucketdownsize = appconn->s_params.bandwidthmaxdown / 8000 * BUCKET_TIME;
                   2334:     if (appconn->s_state.bucketdownsize < BUCKET_SIZE_MIN) 
                   2335:       appconn->s_state.bucketdownsize = BUCKET_SIZE_MIN;
                   2336: #endif
                   2337:   }
                   2338: #endif
                   2339: 
                   2340:   /* EAP Message */
                   2341:   appconn->challen = 0;
                   2342:   do {
                   2343:     eapattr=NULL;
                   2344:     if (!radius_getattr(pack, &eapattr, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 
                   2345:                        instance++)) {
                   2346:       if ((appconn->challen + eapattr->l-2) > EAP_LEN) {
                   2347:        log(LOG_INFO, "EAP message too long");
                   2348:        return dnprot_reject(appconn);
                   2349:       }
                   2350:       memcpy(appconn->chal+appconn->challen,
                   2351:             eapattr->v.t, eapattr->l-2);
                   2352:       appconn->challen += eapattr->l-2;
                   2353:     }
                   2354:   } while (eapattr);
                   2355: 
                   2356:   /* Get sendkey */
                   2357:   if (!radius_getattr(pack, &sendattr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2358:                      RADIUS_VENDOR_MS,
                   2359:                      RADIUS_ATTR_MS_MPPE_SEND_KEY, 0)) {
                   2360:     if (radius_keydecode(radius, appconn->sendkey, RADIUS_ATTR_VLEN, &appconn->sendlen, 
                   2361:                         (uint8_t *)&sendattr->v.t, sendattr->l-2, 
                   2362:                         pack_req->authenticator,
                   2363:                         radius->secret, radius->secretlen)) {
                   2364:       log_err(0, "radius_keydecode() failed!");
                   2365:       return dnprot_reject(appconn);
                   2366:     }
                   2367:   }
                   2368:     
                   2369:   /* Get recvkey */
                   2370:   if (!radius_getattr(pack, &recvattr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2371:                      RADIUS_VENDOR_MS,
                   2372:                      RADIUS_ATTR_MS_MPPE_RECV_KEY, 0)) {
                   2373:     if (radius_keydecode(radius, appconn->recvkey, RADIUS_ATTR_VLEN, &appconn->recvlen, 
                   2374:                         (uint8_t *)&recvattr->v.t, recvattr->l-2, 
                   2375:                         pack_req->authenticator,
                   2376:                         radius->secret, radius->secretlen) ) {
                   2377:       log_err(0, "radius_keydecode() failed!");
                   2378:       return dnprot_reject(appconn);
                   2379:     }
                   2380:   }
                   2381: 
                   2382:   /* Get LMNT keys */
                   2383:   if (!radius_getattr(pack, &lmntattr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2384:                      RADIUS_VENDOR_MS,
                   2385:                      RADIUS_ATTR_MS_CHAP_MPPE_KEYS, 0)) {
                   2386: 
                   2387:     /* TODO: Check length of vendor attributes */
                   2388:     if (radius_pwdecode(radius, appconn->lmntkeys, RADIUS_MPPEKEYSSIZE,
                   2389:                        &appconn->lmntlen, (uint8_t *)&lmntattr->v.t,
                   2390:                        lmntattr->l-2, pack_req->authenticator,
                   2391:                        radius->secret, radius->secretlen)) {
                   2392:       log_err(0, "radius_pwdecode() failed");
                   2393:       return dnprot_reject(appconn);
                   2394:     }
                   2395:   }
                   2396:   
                   2397:   /* Get encryption policy */
                   2398:   if (!radius_getattr(pack, &policyattr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2399:                      RADIUS_VENDOR_MS, 
                   2400:                      RADIUS_ATTR_MS_MPPE_ENCRYPTION_POLICY, 0)) {
                   2401:     appconn->policy = ntohl(policyattr->v.i);
                   2402:   }
                   2403:   
                   2404:   /* Get encryption types */
                   2405:   if (!radius_getattr(pack, &typesattr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2406:                      RADIUS_VENDOR_MS, 
                   2407:                      RADIUS_ATTR_MS_MPPE_ENCRYPTION_TYPES, 0)) {
                   2408:     appconn->types = ntohl(typesattr->v.i);
                   2409:   }
                   2410:   
                   2411: 
                   2412:   /* Get MS_Chap_v2 SUCCESS */
                   2413:   if (!radius_getattr(pack, &succattr, RADIUS_ATTR_VENDOR_SPECIFIC,
                   2414:                      RADIUS_VENDOR_MS,
                   2415:                      RADIUS_ATTR_MS_CHAP2_SUCCESS, 0)) {
                   2416:     if ((succattr->l-5) != MS2SUCCSIZE) {
                   2417:       log_err(0, "Wrong length of MS-CHAP2 success: %d", succattr->l-5);
                   2418:       return dnprot_reject(appconn);
                   2419:     }
                   2420:     memcpy(appconn->ms2succ, ((void*)&succattr->v.t)+3, MS2SUCCSIZE);
                   2421:   }
                   2422: 
                   2423:   /* for the admin session */
                   2424:   if (appconn->is_adminsession) {
                   2425:     return chilliauth_cb(radius, pack, pack_req, cbp);
                   2426:   }
                   2427: 
                   2428:   switch(appconn->authtype) {
                   2429: 
                   2430:   case PAP_PASSWORD:
                   2431:     appconn->policy = 0; /* TODO */
                   2432:     break;
                   2433: 
                   2434:   case EAP_MESSAGE:
                   2435:     if (!appconn->challen) {
                   2436:       log(LOG_INFO, "No EAP message found");
                   2437:       return dnprot_reject(appconn);
                   2438:     }
                   2439:     break;
                   2440: 
                   2441:   case CHAP_DIGEST_MD5:
                   2442:     appconn->policy = 0; /* TODO */
                   2443:     break;
                   2444: 
                   2445:   case CHAP_MICROSOFT:
                   2446:     if (!lmntattr) {
                   2447:       log(LOG_INFO, "No MPPE keys found");
                   2448:       return dnprot_reject(appconn);
                   2449:       }
                   2450:     if (!succattr) {
                   2451:       log_err(0, "No MS-CHAP2 success found");
                   2452:       return dnprot_reject(appconn);
                   2453:     }
                   2454:     break;
                   2455: 
                   2456:   case CHAP_MICROSOFT_V2:
                   2457:     if (!sendattr) {
                   2458:       log(LOG_INFO, "No MPPE sendkey found");
                   2459:       return dnprot_reject(appconn);
                   2460:     }
                   2461:     
                   2462:     if (!recvattr) {
                   2463:       log(LOG_INFO, "No MPPE recvkey found");
                   2464:       return dnprot_reject(appconn);
                   2465:     }
                   2466:     
                   2467:     break;
                   2468: 
                   2469:   default:
                   2470:     log_err(0, "Unknown authtype");
                   2471:     return dnprot_reject(appconn);
                   2472:   }
                   2473:   
                   2474:   return upprot_getip(appconn, hisip, statip);
                   2475: }
                   2476: 
                   2477: 
                   2478: /* Radius callback when coa or disconnect request has been received */
                   2479: int cb_radius_coa_ind(struct radius_t *radius, struct radius_packet_t *pack,
                   2480:                      struct sockaddr_in *peer) {
                   2481:   struct app_conn_t *appconn;
                   2482:   struct radius_attr_t *uattr = NULL;
                   2483:   struct radius_attr_t *sattr = NULL;
                   2484:   struct radius_packet_t radius_pack;
                   2485:   int found = 0;
                   2486:   int iscoa = 0;
                   2487: 
                   2488:   if (options.debug)
                   2489:     log_dbg("Received coa or disconnect request\n");
                   2490:   
                   2491:   if (pack->code != RADIUS_CODE_DISCONNECT_REQUEST &&
                   2492:       pack->code != RADIUS_CODE_COA_REQUEST) {
                   2493:     log_err(0, "Radius packet not supported: %d,\n", pack->code);
                   2494:     return -1;
                   2495:   }
                   2496: 
                   2497:   iscoa = pack->code == RADIUS_CODE_COA_REQUEST;
                   2498: 
                   2499:   /* Get username */
                   2500:   if (radius_getattr(pack, &uattr, RADIUS_ATTR_USER_NAME, 0, 0, 0)) {
                   2501:     log_warn(0, "Username must be included in disconnect request");
                   2502:     return -1;
                   2503:   }
                   2504: 
                   2505:   if (!radius_getattr(pack, &sattr, RADIUS_ATTR_ACCT_SESSION_ID, 0, 0, 0))
                   2506:     if (options.debug) 
                   2507:       log_dbg("Session-id present in disconnect. Only disconnecting that session\n");
                   2508: 
                   2509: 
                   2510:   if (options.debug)
                   2511:     log_dbg("Looking for session [username=%.*s,sessionid=%.*s]", 
                   2512:            uattr->l-2, uattr->v.t, sattr ? sattr->l-2 : 3, sattr ? (char*)sattr->v.t : "all");
                   2513:   
                   2514:   for (appconn = firstusedconn; appconn; appconn = appconn->next) {
                   2515:     if (!appconn->inuse) { log_err(0, "Connection with inuse == 0!"); }
                   2516: 
                   2517:     if ((appconn->s_state.authenticated) && 
                   2518:        (strlen(appconn->s_state.redir.username) == uattr->l-2 && 
                   2519:         !memcmp(appconn->s_state.redir.username, uattr->v.t, uattr->l-2)) &&
                   2520:        (!sattr || 
                   2521:         (strlen(appconn->s_state.sessionid) == sattr->l-2 && 
                   2522:          !strncasecmp(appconn->s_state.sessionid, (char*)sattr->v.t, sattr->l-2)))) {
                   2523: 
                   2524:       if (options.debug)
                   2525:        log_dbg("Found session\n");
                   2526: 
                   2527:       if (iscoa)
                   2528:        config_radius_session(&appconn->s_params, pack, 0);
                   2529:       else
                   2530:        terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_ADMIN_RESET);
                   2531: 
                   2532:       found = 1;
                   2533:     }
                   2534:   }
                   2535: 
                   2536:   if (found) {
                   2537:     if (radius_default_pack(radius, &radius_pack, 
                   2538:                            iscoa ? RADIUS_CODE_COA_ACK : RADIUS_CODE_DISCONNECT_ACK)) {
                   2539:       log_err(0, "radius_default_pack() failed");
                   2540:       return -1;
                   2541:     }
                   2542:   }
                   2543:   else {
                   2544:     if (radius_default_pack(radius, &radius_pack, 
                   2545:                            iscoa ? RADIUS_CODE_COA_NAK : RADIUS_CODE_DISCONNECT_NAK)) {
                   2546:       log_err(0, "radius_default_pack() failed");
                   2547:       return -1;
                   2548:     }
                   2549:   }
                   2550: 
                   2551:   radius_pack.id = pack->id;
                   2552:   (void) radius_coaresp(radius, &radius_pack, peer, pack->authenticator);
                   2553: 
                   2554:   return 0;
                   2555: }
                   2556: 
                   2557: 
                   2558: /***********************************************************
                   2559:  *
                   2560:  * dhcp callback functions
                   2561:  *
                   2562:  ***********************************************************/
                   2563: 
                   2564: /* DHCP callback for allocating new IP address */
                   2565: /* In the case of WPA it is allready allocated,
                   2566:  * for UAM address is allocated before authentication */
                   2567: int cb_dhcp_request(struct dhcp_conn_t *conn, struct in_addr *addr, 
                   2568:                    struct dhcp_fullpacket_t *dhcp_pkt, size_t dhcp_len) {
                   2569:   struct app_conn_t *appconn = conn->peer;
                   2570:   struct ippoolm_t *ipm;
                   2571: 
                   2572:   if (options.debug) 
                   2573:     log_dbg("DHCP request for IP address");
                   2574: 
                   2575:   if (!appconn) {
                   2576:     log_err(0, "Peer protocol not defined");
                   2577:     return -1;
                   2578:   }
                   2579: 
                   2580:   /* if uamanyip is on we have to filter out which ip's are allowed */
                   2581:   if (options.uamanyip && addr && addr->s_addr) {
                   2582:     if ((addr->s_addr & ipv4ll_mask.s_addr) == ipv4ll_ip.s_addr) {
                   2583:       /* clients with an IPv4LL ip normally have no default gw assigned, rendering uamanyip useless
                   2584:       They must rather get a proper dynamic ip via dhcp */
                   2585:       log_dbg("IPv4LL/APIPA address requested, ignoring");
                   2586:       return -1;
                   2587:     }
                   2588:   }
                   2589: 
                   2590:   appconn->reqip.s_addr = addr->s_addr; /* Save for MAC auth later */
                   2591: 
                   2592:   if (appconn->uplink) {
                   2593: 
                   2594:     /*
                   2595:      *  IP Address is already known and allocated.
                   2596:      */
                   2597:     ipm = (struct ippoolm_t*) appconn->uplink;
                   2598: 
                   2599:   } else if ((options.macoklen) && 
                   2600:             (appconn->dnprot == DNPROT_DHCP_NONE) &&
                   2601:             !maccmp(conn->hismac)) {
                   2602:     
                   2603:     /*
                   2604:      *  When using macallowed option, and hismac matches.
                   2605:      */
                   2606:     appconn->dnprot = DNPROT_MAC;
                   2607: 
                   2608:     if (options.macallowlocal) {
                   2609: 
                   2610:       /*
                   2611:        *  Local MAC allowed list, authenticate without RADIUS.
                   2612:        */
                   2613:       upprot_getip(appconn, &appconn->reqip, 0);/**/
                   2614:       dnprot_accept(appconn);
                   2615:       log_info("Granted MAC=%.2X-%.2X-%.2X-%.2X-%.2X-%.2X with IP=%s access without radius auth" ,
                   2616:                     conn->hismac[0], conn->hismac[1],
                   2617:                     conn->hismac[2], conn->hismac[3],
                   2618:                     conn->hismac[4], conn->hismac[5],
                   2619:                     inet_ntoa(appconn->hisip));
                   2620:     } else {
                   2621: 
                   2622:       /*
                   2623:        *  Otherwise, authenticate with RADIUS.
                   2624:        */
                   2625:       macauth_radius(appconn, dhcp_pkt, dhcp_len);
                   2626:     }
                   2627: 
                   2628:     return -1;
                   2629: 
                   2630:   } else if ((options.macauth) && 
                   2631:             (appconn->dnprot == DNPROT_DHCP_NONE)) {
                   2632:     
                   2633:     /*
                   2634:      *  Using macauth option to authenticate via RADIUS.
                   2635:      */
                   2636:     appconn->dnprot = DNPROT_MAC;
                   2637: 
                   2638:     macauth_radius(appconn, dhcp_pkt, dhcp_len);
                   2639: 
                   2640:     return -1;
                   2641: 
                   2642:   } else {
                   2643: 
                   2644:     if (appconn->dnprot != DNPROT_DHCP_NONE) {
                   2645:       log_warn(0, "Requested IP address when already allocated");
                   2646:     }
                   2647:     
                   2648:     /* Allocate dynamic IP address */
                   2649:     /*XXX    if (ippool_newip(ippool, &ipm, &appconn->reqip, 0)) {*/
                   2650:     if (newip(&ipm, &appconn->reqip)) {
                   2651:       log_err(0, "Failed allocate dynamic IP address");
                   2652:       return -1;
                   2653:     }
                   2654: 
                   2655:     appconn->hisip.s_addr = ipm->addr.s_addr;
                   2656:     
                   2657:     log(LOG_NOTICE, "Client MAC=%.2X-%.2X-%.2X-%.2X-%.2X-%.2X assigned IP %s" , 
                   2658:        conn->hismac[0], conn->hismac[1], 
                   2659:        conn->hismac[2], conn->hismac[3],
                   2660:        conn->hismac[4], conn->hismac[5], 
                   2661:        inet_ntoa(appconn->hisip));
                   2662: 
                   2663:     /* TODO: Too many "listen" and "our" addresses hanging around */
                   2664:     appconn->ourip.s_addr = options.dhcplisten.s_addr;
                   2665:     
                   2666:     appconn->uplink =  ipm;
                   2667:     ipm->peer   = appconn; 
                   2668:   }
                   2669:   
                   2670:   dhcp_set_addrs(conn, 
                   2671:                 &ipm->addr, &options.mask, 
                   2672:                 &appconn->ourip, &appconn->mask,
                   2673:                 &options.dns1, &options.dns2, 
                   2674:                 options.domain);
                   2675: 
                   2676:   /* if not already authenticated, ensure DNAT authstate */
                   2677:   if (!appconn->s_state.authenticated)
                   2678:     conn->authstate = DHCP_AUTH_DNAT;
                   2679: 
                   2680:   /* If IP was requested before authentication it was UAM */
                   2681:   if (appconn->dnprot == DNPROT_DHCP_NONE)
                   2682:     appconn->dnprot = DNPROT_UAM;
                   2683: 
                   2684:   return 0;
                   2685: }
                   2686: 
                   2687: /* DHCP callback for establishing new connection */
                   2688: int cb_dhcp_connect(struct dhcp_conn_t *conn) {
                   2689:   struct app_conn_t *appconn;
                   2690: 
                   2691:   log(LOG_NOTICE, "New DHCP request from MAC=%.2X-%.2X-%.2X-%.2X-%.2X-%.2X" , 
                   2692:       conn->hismac[0], conn->hismac[1], 
                   2693:       conn->hismac[2], conn->hismac[3],
                   2694:       conn->hismac[4], conn->hismac[5]);
                   2695:   
                   2696:   if (options.debug) 
                   2697:     log_dbg("New DHCP connection established");
                   2698: 
                   2699:   /* Allocate new application connection */
                   2700:   if (newconn(&appconn)) {
                   2701:     log_err(0, "Failed to allocate connection");
                   2702:     return 0;
                   2703:   }
                   2704: 
                   2705:   appconn->dnlink =  conn;
                   2706:   appconn->dnprot =  DNPROT_DHCP_NONE;
                   2707:   conn->peer = appconn;
                   2708: 
                   2709:   appconn->net.s_addr = options.net.s_addr;
                   2710:   appconn->mask.s_addr = options.mask.s_addr;
                   2711:   appconn->dns1.s_addr = options.dns1.s_addr;
                   2712:   appconn->dns2.s_addr = options.dns2.s_addr;
                   2713: 
                   2714:   memcpy(appconn->hismac, conn->hismac, PKT_ETH_ALEN);
                   2715:   memcpy(appconn->ourmac, conn->ourmac, PKT_ETH_ALEN);
                   2716:   
                   2717:   set_sessionid(appconn);
                   2718: 
                   2719:   conn->authstate = DHCP_AUTH_NONE; /* TODO: Not yet authenticated */
                   2720: 
                   2721:   return 0;
                   2722: }
                   2723: 
                   2724: int cb_dhcp_getinfo(struct dhcp_conn_t *conn, bstring b, int fmt) {
                   2725:   time_t timenow = mainclock;
                   2726:   struct app_conn_t *appconn;
                   2727:   uint32_t sessiontime = 0;
                   2728:   uint32_t idletime = 0;
                   2729: 
                   2730:   if (!conn->peer) return 2;
                   2731:   appconn = (struct app_conn_t*) conn->peer;
                   2732:   if (!appconn->inuse) return 2;
                   2733: 
                   2734:   if (appconn->s_state.authenticated) {
                   2735:     sessiontime = timenow - appconn->s_state.start_time;
                   2736:     idletime    = timenow - appconn->s_state.last_time;
                   2737:   }
                   2738: 
                   2739:   switch(fmt) {
                   2740:   case LIST_JSON_FMT:
                   2741:     if (appconn->s_state.authenticated)
                   2742:       session_json_fmt(&appconn->s_state, &appconn->s_params, b, 0);
                   2743:     break;
                   2744:   default:
                   2745:     {
                   2746:       bstring tmp = bfromcstr("");
                   2747:       bassignformat(tmp, " %.*s %d %.*s %d/%d %d/%d %.*s", 
                   2748:                    appconn->s_state.sessionid[0] ? strlen(appconn->s_state.sessionid) : 1,
                   2749:                    appconn->s_state.sessionid[0] ? appconn->s_state.sessionid : "-",
                   2750:                    appconn->s_state.authenticated,
                   2751:                    appconn->s_state.redir.username[0] ? strlen(appconn->s_state.redir.username) : 1,
                   2752:                    appconn->s_state.redir.username[0] ? appconn->s_state.redir.username : "-",
                   2753:                    sessiontime, (int)appconn->s_params.sessiontimeout,
                   2754:                    idletime, (int)appconn->s_params.idletimeout,
                   2755:                    appconn->s_state.redir.userurl[0] ? strlen(appconn->s_state.redir.userurl) : 1,
                   2756:                    appconn->s_state.redir.userurl[0] ? appconn->s_state.redir.userurl : "-");
                   2757:       bconcat(b, tmp);
                   2758:       bdestroy(tmp);
                   2759:     }
                   2760:   }
                   2761:   return 0;
                   2762: }
                   2763: 
                   2764: int terminate_appconn(struct app_conn_t *appconn, int terminate_cause) {
                   2765:   if (appconn->s_state.authenticated == 1) { /* Only send accounting if logged in */
                   2766:     dnprot_terminate(appconn);
                   2767:     appconn->s_state.terminate_cause = terminate_cause;
                   2768:     acct_req(appconn, RADIUS_STATUS_TYPE_STOP);
                   2769: 
                   2770:     /* should memory be cleared here?? */
                   2771:     memset(&appconn->s_params, 0, sizeof(appconn->s_params));
                   2772:     set_sessionid(appconn);
                   2773:   }
                   2774:   return 0;
                   2775: }
                   2776: 
                   2777: /* Callback when a dhcp connection is deleted */
                   2778: int cb_dhcp_disconnect(struct dhcp_conn_t *conn, int term_cause) {
                   2779:   struct app_conn_t *appconn;
                   2780: 
                   2781:   log(LOG_INFO, "DHCP addr released by MAC=%.2X-%.2X-%.2X-%.2X-%.2X-%.2X IP=%s", 
                   2782:       conn->hismac[0], conn->hismac[1], 
                   2783:       conn->hismac[2], conn->hismac[3],
                   2784:       conn->hismac[4], conn->hismac[5], 
                   2785:       inet_ntoa(conn->hisip));
                   2786:   
                   2787:   if (options.debug) log_dbg("DHCP connection removed");
                   2788: 
                   2789:   if (!conn->peer) return 0; /* No appconn allocated. Stop here */
                   2790:   appconn = (struct app_conn_t*) conn->peer;
                   2791: 
                   2792:   if ((appconn->dnprot != DNPROT_DHCP_NONE) &&
                   2793:       (appconn->dnprot != DNPROT_UAM) &&
                   2794:       (appconn->dnprot != DNPROT_MAC) &&
                   2795:       (appconn->dnprot != DNPROT_WPA) &&
                   2796:       (appconn->dnprot != DNPROT_EAPOL))  {
                   2797:     return 0; /* DNPROT_WPA and DNPROT_EAPOL are unaffected by dhcp release? */
                   2798:   }
                   2799: 
                   2800:   terminate_appconn(appconn, 
                   2801:                    term_cause ? term_cause : 
                   2802:                    appconn->s_state.terminate_cause ? 
                   2803:                    appconn->s_state.terminate_cause :
                   2804:                    RADIUS_TERMINATE_CAUSE_LOST_CARRIER);
                   2805: 
                   2806:   /* ALPAPAD */
                   2807:   if (appconn->uplink) {
                   2808:     if (options.uamanyip) {
                   2809:       struct ippoolm_t *member = (struct ippoolm_t *) appconn->uplink;
                   2810:       if (member->inuse  == 2) {
                   2811:        struct in_addr mask;
                   2812:        mask.s_addr = 0xffffffff;
                   2813:        log_dbg("Removing route: %s %d\n", inet_ntoa(member->addr),
                   2814:                net_del_route(&member->addr, &appconn->ourip, &mask));
                   2815:       }
                   2816:     }
                   2817:     if (ippool_freeip(ippool, (struct ippoolm_t *) appconn->uplink)) {
                   2818:       log_err(0, "ippool_freeip() failed!");
                   2819:     }
                   2820:   }
                   2821:   
                   2822:   freeconn(appconn);
                   2823: 
                   2824:   return 0;
                   2825: }
                   2826: 
                   2827: 
                   2828: /* Callback for receiving messages from dhcp */
                   2829: int cb_dhcp_data_ind(struct dhcp_conn_t *conn, void *pack, size_t len) {
                   2830:   struct app_conn_t *appconn = conn->peer;
                   2831:   /*struct dhcp_ethhdr_t *ethh = (struct dhcp_ethhdr_t *)pack;*/
                   2832:   struct pkt_ipphdr_t *ipph = (struct pkt_ipphdr_t *)((char*)pack + PKT_ETH_HLEN);
                   2833: 
                   2834:   /*if (options.debug)
                   2835:     log_dbg("cb_dhcp_data_ind. Packet received. DHCP authstate: %d\n", 
                   2836:     conn->authstate);*/
                   2837: 
                   2838:   if (ipph->saddr != conn->hisip.s_addr) {
                   2839:     if (options.debug) 
                   2840:       log_dbg("Received packet with spoofed source!");
                   2841:     return 0;
                   2842:   }
                   2843: 
                   2844:   if (!appconn) {
                   2845:     log_err(0, "No peer protocol defined");
                   2846:     return -1;
                   2847:   }
                   2848: 
                   2849:   switch (appconn->dnprot) {
                   2850:   case DNPROT_NULL:
                   2851:   case DNPROT_DHCP_NONE:
                   2852:     return -1;
                   2853: 
                   2854:   case DNPROT_UAM:
                   2855:   case DNPROT_WPA:
                   2856:   case DNPROT_MAC:
                   2857:   case DNPROT_EAPOL:
                   2858:     break;
                   2859: 
                   2860:   default:
                   2861:     log_err(0, "Unknown downlink protocol: %d", appconn->dnprot);
                   2862:     break;
                   2863:   }
                   2864: 
                   2865:   /* If the ip dst is uamlisten and pdst is uamport we won't call leaky_bucket,
                   2866:   *  and we always send these packets through to the tun/tap interface (index 0) 
                   2867:   */
                   2868:   if (ipph->daddr  == options.uamlisten.s_addr && 
                   2869:       (ipph->dport == htons(options.uamport) ||
                   2870:        ipph->dport == htons(options.uamuiport)))
                   2871:     return tun_encaps(tun, pack, len, 0);
                   2872:   
                   2873:   if (appconn->s_state.authenticated == 1) {
                   2874: 
                   2875: #ifndef LEAKY_BUCKET
                   2876:     appconn->s_state.last_time = mainclock;
                   2877: #endif
                   2878: 
                   2879: #ifdef LEAKY_BUCKET
                   2880: #ifndef COUNT_UPLINK_DROP
                   2881:     if (leaky_bucket(appconn, len, 0)) return 0;
                   2882: #endif
                   2883: #endif
                   2884:     if (options.swapoctets) {
                   2885:       appconn->s_state.input_packets++;
                   2886:       appconn->s_state.input_octets +=len;
                   2887:       if (admin_session.s_state.authenticated) {
                   2888:        admin_session.s_state.input_packets++;
                   2889:        admin_session.s_state.input_octets+=len;
                   2890:       }
                   2891:     } else {
                   2892:       appconn->s_state.output_packets++;
                   2893:       appconn->s_state.output_octets +=len;
                   2894:       if (admin_session.s_state.authenticated) {
                   2895:        admin_session.s_state.output_packets++;
                   2896:        admin_session.s_state.output_octets+=len;
                   2897:       }
                   2898:     }
                   2899: #ifdef LEAKY_BUCKET
                   2900: #ifdef COUNT_UPLINK_DROP
                   2901:     if (leaky_bucket(appconn, len, 0)) return 0;
                   2902: #endif
                   2903: #endif
                   2904:   }
                   2905: 
                   2906:   return tun_encaps(tun, pack, len, appconn->s_params.routeidx);
                   2907: }
                   2908: 
                   2909: /* Callback for receiving messages from eapol */
                   2910: int cb_dhcp_eap_ind(struct dhcp_conn_t *conn, void *pack, size_t len) {
                   2911:   struct eap_packet_t *eap = (struct eap_packet_t *)pack;
                   2912:   struct app_conn_t *appconn = conn->peer;
                   2913:   struct radius_packet_t radius_pack;
                   2914:   char mac[MACSTRLEN+1];
                   2915:   size_t offset;
                   2916: 
                   2917:   if (options.debug) log_dbg("EAP Packet received");
                   2918: 
                   2919:   /* If this is the first EAPOL authentication request */
                   2920:   if ((appconn->dnprot == DNPROT_DHCP_NONE) || 
                   2921:       (appconn->dnprot == DNPROT_EAPOL)) {
                   2922:     if ((eap->code == 2) && /* Response */
                   2923:        (eap->type == 1) && /* Identity */
                   2924:        (len > 5) &&        /* Must be at least 5 octets */
                   2925:        ((len - 5) <= USERNAMESIZE )) {
                   2926:       memcpy(appconn->s_state.redir.username, eap->payload, len - 5); 
                   2927:       appconn->dnprot = DNPROT_EAPOL;
                   2928:       appconn->authtype = EAP_MESSAGE;
                   2929:     }
                   2930:     else if (appconn->dnprot == DNPROT_DHCP_NONE) {
                   2931:       log_err(0, "Initial EAP response was not a valid identity response!");
                   2932:       return 0;
                   2933:     }
                   2934:   }
                   2935: 
                   2936:   /* Return if not EAPOL */
                   2937:   if (appconn->dnprot != DNPROT_EAPOL) {
                   2938:     log_warn(0, "Received EAP message, processing for authentication");
                   2939:     appconn->dnprot = DNPROT_EAPOL;
                   2940:     return 0;
                   2941:   }
                   2942:   
                   2943:   if (radius_default_pack(radius, &radius_pack, RADIUS_CODE_ACCESS_REQUEST)) {
                   2944:     log_err(0, "radius_default_pack() failed");
                   2945:     return -1;
                   2946:   }
                   2947: 
                   2948:   /* Build up radius request */
                   2949:   radius_pack.code = RADIUS_CODE_ACCESS_REQUEST;
                   2950: 
                   2951:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_NAME, 0, 0, 0,
                   2952:                        (uint8_t*) appconn->s_state.redir.username, 
                   2953:                        strlen(appconn->s_state.redir.username));
                   2954: 
                   2955:   if (appconn->s_state.redir.statelen) {
                   2956:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_STATE, 0, 0, 0,
                   2957:                   appconn->s_state.redir.statebuf,
                   2958:                   appconn->s_state.redir.statelen);
                   2959:   }
                   2960:   
                   2961:   /* Include EAP (if present) */
                   2962:   offset = 0;
                   2963:   while (offset < len) {
                   2964:     size_t eaplen;
                   2965: 
                   2966:     if ((len - offset) > RADIUS_ATTR_VLEN)
                   2967:       eaplen = RADIUS_ATTR_VLEN;
                   2968:     else
                   2969:       eaplen = len - offset;
                   2970: 
                   2971:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_EAP_MESSAGE, 0, 0, 0,
                   2972:                   pack + offset, eaplen);
                   2973: 
                   2974:     offset += eaplen;
                   2975:   } 
                   2976:   
                   2977:   if (len)
                   2978:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, 
                   2979:                   0, 0, 0, NULL, RADIUS_MD5LEN);
                   2980:   
                   2981:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT_TYPE, 0, 0,
                   2982:                 options.radiusnasporttype, NULL, 0);
                   2983:   
                   2984:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_PORT, 0, 0,
                   2985:                 appconn->unit, NULL, 0);
                   2986:   
                   2987:   radius_addnasip(radius, &radius_pack);
                   2988: 
                   2989:   snprintf(mac, MACSTRLEN+1, "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",
                   2990:           appconn->hismac[0], appconn->hismac[1],
                   2991:           appconn->hismac[2], appconn->hismac[3],
                   2992:           appconn->hismac[4], appconn->hismac[5]);
                   2993:   
                   2994:   radius_addattr(radius, &radius_pack, RADIUS_ATTR_CALLING_STATION_ID, 0, 0, 0,
                   2995:                 (uint8_t*) mac, MACSTRLEN);
                   2996:   
                   2997:   radius_addcalledstation(radius, &radius_pack);
                   2998:   
                   2999:   /* Include NAS-Identifier if given in configuration options */
                   3000:   if (options.radiusnasid)
                   3001:     radius_addattr(radius, &radius_pack, RADIUS_ATTR_NAS_IDENTIFIER, 0, 0, 0,
                   3002:                   (uint8_t*) options.radiusnasid,
                   3003:                   strlen(options.radiusnasid));
                   3004:   
                   3005:   return radius_req(radius, &radius_pack, appconn);
                   3006: }
                   3007: 
                   3008: 
                   3009: /***********************************************************
                   3010:  *
                   3011:  * uam message handling functions
                   3012:  *
                   3013:  ***********************************************************/
                   3014: 
                   3015: int static uam_msg(struct redir_msg_t *msg) {
                   3016: 
                   3017:   struct ippoolm_t *ipm;
                   3018:   struct app_conn_t *appconn = NULL;
                   3019:   struct dhcp_conn_t* dhcpconn;
                   3020: 
                   3021:   if (ippool_getip(ippool, &ipm, &msg->mdata.addr)) {
                   3022:     if (options.debug) 
                   3023:       log_dbg("UAM login with unknown IP address: %s", inet_ntoa(msg->mdata.addr));
                   3024:     return 0;
                   3025:   }
                   3026: 
                   3027:   if ((appconn  = (struct app_conn_t *)ipm->peer)        == NULL || 
                   3028:       (dhcpconn = (struct dhcp_conn_t *)appconn->dnlink) == NULL) {
                   3029:     log_err(0, "No peer protocol defined");
                   3030:     return 0;
                   3031:   }
                   3032: 
                   3033:   if (msg->mdata.opt & REDIR_MSG_OPT_REDIR)
                   3034:     memcpy(&appconn->s_state.redir, &msg->mdata.redir, sizeof(msg->mdata.redir));
                   3035: 
                   3036:   if (msg->mdata.opt & REDIR_MSG_OPT_PARAMS)
                   3037:     memcpy(&appconn->s_params, &msg->mdata.params, sizeof(msg->mdata.params));
                   3038: 
                   3039:   switch(msg->mtype) {
                   3040: 
                   3041:   case REDIR_LOGIN:
                   3042:     if (appconn->uamabort) {
                   3043:       log_info("UAM login from username=%s IP=%s was aborted!", 
                   3044:               msg->mdata.redir.username, inet_ntoa(appconn->hisip));
                   3045:       appconn->uamabort = 0;
                   3046:       return 0;
                   3047:     }
                   3048: 
                   3049:     log_info("Successful UAM login from username=%s IP=%s", 
                   3050:             msg->mdata.redir.username, inet_ntoa(appconn->hisip));
                   3051:     
                   3052:     /* Initialise */
                   3053:     appconn->s_params.routeidx = tun->routeidx;
                   3054:     appconn->s_state.redir.statelen = 0;
                   3055:     appconn->challen  = 0;
                   3056:     appconn->sendlen  = 0;
                   3057:     appconn->recvlen  = 0;
                   3058:     appconn->lmntlen  = 0;
                   3059:     
                   3060:     memcpy(appconn->hismac, dhcpconn->hismac, PKT_ETH_ALEN);
                   3061:     memcpy(appconn->ourmac, dhcpconn->ourmac, PKT_ETH_ALEN);
                   3062:     
                   3063:     appconn->policy = 0; /* TODO */
                   3064: 
                   3065: #ifdef LEAKY_BUCKET
                   3066: #ifdef BUCKET_SIZE
                   3067:     appconn->s_state.bucketupsize = BUCKET_SIZE;
                   3068: #else
                   3069:     appconn->s_state.bucketupsize = appconn->s_params.bandwidthmaxup / 8000 * BUCKET_TIME;
                   3070:     if (appconn->s_state.bucketupsize < BUCKET_SIZE_MIN) 
                   3071:       appconn->s_state.bucketupsize = BUCKET_SIZE_MIN;
                   3072: #endif
                   3073: #endif
                   3074: 
                   3075: #ifdef LEAKY_BUCKET
                   3076: #ifdef BUCKET_SIZE
                   3077:     appconn->s_state.bucketdownsize = BUCKET_SIZE;
                   3078: #else
                   3079:     appconn->s_state.bucketdownsize = appconn->s_params.bandwidthmaxdown / 8000 * BUCKET_TIME;
                   3080:     if (appconn->s_state.bucketdownsize < BUCKET_SIZE_MIN) 
                   3081:       appconn->s_state.bucketdownsize = BUCKET_SIZE_MIN;
                   3082: #endif
                   3083: #endif
                   3084: 
                   3085:     return upprot_getip(appconn, NULL, 0);
                   3086: 
                   3087:   case REDIR_LOGOUT:
                   3088: 
                   3089:     log_info("Received UAM logoff from username=%s IP=%s",
                   3090:             appconn->s_state.redir.username, inet_ntoa(appconn->hisip));
                   3091: 
                   3092:     if (options.debug)
                   3093:       log_dbg("Received logoff from UAM\n");
                   3094: 
                   3095:     if (appconn->s_state.authenticated == 1) {
                   3096:       terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_USER_REQUEST);
                   3097:       appconn->s_state.uamtime = 0;
                   3098:       appconn->s_params.sessiontimeout = 0;
                   3099:       appconn->s_params.idletimeout = 0;
                   3100:     }
                   3101: 
                   3102:     appconn->s_state.uamtime = mainclock;
                   3103:     dhcpconn->authstate = DHCP_AUTH_DNAT;
                   3104:     appconn->uamabort = 0;
                   3105: 
                   3106:     break;
                   3107: 
                   3108:   case REDIR_ABORT:
                   3109:     
                   3110:     log_info("Received UAM abort from IP=%s", inet_ntoa(appconn->hisip));
                   3111: 
                   3112:     appconn->uamabort = 1; /* Next login will be aborted */
                   3113:     appconn->s_state.uamtime = 0;  /* Force generation of new challenge */
                   3114:     dhcpconn->authstate = DHCP_AUTH_DNAT;
                   3115: 
                   3116:     terminate_appconn(appconn, RADIUS_TERMINATE_CAUSE_USER_REQUEST);
                   3117: 
                   3118:     break;
                   3119: 
                   3120:   case REDIR_CHALLENGE:
                   3121:     appconn->s_state.uamtime = mainclock;
                   3122:     appconn->uamabort = 0;
                   3123:     break;
                   3124: 
                   3125:   case REDIR_NOTYET:
                   3126:     break;
                   3127:   }
                   3128: 
                   3129:   return 0;
                   3130: }
                   3131: 
                   3132: static int cmdsock_accept(int sock) {
                   3133:   struct sockaddr_un remote; 
                   3134:   struct cmdsock_request req;
                   3135: 
                   3136:   bstring s = 0;
                   3137:   size_t len;
                   3138:   int csock;
                   3139:   int rval = 0;
                   3140: 
                   3141:   if (options.debug) 
                   3142:     log_dbg("Processing cmdsock request...\n");
                   3143: 
                   3144:   len = sizeof(remote);
                   3145:   if ((csock = accept(sock, (struct sockaddr *)&remote, &len)) == -1) {
                   3146:     perror("cmdsock_accept()/accept()");
                   3147:     return -1;
                   3148:   }
                   3149: 
                   3150:   if (read(csock, &req, sizeof(req)) != sizeof(req)) {
                   3151:     perror("cmdsock_accept()/read()");
                   3152:     close(csock);
                   3153:     return -1;
                   3154:   }
                   3155: 
                   3156:   switch(req.type) {
                   3157: 
                   3158:   case CMDSOCK_DHCP_LIST:
                   3159:     s = bfromcstr("");
                   3160:     if (dhcp) dhcp_list(dhcp, s, 0, 0,
                   3161:                        req.options & CMDSOCK_OPT_JSON ? 
                   3162:                        LIST_JSON_FMT : LIST_SHORT_FMT);
                   3163:     write(csock, s->data, s->slen);
                   3164:     break;
                   3165:     
                   3166:   case CMDSOCK_DHCP_DROP:
                   3167:   case CMDSOCK_DHCP_RELEASE:
                   3168:     if (dhcp) dhcp_release_mac(dhcp, req.data.mac, RADIUS_TERMINATE_CAUSE_ADMIN_RESET);
                   3169:     break;
                   3170: 
                   3171:   case CMDSOCK_LIST:
                   3172:     s = bfromcstr("");
                   3173:     if (dhcp) dhcp_list(dhcp, s, 0, 0,
                   3174:                        req.options & CMDSOCK_OPT_JSON ? 
                   3175:                        LIST_JSON_FMT : LIST_LONG_FMT);
                   3176:     write(csock, s->data, s->slen);
                   3177:     break;
                   3178: 
                   3179:   case CMDSOCK_SHOW:
                   3180:     /*ToDo*/
                   3181:     break;
                   3182: 
                   3183:   case CMDSOCK_ROUTE_SET:
                   3184:     {
                   3185:       struct dhcp_conn_t *conn = dhcp->firstusedconn;
                   3186:       log_dbg("looking to authorized session %s",inet_ntoa(req.data.sess.ip));
                   3187:       while (conn && conn->inuse) {
                   3188:        if (conn->peer) {
                   3189:          struct app_conn_t * appconn = (struct app_conn_t*)conn->peer;
                   3190:          if (!memcmp(appconn->hismac, req.data.mac, 6)) {
                   3191:            log_dbg("routeidx %s %d",appconn->s_state.sessionid, req.data.sess.params.routeidx);
                   3192:            appconn->s_params.routeidx = req.data.sess.params.routeidx;
                   3193:            break;
                   3194:          }
                   3195:        }
                   3196:        conn = conn->next;
                   3197:       }
                   3198:     }
                   3199:     /* drop through */
                   3200:   case CMDSOCK_ROUTE:
                   3201:     {
                   3202:       int i;
                   3203:       bstring b = bfromcstr("routes:\n");
                   3204:       write(csock, b->data, b->slen);
                   3205:       for (i=0; i<tun->_interface_count; i++) {
                   3206:        bassignformat(b, "idx: %d dev: %s%s\n", 
                   3207:                      i, tun->_interfaces[i].devname,
                   3208:                      i == 0 ? " (tun/tap)":"");
                   3209:        write(csock, b->data, b->slen);
                   3210:       }
                   3211: 
                   3212:       { 
                   3213:        struct dhcp_conn_t *conn = dhcp->firstusedconn;
                   3214:        bassignformat(b, "subscribers:\n");
                   3215:        write(csock, b->data, b->slen);
                   3216:        while (conn) {
                   3217:          struct app_conn_t *appconn = (struct app_conn_t *)conn->peer;
                   3218:          bassignformat(b, "mac: %.2X-%.2X-%.2X-%.2X-%.2X-%.2X -> idx: %d\n", 
                   3219:                        appconn->hismac[0], appconn->hismac[1],
                   3220:                        appconn->hismac[2], appconn->hismac[3],
                   3221:                        appconn->hismac[4], appconn->hismac[5],
                   3222:                        appconn->s_params.routeidx);
                   3223:          write(csock, b->data, b->slen);
                   3224:          conn = conn->next;
                   3225:        }
                   3226:       }
                   3227:       bdestroy(b);
                   3228:     }
                   3229:     break;
                   3230: 
                   3231:   case CMDSOCK_AUTHORIZE:
                   3232:     if (dhcp) {
                   3233:       struct dhcp_conn_t *dhcpconn = dhcp->firstusedconn;
                   3234:       log_dbg("looking to authorized session %s",inet_ntoa(req.data.sess.ip));
                   3235:       while (dhcpconn && dhcpconn->inuse) {
                   3236:        if (dhcpconn->peer) {
                   3237:          struct app_conn_t * appconn = (struct app_conn_t*) dhcpconn->peer;
                   3238:          if (  (req.data.sess.ip.s_addr == 0    || appconn->hisip.s_addr == req.data.sess.ip.s_addr) &&
                   3239:                (req.data.sess.sessionid[0] == 0 || !strcmp(appconn->s_state.sessionid,req.data.sess.sessionid))
                   3240:                ){
                   3241:            char *uname = req.data.sess.username;
                   3242:            log_dbg("remotely authorized session %s",appconn->s_state.sessionid);
                   3243:            memcpy(&appconn->s_params, &req.data.sess.params, sizeof(req.data.sess.params));
                   3244:            if (uname[0]) strncpy(appconn->s_state.redir.username, uname, USERNAMESIZE);
                   3245:            dnprot_accept(appconn);
                   3246:            break;
                   3247:          }
                   3248:        }
                   3249:        dhcpconn = dhcpconn->next;
                   3250:       }
                   3251:     }
                   3252:     break;
                   3253: 
                   3254:   default:
                   3255:     perror("unknown command");
                   3256:     close(csock);
                   3257:     rval = -1;
                   3258:   }
                   3259: 
                   3260:   if (s) bdestroy(s);
                   3261:   shutdown(csock, 2);
                   3262:   close(csock);
                   3263: 
                   3264:   return rval;
                   3265: }
                   3266: 
                   3267: /* Function that will create and write a status file in statedir*/
                   3268: int printstatus(struct app_conn_t *appconn) {
                   3269:   char *statedir = options.statedir ? options.statedir : DEFSTATEDIR;
                   3270:   struct app_conn_t *apptemp;
                   3271:   FILE *file;
                   3272:   char filedest[512];
                   3273:   time_t timenow = mainclock;
                   3274:   struct stat statbuf;
                   3275: 
                   3276:   if (!options.usestatusfile) 
                   3277:     return 0;
                   3278: 
                   3279:   if (strlen(statedir)>sizeof(filedest)-1) 
                   3280:     return -1;
                   3281: 
                   3282:   if (stat(statedir, &statbuf)) { 
                   3283:     log_err(errno, "statedir (%s) does not exist", statedir); 
                   3284:     return -1; 
                   3285:   }
                   3286: 
                   3287:   if (!S_ISDIR(statbuf.st_mode)) { 
                   3288:     log_err(0, "statedir (%s) not a directory", statedir); 
                   3289:     return -1; 
                   3290:   }
                   3291: 
                   3292:   strcpy(filedest, statedir);
                   3293:   strcat(filedest, "/chillispot.state");
                   3294: 
                   3295:   file = fopen(filedest, "w");
                   3296:   if (!file) { log_err(errno, "could not open file %s", filedest); return -1; }
                   3297:   fprintf(file, "#Version:1.1\n");
                   3298:   fprintf(file, "#SessionID = SID\n#Start-Time = ST\n");
                   3299:   fprintf(file, "#SessionTimeOut = STO\n#SessionTerminateTime = STT\n");
                   3300:   fprintf(file, "#Timestamp: %d\n", timenow);
                   3301:   fprintf(file, "#User, IP, MAC, SID, ST, STO, STT\n");
                   3302:   if(appconn == NULL)
                   3303:   {
                   3304:     fclose(file);
                   3305:     return 0;
                   3306:   }
                   3307:   apptemp = appconn;
                   3308:   while(apptemp != NULL)
                   3309:   {
                   3310:     if(apptemp->s_state.authenticated==1)
                   3311:     {
                   3312:       fprintf(file, "%s, %s, %.2X-%.2X-%.2X-%.2X-%.2X-%.2X, %s, %d, %d, %d\n",
                   3313:        apptemp->s_state.redir.username,
                   3314:        inet_ntoa(apptemp->hisip),
                   3315:        apptemp->hismac[0], apptemp->hismac[1],
                   3316:        apptemp->hismac[2], apptemp->hismac[3],
                   3317:        apptemp->hismac[4], apptemp->hismac[5],
                   3318:        apptemp->s_state.sessionid,
                   3319:        apptemp->s_state.start_time,
                   3320:        apptemp->s_params.sessiontimeout,
                   3321:        apptemp->s_params.sessionterminatetime);
                   3322:     }
                   3323:     apptemp = apptemp->prev;
                   3324:   }
                   3325:   apptemp = appconn->next;
                   3326:   while(apptemp != NULL)
                   3327:   {
                   3328:     if(apptemp->s_state.authenticated==1)
                   3329:     {
                   3330:       fprintf(file, "%s, %s, %.2X-%.2X-%.2X-%.2X-%.2X-%.2X, %s, %d, %d, %d\n",
                   3331:        apptemp->s_state.redir.username,
                   3332:        inet_ntoa(apptemp->hisip),
                   3333:        apptemp->hismac[0], apptemp->hismac[1],
                   3334:        apptemp->hismac[2], apptemp->hismac[3],
                   3335:        apptemp->hismac[4], apptemp->hismac[5],
                   3336:        apptemp->s_state.sessionid,
                   3337:         apptemp->s_state.start_time,
                   3338:        apptemp->s_params.sessiontimeout,
                   3339:        apptemp->s_params.sessionterminatetime);
                   3340:     }
                   3341:     apptemp = apptemp->next;
                   3342:   }
                   3343:   fclose(file);
                   3344:   return 0;
                   3345: }
                   3346: 
                   3347: static void fixup_options() {
                   3348:   /*
                   3349:    * If we have no nasmac configured, lets default it here, after creating the dhcp
                   3350:    */
                   3351:   if (!options.nasmac) {
                   3352:     char mac[24];
                   3353: 
                   3354:     sprintf(mac, "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X", 
                   3355:            dhcp->ipif.hwaddr[0],dhcp->ipif.hwaddr[1],dhcp->ipif.hwaddr[2],
                   3356:            dhcp->ipif.hwaddr[3],dhcp->ipif.hwaddr[4],dhcp->ipif.hwaddr[5]);
                   3357:     
                   3358:     options.nasmac = strdup(mac);
                   3359:   }
                   3360: 
                   3361: }
                   3362: 
                   3363: int chilli_main(int argc, char **argv) {
                   3364:   
                   3365:   int maxfd = 0;               /* For select() */
                   3366:   fd_set fds;                  /* For select() */
                   3367:   struct timeval idleTime;     /* How long to select() */
                   3368:   int status;
                   3369:   int msgresult;
                   3370: 
                   3371:   struct redir_msg_t msg;
                   3372:   struct sigaction act;
                   3373:   /*  struct itimerval itval; */
                   3374:   int lastSecond = 0, thisSecond;
                   3375: 
                   3376:   int cmdsock = -1;
                   3377: 
                   3378:   /* open a connection to the syslog daemon */
                   3379:   /*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
                   3380:   openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
                   3381: 
                   3382:   /* Process options given in configuration file and command line */
                   3383:   if (process_options(argc, argv, 0))
                   3384:     exit(1);
                   3385: 
                   3386:   /* foreground                                                   */
                   3387:   /* If flag not given run as a daemon                            */
                   3388:   if (!options.foreground) {
                   3389:     /* Close the standard file descriptors. */
                   3390:     /* Is this really needed ? */
                   3391:     freopen("/dev/null", "w", stdout);
                   3392:     freopen("/dev/null", "w", stderr);
                   3393:     freopen("/dev/null", "r", stdin);
                   3394:     if (daemon(1, 1)) {
                   3395:       log_err(errno, "daemon() failed!");
                   3396:     }
                   3397:   } 
                   3398: 
                   3399:   if (options.logfacility<0||options.logfacility>LOG_NFACILITIES)
                   3400:     options.logfacility=LOG_FAC(LOG_LOCAL6);
                   3401: 
                   3402:   closelog(); 
                   3403:   openlog(PACKAGE, LOG_PID, (options.logfacility<<3));
                   3404:   
                   3405:   /* This has to be done after we have our final pid */
                   3406:   log_pid((options.pidfile && *options.pidfile) ? options.pidfile : DEFPIDFILE);
                   3407: 
                   3408:   if (options.debug) 
                   3409:     log_dbg("ChilliSpot version %s started.\n", VERSION);
                   3410: 
                   3411:   syslog(LOG_INFO, "CoovaChilli(ChilliSpot) %s. Copyright 2002-2005 Mondru AB. Licensed under GPL. "
                   3412:         "Copyright 2006-2008 David Bird <dbird@acm.org>. Licensed under GPL. "
                   3413:         "See http://coova.org/ for details.", VERSION);
                   3414: 
                   3415:   mainclock = time(0);
                   3416: 
                   3417:   printstatus(NULL);
                   3418: 
                   3419:   /* Create a tunnel interface */
                   3420:   if (tun_new(&tun)) {
                   3421:     log_err(0, "Failed to create tun");
                   3422:     exit(1);
                   3423:   }
                   3424: 
                   3425:   /*tun_setaddr(tun, &options.dhcplisten,  &options.net, &options.mask);*/
                   3426:   tun_setaddr(tun, &options.dhcplisten,  &options.dhcplisten, &options.mask);
                   3427:   tun_set_cb_ind(tun, cb_tun_ind);
                   3428: 
                   3429:   if (tun) tun_maxfd(tun, maxfd);
                   3430:   if (options.ipup) tun_runscript(tun, options.ipup);
                   3431: 
                   3432:   
                   3433:   /* Create an instance of dhcp */
                   3434:   if (dhcp_new(&dhcp, APP_NUM_CONN, options.dhcpif,
                   3435:               options.dhcpusemac, options.dhcpmac, options.dhcpusemac, 
                   3436:               &options.dhcplisten, options.lease, 1, 
                   3437:               &options.uamlisten, options.uamport, 
                   3438:               options.eapolenable)) {
                   3439:     log_err(0, "Failed to create dhcp");
                   3440:     exit(1);
                   3441:   }
                   3442: 
                   3443:   net_maxfd(&dhcp->ipif, maxfd);
                   3444:   net_maxfd(&dhcp->arpif, maxfd);
                   3445:   net_maxfd(&dhcp->eapif, maxfd);
                   3446: 
                   3447:   fd_max(dhcp->relayfd, maxfd);
                   3448:   
                   3449:   dhcp_set_cb_request(dhcp, cb_dhcp_request);
                   3450:   dhcp_set_cb_connect(dhcp, cb_dhcp_connect);
                   3451:   dhcp_set_cb_disconnect(dhcp, cb_dhcp_disconnect);
                   3452:   dhcp_set_cb_data_ind(dhcp, cb_dhcp_data_ind);
                   3453:   dhcp_set_cb_eap_ind(dhcp, cb_dhcp_eap_ind);
                   3454:   dhcp_set_cb_getinfo(dhcp, cb_dhcp_getinfo);
                   3455: 
                   3456:   if (dhcp_set(dhcp, (options.debug & DEBUG_DHCP))) {
                   3457:     log_err(0, "Failed to set DHCP parameters");
                   3458:     exit(1);
                   3459:   }
                   3460: 
                   3461:   fixup_options();
                   3462: 
                   3463:   /* Create an instance of radius */
                   3464:   if (radius_new(&radius,
                   3465:                 &options.radiuslisten, options.coaport, options.coanoipcheck,
                   3466:                 &options.proxylisten, options.proxyport,
                   3467:                 &options.proxyaddr, &options.proxymask,
                   3468:                 options.proxysecret)) {
                   3469:     log_err(0, "Failed to create radius");
                   3470:     return -1;
                   3471:   }
                   3472: 
                   3473:   if (radius->fd > maxfd)
                   3474:     maxfd = radius->fd;
                   3475:   
                   3476:   if ((radius->proxyfd != -1) && (radius->proxyfd > maxfd))
                   3477:     maxfd = radius->proxyfd;
                   3478:   
                   3479:   radius_set(radius, dhcp ? dhcp->ipif.hwaddr : 0, (options.debug & DEBUG_RADIUS));
                   3480:   radius_set_cb_auth_conf(radius, cb_radius_auth_conf);
                   3481:   radius_set_cb_coa_ind(radius, cb_radius_coa_ind);
                   3482:   radius_set_cb_ind(radius, cb_radius_ind);
                   3483: 
                   3484:   if (options.acct_update)
                   3485:     radius_set_cb_acct_conf(radius, cb_radius_acct_conf);
                   3486: 
                   3487:   /* Initialise connections */
                   3488:   initconn();
                   3489:   
                   3490:   /* Allocate ippool for dynamic IP address allocation */
                   3491:   if (ippool_new(&ippool, 
                   3492:                 options.dynip, 
                   3493:                 options.dhcpstart, 
                   3494:                 options.dhcpend, 
                   3495:                 options.statip, 
                   3496:                 options.allowdyn, 
                   3497:                 options.allowstat)) {
                   3498:     log_err(0, "Failed to allocate IP pool!");
                   3499:     exit(1);
                   3500:   }
                   3501: 
                   3502:   /* Create an instance of redir */
                   3503:   if (redir_new(&redir, &options.uamlisten, options.uamport, options.uamuiport)) {
                   3504:     log_err(0, "Failed to create redir");
                   3505:     return -1;
                   3506:   }
                   3507: 
                   3508:   if (redir->fd[0] > maxfd) maxfd = redir->fd[0];
                   3509:   if (redir->fd[1] > maxfd) maxfd = redir->fd[1];
                   3510:   redir_set(redir, (options.debug));
                   3511:   redir_set_cb_getstate(redir, cb_redir_getstate);
                   3512: 
                   3513:   memset(&admin_session, 0, sizeof(admin_session));
                   3514:   memcpy(admin_session.ourmac, dhcp->ipif.hwaddr, sizeof(dhcp->ipif.hwaddr));
                   3515:   acct_req(&admin_session, RADIUS_STATUS_TYPE_ACCOUNTING_ON);
                   3516: 
                   3517:   if (options.adminuser) {
                   3518:     admin_session.is_adminsession = 1;
                   3519:     strncpy(admin_session.s_state.redir.username, 
                   3520:            options.adminuser, sizeof(admin_session.s_state.redir.username));
                   3521:     set_sessionid(&admin_session);
                   3522:     chilliauth_radius(radius);
                   3523:   }
                   3524: 
                   3525:   if (options.cmdsocket) {
                   3526:     cmdsock = cmdsock_init();
                   3527:     if (cmdsock > 0)
                   3528:       maxfd = cmdsock;
                   3529:   }
                   3530: 
                   3531:   /* Set up signal handlers */
                   3532:   memset(&act, 0, sizeof(act));
                   3533: 
                   3534:   act.sa_handler = fireman;
                   3535:   sigaction(SIGCHLD, &act, NULL);
                   3536: 
                   3537:   act.sa_handler = termination_handler;
                   3538:   sigaction(SIGTERM, &act, NULL);
                   3539:   sigaction(SIGINT, &act, NULL);
                   3540: 
                   3541:   act.sa_handler = sighup_handler;
                   3542:   sigaction(SIGHUP, &act, NULL);
                   3543: 
                   3544:   /*
                   3545:   act.sa_handler = alarm_handler;
                   3546:   sigaction(SIGALRM, &act, NULL);
                   3547: 
                   3548:   memset(&itval, 0, sizeof(itval));
                   3549:   itval.it_interval.tv_sec = 0;
                   3550:   itval.it_interval.tv_usec = 500000; / * TODO 0.5 second * /
                   3551:   itval.it_value.tv_sec = 0; 
                   3552:   itval.it_value.tv_usec = 500000; / * TODO 0.5 second * /
                   3553: 
                   3554:   if (setitimer(ITIMER_REAL, &itval, NULL)) {
                   3555:     log_err(errno, "setitimer() failed!");
                   3556:   }
                   3557:   */
                   3558: 
                   3559:   /* setup IPv4LL/APIPA network ip and mask for uamanyip exception */
                   3560:   inet_aton("169.254.0.0", &ipv4ll_ip);
                   3561:   inet_aton("255.255.0.0", &ipv4ll_mask);
                   3562: 
                   3563:   if (options.debug) 
                   3564:     log_dbg("Waiting for client request...");
                   3565: 
                   3566: 
                   3567:   /******************************************************************/
                   3568:   /* Main select loop                                               */
                   3569:   /******************************************************************/
                   3570: 
                   3571:   mainclock = time(0);
                   3572:   while (keep_going) {
                   3573: 
                   3574:     if (do_sighup) {
                   3575:       reprocess_options(argc, argv);
                   3576:       fixup_options();
                   3577: 
                   3578:       do_sighup = 0;
                   3579: 
                   3580:       /* Reinit DHCP parameters */
                   3581:       if (dhcp)
                   3582:        dhcp_set(dhcp, (options.debug & DEBUG_DHCP));
                   3583:       
                   3584:       /* Reinit RADIUS parameters */
                   3585:       radius_set(radius, dhcp ? dhcp->ipif.hwaddr : 0, (options.debug & DEBUG_RADIUS));
                   3586:       
                   3587:       /* Reinit Redir parameters */
                   3588:       redir_set(redir, options.debug);
                   3589: 
                   3590:       if (options.adminuser)
                   3591:        chilliauth_radius(radius);
                   3592:     }
                   3593: 
                   3594:     if (lastSecond != (thisSecond = mainclock) /*do_timeouts*/) {
                   3595:       radius_timeout(radius);
                   3596: 
                   3597:       if (dhcp) 
                   3598:        dhcp_timeout(dhcp);
                   3599:       
                   3600:       checkconn();
                   3601:       lastSecond = thisSecond;
                   3602:       /*do_timeouts = 0;*/
                   3603:     }
                   3604: 
                   3605:     fd_zero(&fds);
                   3606: 
                   3607:     if (tun) tun_fdset(tun, &fds);
                   3608:     if (dhcp) {
                   3609:       net_fdset(&dhcp->ipif, &fds);
                   3610: #if defined(__linux__)
                   3611:       net_fdset(&dhcp->arpif, &fds);
                   3612:       net_fdset(&dhcp->eapif, &fds);
                   3613:       fd_set(dhcp->relayfd, &fds);
                   3614: #endif
                   3615:     }
                   3616: 
                   3617:     fd_set(radius->fd, &fds);
                   3618:     fd_set(radius->proxyfd, &fds);
                   3619:     fd_set(redir->fd[0], &fds);
                   3620:     fd_set(redir->fd[1], &fds);
                   3621:     fd_set(cmdsock, &fds);
                   3622: 
                   3623:     idleTime.tv_sec = 0; /*IDLETIME;*/
                   3624:     idleTime.tv_usec = 500;
                   3625:     /*radius_timeleft(radius, &idleTime);
                   3626:       if (dhcp) dhcp_timeleft(dhcp, &idleTime);*/
                   3627:     switch (status = select(maxfd + 1, &fds, NULL, NULL, &idleTime /* NULL */)) {
                   3628:     case -1:
                   3629:       if (EINTR != errno) {
                   3630:        log_err(errno, "select() returned -1!");
                   3631:       }
                   3632:       break;
                   3633:     case 0:
                   3634:     default:
                   3635:       break;
                   3636:     }
                   3637: 
                   3638:     mainclock = time(0);
                   3639: 
                   3640:     if ((msgresult = 
                   3641:         TEMP_FAILURE_RETRY(msgrcv(redir->msgid, (struct msgbuf *)&msg, 
                   3642:                                   sizeof(msg.mdata), 0, IPC_NOWAIT)))  == -1) {
                   3643:       if ((errno != EAGAIN) && (errno != ENOMSG))
                   3644:        log_err(errno, "msgrcv() failed!");
                   3645:     }
                   3646: 
                   3647:     if (msgresult > 0) 
                   3648:       uam_msg(&msg);
                   3649:     
                   3650:     if (status > 0) {
                   3651: 
                   3652:       if (tun) tun_ckset(tun, &fds);
                   3653:      
                   3654:       if (dhcp) {
                   3655: 
                   3656:        if (fd_isset(dhcp->relayfd, &fds) && dhcp_relay_decaps(dhcp) < 0)
                   3657:          log_err(0, "dhcp_relay_decaps() failed!");
                   3658:       
                   3659: #if defined(__linux__)
                   3660: 
                   3661:        if (net_isset(&dhcp->ipif, &fds) && dhcp_decaps(dhcp) < 0)
                   3662:          log_err(0, "dhcp_decaps() failed!");
                   3663:       
                   3664:        if (net_isset(&dhcp->arpif, &fds) && dhcp_arp_ind(dhcp) < 0)
                   3665:          log_err(0, "dhcp_arpind() failed!");
                   3666:        
                   3667:        if (net_isset(&dhcp->eapif, &fds) && dhcp_eapol_ind(dhcp) < 0)
                   3668:          log_err(0, "dhcp_eapol_ind() failed!");
                   3669: 
                   3670: #elif defined (__FreeBSD__)  || defined (__APPLE__) || defined (__OpenBSD__)
                   3671: 
                   3672:        if (net_isset(&dhcp->ipif, &fds) && dhcp_decaps(dhcp) < 0)
                   3673:          log_err(0, "dhcp_decaps() failed!");
                   3674: 
                   3675: #endif
                   3676: 
                   3677:       }
                   3678: 
                   3679:       if (fd_isset(radius->fd, &fds) && radius_decaps(radius) < 0)
                   3680:        log_err(0, "radius_ind() failed!");
                   3681: 
                   3682:       if (fd_isset(radius->proxyfd, &fds) && radius_proxy_ind(radius) < 0)
                   3683:        log_err(0, "radius_proxy_ind() failed!");
                   3684: 
                   3685:       if (fd_isset(redir->fd[0], &fds) && redir_accept(redir, 0) < 0)
                   3686:        log_err(0, "redir_accept() failed!");
                   3687: 
                   3688:       if (fd_isset(redir->fd[1], &fds) && redir_accept(redir, 1) < 0)
                   3689:        log_err(0, "redir_accept() failed!");
                   3690:       
                   3691:       if (fd_isset(cmdsock, &fds) && cmdsock_accept(cmdsock) < 0)
                   3692:        log_err(0, "cmdsock_accept() failed!");
                   3693: 
                   3694:     }
                   3695:   }
                   3696:   
                   3697:   if (options.debug) 
                   3698:     log_dbg("Terminating ChilliSpot!");
                   3699: 
                   3700:   killconn();
                   3701: 
                   3702:   if (redir) 
                   3703:     redir_free(redir);
                   3704: 
                   3705:   if (radius) 
                   3706:     radius_free(radius);
                   3707: 
                   3708:   if (dhcp) 
                   3709:     dhcp_free(dhcp);
                   3710: 
                   3711:   if (tun && options.ipdown)
                   3712:     tun_runscript(tun, options.ipdown);
                   3713: 
                   3714:   if (tun) 
                   3715:     tun_free(tun);
                   3716: 
                   3717:   if (ippool) 
                   3718:     ippool_free(ippool);
                   3719: 
                   3720:   return 0;
                   3721:   
                   3722: }

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