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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2000 The FreeRADIUS server project
37 /* End a session by faking a Stop packet to all accounting modules */
38 int session_zap(uint32_t nasaddr, int port, const char *user,
39 const char *sessionid, uint32_t cliaddr, char proto, time_t t)
41 static unsigned char id = 0;
44 RADIUS_PACKET *stoppkt;
45 VALUE_PAIR *vp, *userpair;
48 stoppkt = rad_malloc(sizeof *stoppkt);
49 memset(stoppkt, 0, sizeof stoppkt);
51 stoppkt->sockfd = acctfd;
52 stoppkt->code = PW_ACCOUNTING_REQUEST;
54 stoppkt->timestamp = t?t:time(0);
57 /* Hold your breath */
58 #define PAIR(n,v,t,e) do { \
59 if(!(vp = paircreate(n, t))) { \
60 radlog(L_ERR|L_CONS, "no memory"); \
61 pairfree(&stoppkt->vps); \
65 pairadd(&stoppkt->vps, vp); \
67 #define INTPAIR(n,v) PAIR(n,v,PW_TYPE_INTEGER,lvalue)
68 #define IPPAIR(n,v) PAIR(n,v,PW_TYPE_IPADDR,lvalue)
69 #define STRINGPAIR(n,v) do { \
70 if(!(vp = paircreate(n, PW_TYPE_STRING))) { \
71 radlog(L_ERR|L_CONS, "no memory"); \
72 pairfree(&stoppkt->vps); \
75 strNcpy((char *)vp->strvalue, v, sizeof vp->strvalue); \
76 vp->length = strlen(v); \
77 pairadd(&stoppkt->vps, vp); \
80 INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
81 IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
82 INTPAIR(PW_ACCT_DELAY_TIME, 0);
83 STRINGPAIR(PW_USER_NAME, user);
85 INTPAIR(PW_NAS_PORT_ID, port);
86 STRINGPAIR(PW_ACCT_SESSION_ID, sessionid);
88 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
89 INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
90 } else if(proto == 'S') {
91 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
92 INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
94 INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER); /* A guess, really */
97 IPPAIR(PW_FRAMED_IP_ADDRESS, cliaddr);
98 INTPAIR(PW_ACCT_SESSION_TIME, 0);
99 INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
100 INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
101 INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
102 INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
104 stopreq = rad_malloc(sizeof *stopreq);
105 memset(stopreq, 0, sizeof *stopreq);
107 stopreq->magic = REQUEST_MAGIC;
109 stopreq->packet = stoppkt;
110 stopreq->proxy = NULL;
111 stopreq->reply = NULL;
112 stopreq->proxy_reply = NULL;
113 stopreq->config_items = NULL;
114 stopreq->username = userpair;
115 stopreq->password = NULL;
116 stopreq->timestamp = stoppkt->timestamp;
117 stopreq->number = 0; /* FIXME */
118 stopreq->child_pid = NO_SUCH_CHILD_PID;
119 stopreq->container = NULL;
120 ret = rad_process(stopreq, spawn_flag);
127 * Timeout handler (10 secs)
129 static volatile int got_alrm;
130 static void alrm_handler(int s)
137 * Check one terminal server to see if a user is logged in.
139 int rad_check_ts(uint32_t nasaddr, int portnum, const char *user,
140 const char *session_id)
147 void (*handler)(int);
152 if ((nas = nas_find(nasaddr)) == NULL) {
153 radlog(L_ERR, "Accounting: unknown NAS");
160 handler = signal(SIGCHLD, SIG_DFL);
161 if ((pid = fork()) < 0) {
162 radlog(L_ERR, "Accounting: fork: %s", strerror(errno));
163 signal(SIGCHLD, handler);
169 * Parent - Wait for checkrad to terminate.
170 * We timeout in 10 seconds.
173 signal(SIGALRM, alrm_handler);
175 while((e = waitpid(pid, &st, 0)) != pid)
176 if (e < 0 && (errno != EINTR || got_alrm))
179 signal(SIGCHLD, handler);
184 radlog(L_ERR, "Check-TS: timeout waiting for checkrad");
188 radlog(L_ERR, "Check-TS: unknown error in waitpid()");
191 return WEXITSTATUS(st);
195 * Child - exec checklogin with the right parameters.
197 for (n = 32; n >= 3; n--)
200 ip_ntoa(address, nasaddr);
201 sprintf(port, "%d", portnum);
204 /* OS/2 can't directly execute scripts then we call the command
205 processor to execute checkrad
207 execl(getenv("COMSPEC"), "", "/C","checkrad",nas->nastype, address, port,
208 user, session_id, NULL);
210 execl(CHECKRAD, "checkrad",nas->nastype, address, port,
211 user, session_id, NULL);
213 radlog(L_ERR, "Check-TS: exec %s: %s", CHECKRAD, strerror(errno));
216 * Exit - 2 means "some error occured".