#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
#include <freeradius-devel/rad_assert.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef WITH_SESSION_MGMT
int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
const char *user,
const char *sessionid, uint32_t cliaddr, char proto,
int session_time)
{
REQUEST *stopreq;
VALUE_PAIR *vp, *userpair;
int ret;
stopreq = request_alloc_fake(request);
stopreq->packet->code = PW_ACCOUNTING_REQUEST;
stopreq->listener = request->listener;
rad_assert(stopreq != NULL);
#define PAIR(n,v,t,e) do { \
if(!(vp = paircreate(n, t))) { \
request_free(&stopreq); \
radlog(L_ERR|L_CONS, "no memory"); \
pairfree(&(stopreq->packet->vps)); \
return 0; \
} \
vp->e = v; \
pairadd(&(stopreq->packet->vps), vp); \
} while(0)
#define INTPAIR(n,v) PAIR(n,v,PW_TYPE_INTEGER,vp_integer)
#define IPPAIR(n,v) PAIR(n,v,PW_TYPE_IPADDR,vp_ipaddr)
#define STRINGPAIR(n,v) do { \
if(!(vp = paircreate(n, PW_TYPE_STRING))) { \
request_free(&stopreq); \
radlog(L_ERR|L_CONS, "no memory"); \
pairfree(&(stopreq->packet->vps)); \
return 0; \
} \
strlcpy((char *)vp->vp_strvalue, v, sizeof vp->vp_strvalue); \
vp->length = strlen(v); \
pairadd(&(stopreq->packet->vps), vp); \
} while(0)
INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
INTPAIR(PW_ACCT_DELAY_TIME, 0);
STRINGPAIR(PW_USER_NAME, user);
userpair = vp;
INTPAIR(PW_NAS_PORT, port);
STRINGPAIR(PW_ACCT_SESSION_ID, sessionid);
if(proto == 'P') {
INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
} else if(proto == 'S') {
INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
} else {
INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER);
}
if(cliaddr != 0)
IPPAIR(PW_FRAMED_IP_ADDRESS, cliaddr);
INTPAIR(PW_ACCT_SESSION_TIME, session_time);
INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
stopreq->username = userpair;
stopreq->password = NULL;
ret = rad_accounting(stopreq);
request_free(&stopreq);
return ret;
}
#ifndef __MINGW32__
int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
const char *session_id)
{
pid_t pid, child_pid;
int status;
char address[16];
char port[11];
RADCLIENT *cl;
fr_ipaddr_t ipaddr;
ipaddr.af = AF_INET;
ipaddr.ipaddr.ip4addr.s_addr = nasaddr;
cl = client_find_old(&ipaddr);
if (!cl) {
DEBUG2("checkrad: Unknown NAS %s, not checking",
ip_ntoa(address, nasaddr));
return 1;
}
if (!cl->nastype || (cl->nastype[0] == '\0') ||
(strcmp(cl->nastype, "other") == 0)) {
DEBUG2("checkrad: No NAS type, or type \"other\" not checking");
return 1;
}
if ((pid = rad_fork()) < 0) {
radlog(L_ERR, "Accounting: Failed in fork(): Cannot run checkrad\n");
return 2;
}
if (pid > 0) {
child_pid = rad_waitpid(pid, &status);
if (child_pid == 0) {
radlog(L_ERR, "Check-TS: timeout waiting for checkrad");
return 2;
}
if (child_pid < 0) {
radlog(L_ERR, "Check-TS: unknown error in waitpid()");
return 2;
}
return WEXITSTATUS(status);
}
closefrom(3);
ip_ntoa(address, nasaddr);
snprintf(port, 11, "%u", portnum);
#ifdef __EMX__
execl(getenv("COMSPEC"), "", "/C","checkrad", cl->nastype, address, port,
user, session_id, NULL);
#else
execl(mainconfig.checkrad, "checkrad", cl->nastype, address, port,
user, session_id, NULL);
#endif
radlog(L_ERR, "Check-TS: exec %s: %s", mainconfig.checkrad, strerror(errno));
exit(2);
return 2;
}
#else
int rad_check_ts(UNUSED uint32_t nasaddr, UNUSED unsigned int portnum,
UNUSED const char *user, UNUSED const char *session_id)
{
radlog(L_ERR, "Simultaneous-Use is not supported");
return 2;
}
#endif
#else
int session_zap(UNUSED REQUEST *request, UNUSED uint32_t nasaddr, UNUSED unsigned int port,
UNUSED const char *user,
UNUSED const char *sessionid, UNUSED uint32_t cliaddr, UNUSED char proto,
UNUSED int session_time)
{
return RLM_MODULE_FAIL;
}
int rad_check_ts(UNUSED uint32_t nasaddr, UNUSED unsigned int portnum,
UNUSED const char *user, UNUSED const char *session_id)
{
radlog(L_ERR, "Simultaneous-Use is not supported");
return 2;
}
#endif