Massively cleaned up #include's, so they're in a consistent
[freeradius.git] / src / main / session.c
1 /*
2  * session.c    session management
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 #include        <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include        <freeradius-devel/radiusd.h>
27 #include        <freeradius-devel/rad_assert.h>
28
29 #include        <signal.h>
30 #include        <sys/wait.h>
31
32 /*
33  *      End a session by faking a Stop packet to all accounting modules.
34  */
35 int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
36                 const char *user,
37                 const char *sessionid, uint32_t cliaddr, char proto,
38                 int session_time)
39 {
40         REQUEST *stopreq;
41         VALUE_PAIR *vp, *userpair;
42         int ret;
43
44         stopreq = request_alloc_fake(request);
45         stopreq->packet->code = PW_ACCOUNTING_REQUEST; /* just to be safe */
46         rad_assert(stopreq != NULL);
47
48         /* Hold your breath */
49 #define PAIR(n,v,t,e) do { \
50                 if(!(vp = paircreate(n, t))) { \
51                         radlog(L_ERR|L_CONS, "no memory"); \
52                         pairfree(&(stopreq->packet->vps)); \
53                         return 0; \
54                 } \
55                 vp->e = v; \
56                 pairadd(&(stopreq->packet->vps), vp); \
57         } while(0)
58 #define INTPAIR(n,v) PAIR(n,v,PW_TYPE_INTEGER,lvalue)
59 #define IPPAIR(n,v) PAIR(n,v,PW_TYPE_IPADDR,lvalue)
60 #define STRINGPAIR(n,v) do { \
61         if(!(vp = paircreate(n, PW_TYPE_STRING))) { \
62                 radlog(L_ERR|L_CONS, "no memory"); \
63                 pairfree(&(stopreq->packet->vps)); \
64                 return 0; \
65         } \
66         strlcpy((char *)vp->vp_strvalue, v, sizeof vp->vp_strvalue); \
67         vp->length = strlen(v); \
68         pairadd(&(stopreq->packet->vps), vp); \
69         } while(0)
70
71         INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
72         IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
73         INTPAIR(PW_ACCT_DELAY_TIME, 0);
74         STRINGPAIR(PW_USER_NAME, user);
75         userpair = vp;
76         INTPAIR(PW_NAS_PORT, port);
77         STRINGPAIR(PW_ACCT_SESSION_ID, sessionid);
78         if(proto == 'P') {
79                 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
80                 INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
81         } else if(proto == 'S') {
82                 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
83                 INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
84         } else {
85                 INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER); /* A guess, really */
86         }
87         if(cliaddr != 0)
88                 IPPAIR(PW_FRAMED_IP_ADDRESS, cliaddr);
89         INTPAIR(PW_ACCT_SESSION_TIME, session_time);
90         INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
91         INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
92         INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
93         INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
94
95         stopreq->username = userpair;
96         stopreq->password = NULL;
97
98         ret = rad_accounting(stopreq);
99
100         /*
101          *  We've got to clean it up by hand, because no one else will.
102          */
103         request_free(&stopreq);
104
105         return ret;
106 }
107
108
109 /*
110  *      Check one terminal server to see if a user is logged in.
111  *
112  *      Return values:
113  *              0 The user is off-line.
114  *              1 The user is logged in.
115  *              2 Some error occured.
116  */
117 int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
118                  const char *session_id)
119 {
120         pid_t   pid, child_pid;
121         int     status;
122         int     n;
123         char    address[16];
124         char    port[11];
125         RADCLIENT *cl;
126         lrad_ipaddr_t ipaddr;
127
128         ipaddr.af = AF_INET;
129         ipaddr.ipaddr.ip4addr.s_addr = nasaddr;
130
131         /*
132          *      Find NAS type.
133          */
134         cl = client_find_old(&ipaddr);
135         if (!cl) {
136                 /*
137                  *  Unknown NAS, so trusting radutmp.
138                  */
139                 DEBUG2("checkrad: Unknown NAS %s, not checking",
140                        ip_ntoa(address, nasaddr));
141                 return 1;
142         }
143
144         /*
145          *  No nastype, or nas type 'other', trust radutmp.
146          */
147         if (!cl->nastype || (cl->nastype[0] == '\0') ||
148             (strcmp(cl->nastype, "other") == 0)) {
149                 DEBUG2("checkrad: No NAS type, or type \"other\" not checking");
150                 return 1;
151         }
152
153         /*
154          *      Fork.
155          */
156         if ((pid = rad_fork()) < 0) { /* do wait for the fork'd result */
157                 radlog(L_ERR, "Accounting: Failed in fork(): Cannot run checkrad\n");
158                 return 2;
159         }
160
161         if (pid > 0) {
162                 child_pid = rad_waitpid(pid, &status);
163
164                 /*
165                  *      It's taking too long.  Stop waiting for it.
166                  *
167                  *      Don't bother to kill it, as we don't care what
168                  *      happens to it now.
169                  */
170                 if (child_pid == 0) {
171                         radlog(L_ERR, "Check-TS: timeout waiting for checkrad");
172                         return 2;
173                 }
174
175                 if (child_pid < 0) {
176                         radlog(L_ERR, "Check-TS: unknown error in waitpid()");
177                         return 2;
178                 }
179
180                 return WEXITSTATUS(status);
181         }
182
183         /*
184          *  We don't close fd's 0, 1, and 2.  If we're in debugging mode,
185          *  then they should go to stdout (etc), along with the other
186          *  server log messages.
187          *
188          *  If we're not in debugging mode, then the code in radiusd.c
189          *  takes care of connecting fd's 0, 1, and 2 to /dev/null.
190          */
191         closefrom(3);
192
193         ip_ntoa(address, nasaddr);
194         snprintf(port, 11, "%u", portnum);
195
196 #ifdef __EMX__
197         /* OS/2 can't directly execute scripts then we call the command
198            processor to execute checkrad
199         */
200         execl(getenv("COMSPEC"), "", "/C","checkrad", cl->nastype, address, port,
201                 user, session_id, NULL);
202 #else
203         execl(mainconfig.checkrad, "checkrad", cl->nastype, address, port,
204                 user, session_id, NULL);
205 #endif
206         radlog(L_ERR, "Check-TS: exec %s: %s", mainconfig.checkrad, strerror(errno));
207
208         /*
209          *      Exit - 2 means "some error occured".
210          */
211         exit(2);
212         return 2;
213 }