2 * session.c session management
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
23 #include <freeradius-devel/ident.h>
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/modules.h>
28 #include <freeradius-devel/rad_assert.h>
30 #ifdef HAVE_SYS_WAIT_H
34 #ifdef WITH_SESSION_MGMT
36 * End a session by faking a Stop packet to all accounting modules.
38 int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
40 const char *sessionid, uint32_t cliaddr, char proto,
44 VALUE_PAIR *vp, *userpair;
47 stopreq = request_alloc_fake(request);
48 stopreq->packet->code = PW_ACCOUNTING_REQUEST; /* just to be safe */
49 stopreq->listener = request->listener;
50 rad_assert(stopreq != NULL);
52 /* Hold your breath */
53 #define PAIR(n,v,t,e) do { \
54 if(!(vp = paircreate(n, 0, t))) { \
55 request_free(&stopreq); \
56 radlog(L_ERR|L_CONS, "no memory"); \
57 pairfree(&(stopreq->packet->vps)); \
61 pairadd(&(stopreq->packet->vps), vp); \
63 #define INTPAIR(n,v) PAIR(n,v,PW_TYPE_INTEGER,vp_integer)
64 #define IPPAIR(n,v) PAIR(n,v,PW_TYPE_IPADDR,vp_ipaddr)
65 #define STRINGPAIR(n,v) do { \
66 if(!(vp = paircreate(n, 0, PW_TYPE_STRING))) { \
67 request_free(&stopreq); \
68 radlog(L_ERR|L_CONS, "no memory"); \
69 pairfree(&(stopreq->packet->vps)); \
72 strlcpy((char *)vp->vp_strvalue, v, sizeof vp->vp_strvalue); \
73 vp->length = strlen(v); \
74 pairadd(&(stopreq->packet->vps), vp); \
77 INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
78 IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
79 INTPAIR(PW_ACCT_DELAY_TIME, 0);
80 STRINGPAIR(PW_USER_NAME, user);
82 INTPAIR(PW_NAS_PORT, port);
83 STRINGPAIR(PW_ACCT_SESSION_ID, sessionid);
85 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
86 INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
87 } else if(proto == 'S') {
88 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
89 INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
91 INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER); /* A guess, really */
94 IPPAIR(PW_FRAMED_IP_ADDRESS, cliaddr);
95 INTPAIR(PW_ACCT_SESSION_TIME, session_time);
96 INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
97 INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
98 INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
99 INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
101 stopreq->username = userpair;
102 stopreq->password = NULL;
104 ret = rad_accounting(stopreq);
107 * We've got to clean it up by hand, because no one else will.
109 request_free(&stopreq);
117 * Check one terminal server to see if a user is logged in.
120 * 0 The user is off-line.
121 * 1 The user is logged in.
122 * 2 Some error occured.
124 int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
125 const char *session_id)
127 pid_t pid, child_pid;
135 ipaddr.ipaddr.ip4addr.s_addr = nasaddr;
140 cl = client_find_old(&ipaddr);
143 * Unknown NAS, so trusting radutmp.
145 DEBUG2("checkrad: Unknown NAS %s, not checking",
146 ip_ntoa(address, nasaddr));
151 * No nastype, or nas type 'other', trust radutmp.
153 if (!cl->nastype || (cl->nastype[0] == '\0') ||
154 (strcmp(cl->nastype, "other") == 0)) {
155 DEBUG2("checkrad: No NAS type, or type \"other\" not checking");
162 if ((pid = rad_fork()) < 0) { /* do wait for the fork'd result */
163 radlog(L_ERR, "Accounting: Failed in fork(): Cannot run checkrad\n");
168 child_pid = rad_waitpid(pid, &status);
171 * It's taking too long. Stop waiting for it.
173 * Don't bother to kill it, as we don't care what
176 if (child_pid == 0) {
177 radlog(L_ERR, "Check-TS: timeout waiting for checkrad");
182 radlog(L_ERR, "Check-TS: unknown error in waitpid()");
186 return WEXITSTATUS(status);
190 * We don't close fd's 0, 1, and 2. If we're in debugging mode,
191 * then they should go to stdout (etc), along with the other
192 * server log messages.
194 * If we're not in debugging mode, then the code in radiusd.c
195 * takes care of connecting fd's 0, 1, and 2 to /dev/null.
199 ip_ntoa(address, nasaddr);
200 snprintf(port, 11, "%u", portnum);
203 /* OS/2 can't directly execute scripts then we call the command
204 processor to execute checkrad
206 execl(getenv("COMSPEC"), "", "/C","checkrad", cl->nastype, address, port,
207 user, session_id, NULL);
209 execl(mainconfig.checkrad, "checkrad", cl->nastype, address, port,
210 user, session_id, NULL);
212 radlog(L_ERR, "Check-TS: exec %s: %s", mainconfig.checkrad, strerror(errno));
215 * Exit - 2 means "some error occured".
221 int rad_check_ts(UNUSED uint32_t nasaddr, UNUSED unsigned int portnum,
222 UNUSED const char *user, UNUSED const char *session_id)
224 radlog(L_ERR, "Simultaneous-Use is not supported");
230 /* WITH_SESSION_MGMT */
232 int session_zap(UNUSED REQUEST *request, UNUSED uint32_t nasaddr, UNUSED unsigned int port,
233 UNUSED const char *user,
234 UNUSED const char *sessionid, UNUSED uint32_t cliaddr, UNUSED char proto,
235 UNUSED int session_time)
237 return RLM_MODULE_FAIL;
240 int rad_check_ts(UNUSED uint32_t nasaddr, UNUSED unsigned int portnum,
241 UNUSED const char *user, UNUSED const char *session_id)
243 radlog(L_ERR, "Simultaneous-Use is not supported");