Annotation of embedaddon/coova-chilli/src/chilli.c, revision 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: ¶ms->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>