2 * $Id: buildreq.c,v 1.1 2002/01/22 16:03:02 dfs Exp $
4 * Copyright (C) 1995,1997 Lars Fenneberg
6 * See the file COPYRIGHT for the respective terms and conditions.
7 * If the file is missing contact me at lf@elemental.net
8 * and I'll send you a copy.
14 #include <radiusclient.h>
16 unsigned char rc_get_seqnbr(void);
19 * Function: rc_buildreq
21 * Purpose: builds a skeleton RADIUS request using information from the
26 void rc_buildreq(SEND_DATA *data, int code, char *server, unsigned short port,
27 int timeout, int retries)
29 data->server = server;
30 data->svc_port = port;
31 data->seq_nbr = rc_get_seqnbr();
32 data->timeout = timeout;
33 data->retries = retries;
38 * Function: rc_guess_seqnbr
40 * Purpose: return a random sequence number
44 static unsigned char rc_guess_seqnbr(void)
46 srandom((unsigned int)(time(NULL)+getpid()));
47 return (unsigned char)(random() & UCHAR_MAX);
51 * Function: rc_get_seqnbr
53 * Purpose: generate a sequence number
57 unsigned char rc_get_seqnbr(void)
62 char *seqfile = rc_conf_str("seqfile");
64 if ((sf = fopen(seqfile, "a+")) == NULL)
66 rc_log(LOG_ERR,"rc_get_seqnbr: couldn't open sequence file %s: %s", seqfile, strerror(errno));
67 /* well, so guess a sequence number */
68 return rc_guess_seqnbr();
71 while (do_lock_exclusive(fileno(sf))!= 0)
73 if (errno != EWOULDBLOCK) {
74 rc_log(LOG_ERR, "rc_get_seqnbr: flock failure: %s: %s", seqfile, strerror(errno));
76 return rc_guess_seqnbr();
86 rc_log(LOG_ERR,"rc_get_seqnbr: couldn't get lock after %d tries: %s", tries-1, seqfile);
88 return rc_guess_seqnbr();
92 if (fscanf(sf, "%d", &seq_nbr) != 1) {
93 rc_log(LOG_ERR,"rc_get_seqnbr: fscanf failure: %s", seqfile);
94 seq_nbr = rc_guess_seqnbr();
98 ftruncate(fileno(sf),0);
99 fprintf(sf,"%d\n", (seq_nbr+1) & UCHAR_MAX);
101 fflush(sf); /* fflush because a process may read it between the do_unlock and fclose */
103 if (do_unlock(fileno(sf)) != 0)
104 rc_log(LOG_ERR, "rc_get_seqnbr: couldn't release lock on %s: %s", seqfile, strerror(errno));
108 return (unsigned char)seq_nbr;
114 * Purpose: Builds an authentication request for port id client_port
115 * with the value_pairs send and submits it to a server
117 * Returns: received value_pairs in received, messages from the server in msg
118 * and 0 on success, negative on failure as return value
122 int rc_auth(UINT4 client_port, VALUE_PAIR *send, VALUE_PAIR **received,
129 SERVER *authserver = rc_conf_srv("authserver");
130 int timeout = rc_conf_int("radius_timeout");
131 int retries = rc_conf_int("radius_retries");
133 data.send_pairs = send;
134 data.receive_pairs = NULL;
137 * Fill in NAS-IP-Address
140 if ((client_id = rc_own_ipaddress()) == 0)
143 if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL)
150 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
154 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
157 if (data.receive_pairs != NULL) {
158 rc_avpair_free(data.receive_pairs);
159 data.receive_pairs = NULL;
161 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
162 authserver->port[i], timeout, retries);
164 result = rc_send_server (&data, msg);
167 *received = data.receive_pairs;
173 * Function: rc_auth_proxy
175 * Purpose: Builds an authentication request
176 * with the value_pairs send and submits it to a server.
177 * Works for a proxy; does not add IP address, and does
178 * does not rely on config file.
180 * Returns: received value_pairs in received, messages from the server in msg
181 * and 0 on success, negative on failure as return value
185 int rc_auth_proxy(VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
190 SERVER *authserver = rc_conf_srv("authserver");
191 int timeout = rc_conf_int("radius_timeout");
192 int retries = rc_conf_int("radius_retries");
194 data.send_pairs = send;
195 data.receive_pairs = NULL;
198 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
201 if (data.receive_pairs != NULL) {
202 rc_avpair_free(data.receive_pairs);
203 data.receive_pairs = NULL;
205 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
206 authserver->port[i], timeout, retries);
208 result = rc_send_server (&data, msg);
211 *received = data.receive_pairs;
220 * Purpose: Builds an accounting request for port id client_port
221 * with the value_pairs send
223 * Remarks: NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled
224 * in by this function, the rest has to be supplied.
227 int rc_acct(UINT4 client_port, VALUE_PAIR *send)
233 time_t start_time, dtime;
236 SERVER *acctserver = rc_conf_srv("acctserver");
237 int timeout = rc_conf_int("radius_timeout");
238 int retries = rc_conf_int("radius_retries");
240 data.send_pairs = send;
241 data.receive_pairs = NULL;
244 * Fill in NAS-IP-Address
247 if ((client_id = rc_own_ipaddress()) == 0)
250 if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL)
257 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
261 * Fill in Acct-Delay-Time
265 if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL)
268 start_time = time(NULL);
270 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
273 if (data.receive_pairs != NULL) {
274 rc_avpair_free(data.receive_pairs);
275 data.receive_pairs = NULL;
277 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
278 acctserver->port[i], timeout, retries);
280 dtime = time(NULL) - start_time;
281 rc_avpair_assign(adt_vp, &dtime, 0);
283 result = rc_send_server (&data, msg);
286 rc_avpair_free(data.receive_pairs);
292 * Function: rc_acct_proxy
294 * Purpose: Builds an accounting request with the value_pairs send
298 int rc_acct_proxy(VALUE_PAIR *send)
304 SERVER *acctserver = rc_conf_srv("authserver");
305 int timeout = rc_conf_int("radius_timeout");
306 int retries = rc_conf_int("radius_retries");
308 data.send_pairs = send;
309 data.receive_pairs = NULL;
312 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
315 if (data.receive_pairs != NULL) {
316 rc_avpair_free(data.receive_pairs);
317 data.receive_pairs = NULL;
319 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
320 acctserver->port[i], timeout, retries);
322 result = rc_send_server (&data, msg);
325 rc_avpair_free(data.receive_pairs);
333 * Purpose: ask the server hostname on the specified port for a
338 int rc_check(char *host, unsigned short port, char *msg)
342 UINT4 client_id, service_type;
343 int timeout = rc_conf_int("radius_timeout");
344 int retries = rc_conf_int("radius_retries");
346 data.send_pairs = data.receive_pairs = NULL;
349 * Fill in NAS-IP-Address, although it isn't neccessary
352 if ((client_id = rc_own_ipaddress()) == 0)
355 rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE);
358 * Fill in Service-Type
361 service_type = PW_ADMINISTRATIVE;
362 rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE);
364 rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries);
365 result = rc_send_server (&data, msg);
367 rc_avpair_free(data.receive_pairs);