File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / radsrv.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

    1: 
    2: /*
    3:  * radsrv.c
    4:  *
    5:  * Written by Alexander Motin <mav@FreeBSD.org>
    6:  */
    7: 
    8: #include "ppp.h"
    9: #include "radsrv.h"
   10: #include "util.h"
   11: #include <stdint.h>
   12: #include <radlib.h>
   13: #include <radlib_vs.h>
   14: 
   15: #ifdef RAD_COA_REQUEST
   16: 
   17: /*
   18:  * DEFINITIONS
   19:  */
   20: 
   21:   /* Set menu options */
   22:   enum {
   23:     SET_OPEN,
   24:     SET_CLOSE,
   25:     SET_SELF,
   26:     SET_PEER,
   27:     SET_DISABLE,
   28:     SET_ENABLE
   29:   };
   30: 
   31: 
   32: /*
   33:  * INTERNAL FUNCTIONS
   34:  */
   35: 
   36:   static int	RadsrvSetCommand(Context ctx, int ac, char *av[], void *arg);
   37: 
   38: /*
   39:  * GLOBAL VARIABLES
   40:  */
   41: 
   42:   const struct cmdtab RadsrvSetCmds[] = {
   43:     { "open",			"Open the radsrv" ,
   44:   	RadsrvSetCommand, NULL, 2, (void *) SET_OPEN },
   45:     { "close",			"Close the radsrv" ,
   46:   	RadsrvSetCommand, NULL, 2, (void *) SET_CLOSE },
   47:     { "self {ip} [{port}]",	"Set radsrv ip and port" ,
   48:   	RadsrvSetCommand, NULL, 2, (void *) SET_SELF },
   49:     { "peer {ip} {secret}",	"Set peer ip and secret" ,
   50:   	RadsrvSetCommand, NULL, 2, (void *) SET_PEER },
   51:     { "enable [opt ...]",	"Enable radsrv option" ,
   52:   	RadsrvSetCommand, NULL, 2, (void *) SET_ENABLE },
   53:     { "disable [opt ...]",	"Disable radsrv option" ,
   54:   	RadsrvSetCommand, NULL, 2, (void *) SET_DISABLE },
   55:     { NULL },
   56:   };
   57: 
   58: 
   59: /*
   60:  * INTERNAL VARIABLES
   61:  */
   62: 
   63:   static const struct confinfo	gConfList[] = {
   64:     { 0,	RADSRV_DISCONNECT,	"disconnect"	},
   65:     { 0,	RADSRV_COA,	"coa"	},
   66:     { 0,	0,		NULL	},
   67:   };
   68: 
   69: /*
   70:  * RadsrvInit()
   71:  */
   72: 
   73: int
   74: RadsrvInit(Radsrv w)
   75: {
   76:     /* setup radsrv-defaults */
   77:     memset(w, 0, sizeof(*w));
   78: 
   79:     Enable(&w->options, RADSRV_DISCONNECT);
   80:     Enable(&w->options, RADSRV_COA);
   81: 
   82:     ParseAddr(DEFAULT_RADSRV_IP, &w->addr, ALLOW_IPV4);
   83:     w->port = DEFAULT_RADSRV_PORT;
   84: 
   85:     return (0);
   86: }
   87: 
   88: static void
   89: RadsrvEvent(int type, void *cookie)
   90: {
   91:     Radsrv	w = (Radsrv)cookie;
   92:     const void	*data;
   93:     size_t	len;
   94:     int		res, result, found, err, anysesid, l;
   95:     Bund	B;
   96:     Link  	L;
   97:     char        *tmpval;
   98:     char	*username = NULL, *called = NULL, *calling = NULL, *sesid = NULL;
   99:     char	*msesid = NULL, *link = NULL, *bundle = NULL, *iface = NULL;
  100:     int		nasport = -1, serv_type = 0, ifindex = -1, i;
  101:     u_int	session_timeout = UINT_MAX, idle_timeout = UINT_MAX;
  102:     u_int	acct_update = UINT_MAX;
  103:     struct in_addr ip = { INADDR_BROADCAST };
  104:     struct in_addr nas_ip = { INADDR_BROADCAST };
  105:     char	buf[64];
  106:     u_int32_t	vendor;
  107:     u_char	*state = NULL, *rad_class = NULL;
  108:     int		state_len = 0;
  109:     int		class_len = 0;
  110:     int		authentic = 0;
  111: #if defined(USE_NG_BPF) || defined(USE_IPFW)
  112:     struct acl	**acls, *acls1;
  113:     char	*acl, *acl1, *acl2, *acl3;
  114: #endif
  115: #ifdef USE_IPFW
  116:     struct acl		*acl_rule = NULL;	/* ipfw rules */
  117:     struct acl		*acl_pipe = NULL;	/* ipfw pipes */
  118:     struct acl		*acl_queue = NULL;	/* ipfw queues */
  119:     struct acl		*acl_table = NULL;	/* ipfw tables */
  120: #endif
  121: #ifdef USE_NG_BPF
  122:     struct acl		*acl_filters[ACL_FILTERS]; /* mpd's internal bpf filters */
  123:     struct acl		*acl_limits[ACL_DIRS];	/* traffic limits based on mpd's filters */
  124:     char 		std_acct[ACL_DIRS][ACL_NAME_LEN]; /* Names of ACL returned in standard accounting */
  125: 
  126:     bzero(acl_filters, sizeof(acl_filters));
  127:     bzero(acl_limits, sizeof(acl_limits));
  128:     bzero(std_acct, sizeof(std_acct));
  129: #endif
  130:     result = rad_receive_request(w->handle);
  131:     if (result < 0) {
  132: 	Log(LG_ERR, ("radsrv: request receive error: %d", result));
  133: 	return;
  134:     }
  135:     switch (result) {
  136: 	case RAD_DISCONNECT_REQUEST:
  137: 	    if (!Enabled(&w->options, RADSRV_DISCONNECT)) {
  138: 		Log(LG_ERR, ("radsrv: DISCONNECT request, support disabled"));
  139: 		rad_create_response(w->handle, RAD_DISCONNECT_NAK);
  140: 		rad_put_int(w->handle, RAD_ERROR_CAUSE, 501);
  141: 		rad_send_response(w->handle);
  142: 		return;
  143: 	    }
  144: 	    Log(LG_ERR, ("radsrv: DISCONNECT request"));
  145: 	    break;
  146: 	case RAD_COA_REQUEST:
  147: 	    if (!Enabled(&w->options, RADSRV_COA)) {
  148: 		Log(LG_ERR, ("radsrv: CoA request, support disabled"));
  149: 		rad_create_response(w->handle, RAD_COA_NAK);
  150: 		rad_put_int(w->handle, RAD_ERROR_CAUSE, 501);
  151: 		rad_send_response(w->handle);
  152: 		return;
  153: 	    }
  154: 	    Log(LG_ERR, ("radsrv: CoA request"));
  155: 	    break;
  156: 	default:
  157: 	    Log(LG_ERR, ("radsrv: unsupported request: %d", result));
  158: 	    return;
  159:     }
  160:     anysesid = 0;
  161:     while ((res = rad_get_attr(w->handle, &data, &len)) > 0) {
  162: 	switch (res) {
  163: 	    case RAD_USER_NAME:
  164: 		anysesid = 1;
  165: 		if (username)
  166: 		    free(username);
  167: 		username = rad_cvt_string(data, len);
  168: 		Log(LG_RADIUS2, ("radsrv: Got RAD_USER_NAME: %s", username));
  169: 		break;
  170: 	    case RAD_CLASS:
  171: 		tmpval = Bin2Hex(data, len);
  172: 		Log(LG_RADIUS2, ("radsrv: Got RAD_CLASS: %s", tmpval));
  173: 		Freee(tmpval);
  174: 		class_len = len;
  175: 		if (rad_class != NULL)
  176: 		    Freee(rad_class);
  177: 		rad_class = Mdup(MB_AUTH, data, len);
  178: 		break;
  179: 	    case RAD_NAS_IP_ADDRESS:
  180: 		nas_ip = rad_cvt_addr(data);
  181: 		Log(LG_RADIUS2, ("radsrv: Got RAD_NAS_IP_ADDRESS: %s",
  182: 		    inet_ntoa(nas_ip)));
  183: 		break;
  184: 	    case RAD_SERVICE_TYPE:
  185: 		serv_type = rad_cvt_int(data);
  186: 		Log(LG_RADIUS2, ("radsrv: Got RAD_SERVICE_TYPE: %d",
  187: 		    serv_type));
  188: 		break;
  189:     	    case RAD_STATE:
  190: 		tmpval = Bin2Hex(data, len);
  191: 		Log(LG_RADIUS2, ("radsrv: Got RAD_STATE: 0x%s", tmpval));
  192: 		Freee(tmpval);
  193: 		state_len = len;
  194: 		if (state != NULL)
  195: 		    Freee(state);
  196: 		state = Mdup(MB_RADSRV, data, len);
  197: 		break;
  198: 	    case RAD_CALLED_STATION_ID:
  199: 		anysesid = 1;
  200: 		if (called)
  201: 		    free(called);
  202: 		called = rad_cvt_string(data, len);
  203: 		Log(LG_RADIUS2, ("radsrv: Got RAD_CALLED_STATION_ID: %s",
  204: 		    called));
  205: 		break;
  206: 	    case RAD_CALLING_STATION_ID:
  207: 		anysesid = 1;
  208: 		if (calling)
  209: 		    free(calling);
  210: 		calling = rad_cvt_string(data, len);
  211: 		Log(LG_RADIUS2, ("radsrv: Got RAD_CALLING_STATION_ID: %s",
  212: 		    calling));
  213: 		break;
  214: 	    case RAD_ACCT_SESSION_ID:
  215: 		anysesid = 1;
  216: 		if (sesid)
  217: 		    free(sesid);
  218: 		sesid = rad_cvt_string(data, len);
  219: 		Log(LG_RADIUS2, ("radsrv: Got RAD_ACCT_SESSION_ID: %s",
  220: 		    sesid));
  221: 		break;
  222: 	    case RAD_ACCT_MULTI_SESSION_ID:
  223: 		anysesid = 1;
  224: 		if (msesid)
  225: 		    free(msesid);
  226: 		msesid = rad_cvt_string(data, len);
  227: 		Log(LG_RADIUS2, ("radsrv: Got RAD_ACCT_MULTI_SESSION_ID: %s",
  228: 		    msesid));
  229: 		break;
  230: 	    case RAD_FRAMED_IP_ADDRESS:
  231: 		anysesid = 1;
  232: 		ip = rad_cvt_addr(data);
  233: 		Log(LG_RADIUS2, ("radsrv: Got RAD_FRAMED_IP_ADDRESS: %s",
  234: 		    inet_ntoa(ip)));
  235: 		if (ip.s_addr == INADDR_BROADCAST)
  236: 		    Log(LG_ERR, ("radsrv: incorrect Framed-IP-Address"));
  237: 		break;
  238: 	    case RAD_NAS_PORT:
  239: 		anysesid = 1;
  240: 		nasport = rad_cvt_int(data);
  241: 		Log(LG_RADIUS2, ("radsrv: Got RAD_NAS_PORT: %d",
  242: 		    nasport));
  243: 		break;
  244: 	    case RAD_SESSION_TIMEOUT:
  245: 	        session_timeout = rad_cvt_int(data);
  246: 	        Log(LG_RADIUS2, ("radsrv: Got RAD_SESSION_TIMEOUT: %u",
  247: 	    	    session_timeout));
  248: 	        break;
  249: 	    case RAD_IDLE_TIMEOUT:
  250: 	        idle_timeout = rad_cvt_int(data);
  251: 	        Log(LG_RADIUS2, ("radsrv: Got RAD_IDLE_TIMEOUT: %u",
  252: 	            idle_timeout));
  253: 	        break;
  254: 	    case RAD_ACCT_INTERIM_INTERVAL:
  255: 		acct_update = rad_cvt_int(data);
  256: 	        Log(LG_RADIUS2, ("radsrv: Got RAD_ACCT_INTERIM_INTERVAL: %u",
  257: 	    	    acct_update));
  258: 		break;
  259: 	    case RAD_MESSAGE_AUTHENTIC:
  260: 		Log(LG_RADIUS2, ("radsrv: Got RAD_MESSAGE_AUTHENTIC"));
  261: 		authentic = 1;
  262: 		break;
  263: 	    case RAD_VENDOR_SPECIFIC:
  264: 		if ((res = rad_get_vendor_attr(&vendor, &data, &len)) == -1) {
  265: 		    Log(LG_RADIUS, ("radsrv: Get vendor attr failed: %s",
  266: 			rad_strerror(w->handle)));
  267: 		    break;
  268: 		}
  269: 		switch (vendor) {
  270: 		    case RAD_VENDOR_MPD:
  271: 			if (res == RAD_MPD_LINK) {
  272: 			    if (link)
  273: 				free(link);
  274: 			    link = rad_cvt_string(data, len);
  275: 	    		    Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_LINK: %s",
  276: 				link));
  277: 			    anysesid = 1;
  278: 			    break;
  279: 			} else if (res == RAD_MPD_BUNDLE) {
  280: 			    if (bundle)
  281: 				free(bundle);
  282: 			    bundle = rad_cvt_string(data, len);
  283: 	    		    Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_BINDLE: %s",
  284: 				bundle));
  285: 			    anysesid = 1;
  286: 			    break;
  287: 			} else if (res == RAD_MPD_IFACE) {
  288: 			    if (iface)
  289: 				free(iface);
  290: 			    iface = rad_cvt_string(data, len);
  291: 	    		    Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_IFACE: %s",
  292: 				iface));
  293: 			    anysesid = 1;
  294: 			    break;
  295: 			} else if (res == RAD_MPD_IFACE_INDEX) {
  296: 			    ifindex = rad_cvt_int(data);
  297: 	    		    Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_IFACE_INDEX: %d",
  298: 				ifindex));
  299: 			    anysesid = 1;
  300: 			    break;
  301: 			} else 
  302: #ifdef USE_IPFW
  303: 		        if (res == RAD_MPD_RULE) {
  304:     			  acl1 = acl = rad_cvt_string(data, len);
  305: 		    	  Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_RULE: %s",
  306: 			    acl));
  307: 		    	  acls = &acl_rule;
  308: 			} else if (res == RAD_MPD_PIPE) {
  309: 			  acl1 = acl = rad_cvt_string(data, len);
  310: 		          Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_PIPE: %s",
  311: 			    acl));
  312: 		          acls = &acl_pipe;
  313: 		        } else if (res == RAD_MPD_QUEUE) {
  314: 			  acl1 = acl = rad_cvt_string(data, len);
  315: 			  Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_QUEUE: %s",
  316: 			    acl));
  317: 			  acls = &acl_queue;
  318: 			} else if (res == RAD_MPD_TABLE) {
  319: 			  acl1 = acl = rad_cvt_string(data, len);
  320: 			  Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_TABLE: %s",
  321: 			    acl));
  322: 			  acls = &acl_table;
  323: 			} else if (res == RAD_MPD_TABLE_STATIC) {
  324: 			  acl1 = acl = rad_cvt_string(data, len);
  325: 			  Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_TABLE_STATIC: %s",
  326: 			    acl));
  327: 			  acls = &acl_table;
  328: 			} else
  329: #endif /* USE_IPFW */
  330: #ifdef USE_NG_BPF
  331: 			if (res == RAD_MPD_FILTER) {
  332: 			  acl1 = acl = rad_cvt_string(data, len);
  333: 			  Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_FILTER: %s",
  334: 		            acl));
  335: 		          acl2 = strsep(&acl1, "#");
  336: 		          i = atoi(acl2);
  337: 		          if (i <= 0 || i > ACL_FILTERS) {
  338: 		            Log(LG_RADIUS, ("radsrv: Wrong filter number: %i", i));
  339: 		            free(acl);
  340: 	    		    break;
  341: 			  }
  342: 			  acls = &(acl_filters[i - 1]);
  343: 			} else if (res == RAD_MPD_LIMIT) {
  344: 			  acl1 = acl = rad_cvt_string(data, len);
  345: 		          Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_LIMIT: %s",
  346: 			    acl));
  347: 		          acl2 = strsep(&acl1, "#");
  348: 		          if (strcasecmp(acl2, "in") == 0) {
  349: 		            i = 0;
  350: 		          } else if (strcasecmp(acl2, "out") == 0) {
  351: 		            i = 1;
  352: 		          } else {
  353: 		            Log(LG_ERR, ("radsrv: Wrong limit direction: '%s'",
  354: 		    		acl2));
  355: 		            free(acl);
  356: 			    break;
  357: 		          }
  358: 		          acls = &(acl_limits[i]);
  359: 		        } else if (res == RAD_MPD_INPUT_ACCT) {
  360: 			  tmpval = rad_cvt_string(data, len);
  361: 	    		  Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_INPUT_ACCT: %s",
  362: 	    		    tmpval));
  363: 			  strlcpy(std_acct[0], tmpval, sizeof(std_acct[0]));
  364: 			  free(tmpval);
  365: 			  break;
  366: 			} else if (res == RAD_MPD_OUTPUT_ACCT) {
  367: 			  tmpval = rad_cvt_string(data, len);
  368: 	    		  Log(LG_RADIUS2, ("radsrv: Get RAD_MPD_OUTPUT_ACCT: %s",
  369: 	    		    tmpval));
  370: 			  strlcpy(std_acct[1], tmpval, sizeof(std_acct[1]));
  371: 			  free(tmpval);
  372: 			  break;
  373: 			} else
  374: #endif /* USE_NG_BPF */
  375: 			{
  376: 			  Log(LG_RADIUS2, ("radsrv: Dropping MPD vendor specific attribute: %d",
  377: 			    res));
  378: 	    		  break;
  379: 			}
  380: #if defined(USE_NG_BPF) || defined(USE_IPFW)
  381: 		    if (acl1 == NULL) {
  382: 		      Log(LG_ERR, ("radsrv: Incorrect acl!"));
  383: 		      free(acl);
  384: 		      break;
  385: 		    }
  386: 	    
  387: 		    acl3 = acl1;
  388: 		    strsep(&acl3, "=");
  389: 		    acl2 = acl1;
  390: 		    strsep(&acl2, "#");
  391: 		    i = atoi(acl1);
  392: 		    if (i <= 0) {
  393: 		      Log(LG_ERR, ("radsrv: Wrong acl number: %i", i));
  394: 		      free(acl);
  395: 		      break;
  396: 		    }
  397: 		    if ((acl3 == NULL) || (acl3[0] == 0)) {
  398: 		      Log(LG_ERR, ("radsrv: Wrong acl"));
  399: 		      free(acl);
  400: 		      break;
  401: 		    }
  402: 		    acls1 = Malloc(MB_AUTH, sizeof(struct acl) + strlen(acl3));
  403: 		    if (res != RAD_MPD_TABLE_STATIC) {
  404: 			    acls1->number = i;
  405: 			    acls1->real_number = 0;
  406: 		    } else {
  407: 			    acls1->number = 0;
  408: 			    acls1->real_number = i;
  409: 		    }
  410: 		    if (acl2)
  411: 	    		strlcpy(acls1->name, acl2, sizeof(acls1->name));
  412: 		    strcpy(acls1->rule, acl3);
  413: 		    while ((*acls != NULL) && ((*acls)->number < acls1->number))
  414: 		      acls = &((*acls)->next);
  415: 
  416: 		    if (*acls == NULL) {
  417: 		      acls1->next = NULL;
  418: 		    } else if (((*acls)->number == acls1->number) &&
  419: 			(res != RAD_MPD_TABLE) &&
  420: 			(res != RAD_MPD_TABLE_STATIC)) {
  421: 		      Log(LG_ERR, ("radsrv: Duplicate acl"));
  422: 		      Freee(acls1);
  423: 		      free(acl);
  424: 		      break;
  425: 		    } else {
  426: 		      acls1->next = *acls;
  427: 		    }
  428: 		    *acls = acls1;
  429: 
  430: 		    free(acl);
  431: 		    break;
  432: #endif /* USE_NG_BPF or USE_IPFW */
  433: 
  434: 		  default:
  435: 		    Log(LG_RADIUS2, ("radsrv: Dropping vendor %d attribute: %d",
  436: 		      vendor, res));
  437: 		    break;
  438: 		}
  439: 		break;
  440: 	    default:
  441: 		Log(LG_RADIUS2, ("radsrv: Unknown attribute: %d", res));
  442: 		break;
  443: 	}
  444:     }
  445:     err = 0;
  446:     if (w->addr.u.ip4.s_addr != 0 && nas_ip.s_addr != INADDR_BROADCAST
  447:     && w->addr.u.ip4.s_addr != nas_ip.s_addr) {
  448:         Log(LG_ERR, ("radsrv: incorrect NAS-IP-Address"));
  449: 	err = 403;
  450:     } else if (anysesid == 0) {
  451:         Log(LG_ERR, ("radsrv: request without session identification"));
  452: 	err = 402;
  453:     } else if (serv_type != 0) {
  454:         Log(LG_ERR, ("radsrv: Service-Type attribute not supported"));
  455: 	err = 405;
  456:     }
  457:     if (err) {
  458: 	if (result == RAD_DISCONNECT_REQUEST)
  459: 	    rad_create_response(w->handle, RAD_DISCONNECT_NAK);
  460: 	else
  461: 	    rad_create_response(w->handle, RAD_COA_NAK);
  462:         rad_put_int(w->handle, RAD_ERROR_CAUSE, err);
  463: 	if (state != NULL)
  464: 	    rad_put_attr(w->handle, RAD_STATE, state, state_len);
  465: 	if (authentic)
  466: 	    rad_put_message_authentic(w->handle);
  467: 	rad_send_response(w->handle);
  468: 	goto cleanup;
  469:     }
  470:     found = 0;
  471:     err = 503;
  472:     for (l = 0; l < gNumLinks; l++) {
  473: 	if ((L = gLinks[l]) != NULL) {
  474: 	    B = L->bund;
  475: 	    if (nasport != -1 && nasport != l)
  476: 		continue;
  477: 	    if (sesid && strcmp(sesid, L->session_id))
  478: 		continue;
  479: 	    if (link && strcmp(link, L->name))
  480: 		continue;
  481: 	    if (msesid && strcmp(msesid, L->msession_id))
  482: 		continue;
  483: 	    if (username && strcmp(username, L->lcp.auth.params.authname))
  484: 		continue;
  485: 	    if (called && !PhysGetCalledNum(L, buf, sizeof(buf)) &&
  486: 		    strcmp(called, buf))
  487: 		continue;
  488: 	    if (calling && !PhysGetCallingNum(L, buf, sizeof(buf)) &&
  489: 		    strcmp(calling, buf))
  490: 		continue;
  491: 	    if (bundle && (!B || strcmp(bundle, B->name)))
  492: 		continue;
  493: 	    if (iface && (!B || strcmp(iface, B->iface.ifname)))
  494: 		continue;
  495: 	    if (ifindex >= 0 && (!B || (uint)ifindex != B->iface.ifindex))
  496: 		continue;
  497: 	    if (ip.s_addr != INADDR_BROADCAST && (!B ||
  498: 		    ip.s_addr != B->iface.peer_addr.u.ip4.s_addr))
  499: 		continue;
  500: 		
  501: 	    Log(LG_RADIUS2, ("radsrv: Matched link: %s", L->name));
  502: 	    if (L->tmpl) {
  503: 		Log(LG_ERR, ("radsrv: Impossible to affect template"));
  504: 		err = 504;
  505: 		continue;
  506: 	    }
  507: 	    found++;
  508: 	
  509: 	    if (result == RAD_DISCONNECT_REQUEST) {
  510: 		RecordLinkUpDownReason(NULL, L, 0, STR_MANUALLY, NULL);
  511: 		LinkClose(L);
  512: 	    } else { /* CoA */
  513: 		if (B && B->iface.up && !B->iface.dod) {
  514: 		    if (B->iface.ip_up)
  515: 			IfaceIpIfaceDown(B);
  516: 		    if (B->iface.ipv6_up)
  517: 			IfaceIpv6IfaceDown(B);
  518: 		    IfaceDown(B);
  519: 		}
  520: #ifdef USE_IPFW
  521: 	        ACLDestroy(L->lcp.auth.params.acl_rule);
  522: 	        ACLDestroy(L->lcp.auth.params.acl_pipe);
  523: 	        ACLDestroy(L->lcp.auth.params.acl_queue);
  524: 	        ACLDestroy(L->lcp.auth.params.acl_table);
  525: 	        L->lcp.auth.params.acl_rule = NULL;
  526: 	        L->lcp.auth.params.acl_pipe = NULL;
  527: 	        L->lcp.auth.params.acl_queue = NULL;
  528: 	        L->lcp.auth.params.acl_table = NULL;
  529: 	        ACLCopy(acl_rule, &L->lcp.auth.params.acl_rule);
  530: 	        ACLCopy(acl_pipe, &L->lcp.auth.params.acl_pipe);
  531: 	        ACLCopy(acl_queue, &L->lcp.auth.params.acl_queue);
  532: 	        ACLCopy(acl_table, &L->lcp.auth.params.acl_table);
  533: #endif /* USE_IPFW */
  534: 		if (rad_class != NULL) {
  535: 		    if (L->lcp.auth.params.class != NULL)
  536: 			Freee(L->lcp.auth.params.class);
  537: 		    L->lcp.auth.params.class = Mdup(MB_AUTH, rad_class, class_len);
  538: 		    L->lcp.auth.params.class_len = class_len;
  539: 		}
  540: #ifdef USE_NG_BPF
  541: 	        for (i = 0; i < ACL_FILTERS; i++) {
  542: 	    	    ACLDestroy(L->lcp.auth.params.acl_filters[i]);
  543: 	    	    L->lcp.auth.params.acl_filters[i] = NULL;
  544: 	    	    ACLCopy(acl_filters[i], &L->lcp.auth.params.acl_filters[i]);
  545: 		}
  546: 	        for (i = 0; i < ACL_DIRS; i++) {
  547: 	    	    ACLDestroy(L->lcp.auth.params.acl_limits[i]);
  548: 	    	    L->lcp.auth.params.acl_limits[i] = NULL;
  549: 	    	    ACLCopy(acl_limits[i], &L->lcp.auth.params.acl_limits[i]);
  550: 		}
  551: 		strcpy(L->lcp.auth.params.std_acct[0], std_acct[0]);
  552: 		strcpy(L->lcp.auth.params.std_acct[1], std_acct[1]);
  553: #endif
  554: 		if (session_timeout != UINT_MAX)
  555: 		    L->lcp.auth.params.session_timeout = session_timeout;
  556: 		if (idle_timeout != UINT_MAX)
  557: 		    L->lcp.auth.params.idle_timeout = idle_timeout;
  558: 		if (acct_update != UINT_MAX) {
  559: 		    L->lcp.auth.params.acct_update = acct_update;
  560: 		    /* Stop accounting update timer if running. */
  561: 		    TimerStop(&L->lcp.auth.acct_timer);
  562: 		    if (B) {
  563: 			/* Start accounting update timer if needed. */
  564: 			u_int	updateInterval;
  565: 			if (L->lcp.auth.params.acct_update > 0)
  566: 		    	    updateInterval = L->lcp.auth.params.acct_update;
  567: 			else
  568: 		    	    updateInterval = L->lcp.auth.conf.acct_update;
  569: 			if (updateInterval > 0) {
  570: 	    		    TimerInit(&L->lcp.auth.acct_timer, "AuthAccountTimer",
  571: 				updateInterval * SECONDS, AuthAccountTimeout, L);
  572: 			    TimerStartRecurring(&L->lcp.auth.acct_timer);
  573: 			}
  574: 		    }
  575: 		}
  576: 		if (B && B->iface.up && !B->iface.dod) {
  577: 		    authparamsDestroy(&B->params);
  578: 		    authparamsCopy(&L->lcp.auth.params,&B->params);
  579: 		    if (B->iface.ip_up)
  580: 			IfaceIpIfaceUp(B, 1);
  581: 		    if (B->iface.ipv6_up)
  582: 			IfaceIpv6IfaceUp(B, 1);
  583: 		    IfaceUp(B, 1);
  584: 		}
  585: 	    }
  586: 	}
  587:     }
  588:     if (result == RAD_DISCONNECT_REQUEST) {
  589: 	if (found) {
  590: 	    rad_create_response(w->handle, RAD_DISCONNECT_ACK);
  591: 	} else {
  592: 	    rad_create_response(w->handle, RAD_DISCONNECT_NAK);
  593: 	    rad_put_int(w->handle, RAD_ERROR_CAUSE, err);
  594: 	}
  595:     } else {
  596: 	if (found) {
  597: 	    rad_create_response(w->handle, RAD_COA_ACK);
  598: 	} else {
  599: 	    rad_create_response(w->handle, RAD_COA_NAK);
  600: 	    rad_put_int(w->handle, RAD_ERROR_CAUSE, err);
  601: 	}
  602:     }
  603:     if (state != NULL)
  604:         rad_put_attr(w->handle, RAD_STATE, state, state_len);
  605:     if (authentic)
  606: 	rad_put_message_authentic(w->handle);
  607:     rad_send_response(w->handle);
  608: 
  609: cleanup:
  610:     if (username)
  611: 	free(username);
  612:     if (rad_class != NULL)
  613: 	Freee(rad_class);
  614:     if (called)
  615: 	free(called);
  616:     if (calling)
  617: 	free(calling);
  618:     if (sesid)
  619: 	free(sesid);
  620:     if (msesid)
  621: 	free(msesid);
  622:     if (link)
  623: 	free(link);
  624:     if (bundle)
  625: 	free(bundle);
  626:     if (iface)
  627: 	free(iface);
  628:     if (state != NULL)
  629: 	Freee(state);
  630: #ifdef USE_IPFW
  631:     ACLDestroy(acl_rule);
  632:     ACLDestroy(acl_pipe);
  633:     ACLDestroy(acl_queue);
  634:     ACLDestroy(acl_table);
  635: #endif /* USE_IPFW */
  636: #ifdef USE_NG_BPF
  637:     for (i = 0; i < ACL_FILTERS; i++)
  638: 	ACLDestroy(acl_filters[i]);
  639:     for (i = 0; i < ACL_DIRS; i++)
  640: 	ACLDestroy(acl_limits[i]);
  641: #endif /* USE_NG_BPF */
  642: }
  643: 
  644: /*
  645:  * RadsrvOpen()
  646:  */
  647: 
  648: int
  649: RadsrvOpen(Radsrv w)
  650: {
  651:     char		addrstr[INET6_ADDRSTRLEN];
  652:     struct sockaddr_in sin;
  653:     struct radiusclient_conf *s;
  654: 
  655:     if (w->handle) {
  656: 	Log(LG_ERR, ("radsrv: radsrv already running"));
  657: 	return (-1);
  658:     }
  659: 
  660:     if ((w->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
  661: 	Perror("%s: Cannot create socket", __FUNCTION__);
  662: 	return (-1);
  663:     }
  664:     memset(&sin, 0, sizeof sin);
  665:     sin.sin_len = sizeof sin;
  666:     sin.sin_family = AF_INET;
  667:     sin.sin_addr = w->addr.u.ip4;
  668:     sin.sin_port = htons(w->port);
  669:     if (bind(w->fd, (const struct sockaddr *)&sin,
  670: 	    sizeof sin) == -1) {
  671: 	Log(LG_ERR, ("%s: bind: %s", __FUNCTION__, strerror(errno)));
  672: 	close(w->fd);
  673: 	w->fd = -1;
  674: 	return (-1);
  675:     }
  676: 
  677:     if (!(w->handle = rad_server_open(w->fd))) {
  678: 	Log(LG_ERR, ("%s: rad_server_open error", __FUNCTION__));
  679: 	close(w->fd);
  680: 	w->fd = -1;
  681: 	return(-1);
  682:     }
  683: 
  684:     EventRegister(&w->event, EVENT_READ, w->fd,
  685: 	EVENT_RECURRING, RadsrvEvent, w);
  686: 
  687:     s = w->clients;
  688:     while (s) {
  689: 	Log(LG_RADIUS2, ("radsrv: Adding client %s", s->hostname));
  690: 	if (rad_add_server (w->handle, s->hostname,
  691: 		0, s->sharedsecret, 0, 0) == -1) {
  692: 		Log(LG_RADIUS, ("radsrv: Adding client error: %s",
  693: 		    rad_strerror(w->handle)));
  694: 	}
  695: 	s = s->next;
  696:     }
  697: 
  698:     Log(LG_ERR, ("radsrv: listening on %s %d",
  699: 	u_addrtoa(&w->addr,addrstr,sizeof(addrstr)), w->port));
  700:     return (0);
  701: }
  702: 
  703: /*
  704:  * RadsrvClose()
  705:  */
  706: 
  707: int
  708: RadsrvClose(Radsrv w)
  709: {
  710: 
  711:     if (!w->handle) {
  712: 	Log(LG_ERR, ("radsrv: radsrv is not running"));
  713: 	return (-1);
  714:     }
  715:     EventUnRegister(&w->event);
  716:     rad_close(w->handle);
  717:     w->handle = NULL;
  718: 
  719:     Log(LG_ERR, ("radsrv: stop listening"));
  720:     return (0);
  721: }
  722: 
  723: /*
  724:  * RadsrvStat()
  725:  */
  726: 
  727: int
  728: RadsrvStat(Context ctx, int ac, char *av[], void *arg)
  729: {
  730:     Radsrv	w = &gRadsrv;
  731:     char	addrstr[64];
  732:     struct radiusclient_conf *client;
  733: 
  734:     Printf("Radsrv configuration:\r\n");
  735:     Printf("\tState         : %s\r\n", w->handle ? "OPENED" : "CLOSED");
  736:     Printf("\tSelf          : %s %d\r\n",
  737: 	u_addrtoa(&w->addr,addrstr,sizeof(addrstr)), w->port);
  738:     Printf("\tPeer:\r\n");
  739:     client = w->clients;
  740:     while (client) {
  741:       Printf("\t  %s ********\r\n", client->hostname);
  742:       client = client->next;
  743:     }
  744:     Printf("Radsrv options:\r\n");
  745:     OptStat(ctx, &w->options, gConfList);
  746: 
  747:     return (0);
  748: }
  749: 
  750: /*
  751:  * RadsrvSetCommand()
  752:  */
  753: 
  754: static int
  755: RadsrvSetCommand(Context ctx, int ac, char *av[], void *arg) 
  756: {
  757:     Radsrv	 w = &gRadsrv;
  758:     int		port, count;
  759:     struct radiusclient_conf *peer, *t_peer;
  760: 
  761:   switch ((intptr_t)arg) {
  762: 
  763:     case SET_OPEN:
  764:       RadsrvOpen(w);
  765:       break;
  766: 
  767:     case SET_CLOSE:
  768:       RadsrvClose(w);
  769:       break;
  770: 
  771:     case SET_ENABLE:
  772: 	EnableCommand(ac, av, &w->options, gConfList);
  773:       break;
  774: 
  775:     case SET_DISABLE:
  776: 	DisableCommand(ac, av, &w->options, gConfList);
  777:       break;
  778: 
  779:     case SET_SELF:
  780:       if (ac < 1 || ac > 2)
  781: 	return(-1);
  782: 
  783:       if (!ParseAddr(av[0],&w->addr, ALLOW_IPV4)) 
  784: 	Error("Bogus IP address given %s", av[0]);
  785: 
  786:       if (ac == 2) {
  787:         port =  strtol(av[1], NULL, 10);
  788:         if (port < 1 || port > 65535)
  789: 	    Error("Bogus port given %s", av[1]);
  790:         w->port=port;
  791:       }
  792:       break;
  793: 
  794:     case SET_PEER:
  795: 	if (ac != 2)
  796: 	  return(-1);
  797: 
  798: 	count = 0;
  799: 	for ( t_peer = w->clients ; t_peer ;
  800: 	  t_peer = t_peer->next) {
  801: 	  count++;
  802: 	}
  803: 	if (count > RADSRV_MAX_SERVERS) {
  804: 	  Error("cannot configure more than %d peers",
  805: 	    RADSRV_MAX_SERVERS);
  806: 	}
  807: 	if (strlen(av[0]) > MAXHOSTNAMELEN-1)
  808: 	    Error("Hostname too long. > %d char.", MAXHOSTNAMELEN-1);
  809: 	if (strlen(av[1]) > 127)
  810: 	    Error("Shared Secret too long. > 127 char.");
  811: 
  812: 	peer = Malloc(MB_RADSRV, sizeof(*peer));
  813: 	peer->hostname = Mstrdup(MB_RADSRV, av[0]);
  814: 	peer->sharedsecret = Mstrdup(MB_RADSRV, av[1]);
  815: 	peer->next = w->clients;
  816: 	w->clients = peer;
  817: 	break;
  818: 
  819:     default:
  820:       return(-1);
  821: 
  822:   }
  823: 
  824:   return 0;
  825: }
  826: 
  827: #endif

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