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