File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / radsrv.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (3 years, 3 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

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

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