2 * $Id: buildreq.c,v 1.2 2002/03/01 14:39:19 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,
125 SERVER *authserver = rc_conf_srv("authserver");
130 return rc_auth_using_server(authserver, client_port, send, received, msg);
134 * Function: rc_auth_using_server
136 * Purpose: Builds an authentication request for port id client_port
137 * with the value_pairs send and submits it to a server. You
138 * explicitly supply a server list.
140 * Returns: received value_pairs in received, messages from the server in msg
141 * and 0 on success, negative on failure as return value
145 int rc_auth_using_server(SERVER *authserver,
148 VALUE_PAIR **received,
155 int timeout = rc_conf_int("radius_timeout");
156 int retries = rc_conf_int("radius_retries");
158 data.send_pairs = send;
159 data.receive_pairs = NULL;
162 * Fill in NAS-IP-Address
165 if ((client_id = rc_own_ipaddress()) == 0)
168 if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL)
175 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
179 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
182 if (data.receive_pairs != NULL) {
183 rc_avpair_free(data.receive_pairs);
184 data.receive_pairs = NULL;
186 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
187 authserver->port[i], timeout, retries);
189 result = rc_send_server (&data, msg);
192 *received = data.receive_pairs;
198 * Function: rc_auth_proxy
200 * Purpose: Builds an authentication request
201 * with the value_pairs send and submits it to a server.
202 * Works for a proxy; does not add IP address, and does
203 * does not rely on config file.
205 * Returns: received value_pairs in received, messages from the server in msg
206 * and 0 on success, negative on failure as return value
210 int rc_auth_proxy(VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
215 SERVER *authserver = rc_conf_srv("authserver");
216 int timeout = rc_conf_int("radius_timeout");
217 int retries = rc_conf_int("radius_retries");
219 data.send_pairs = send;
220 data.receive_pairs = NULL;
223 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
226 if (data.receive_pairs != NULL) {
227 rc_avpair_free(data.receive_pairs);
228 data.receive_pairs = NULL;
230 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
231 authserver->port[i], timeout, retries);
233 result = rc_send_server (&data, msg);
236 *received = data.receive_pairs;
243 * Function: rc_acct_using_server
245 * Purpose: Builds an accounting request for port id client_port
246 * with the value_pairs send. You explicitly supply server list.
248 * Remarks: NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled
249 * in by this function, the rest has to be supplied.
252 int rc_acct_using_server(SERVER *acctserver,
260 time_t start_time, dtime;
263 int timeout = rc_conf_int("radius_timeout");
264 int retries = rc_conf_int("radius_retries");
266 data.send_pairs = send;
267 data.receive_pairs = NULL;
270 * Fill in NAS-IP-Address
273 if ((client_id = rc_own_ipaddress()) == 0)
276 if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL)
283 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
287 * Fill in Acct-Delay-Time
291 if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL)
294 start_time = time(NULL);
296 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
299 if (data.receive_pairs != NULL) {
300 rc_avpair_free(data.receive_pairs);
301 data.receive_pairs = NULL;
303 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
304 acctserver->port[i], timeout, retries);
306 dtime = time(NULL) - start_time;
307 rc_avpair_assign(adt_vp, &dtime, 0);
309 result = rc_send_server (&data, msg);
312 rc_avpair_free(data.receive_pairs);
320 * Purpose: Builds an accounting request for port id client_port
321 * with the value_pairs send
323 * Remarks: NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled
324 * in by this function, the rest has to be supplied.
327 int rc_acct(UINT4 client_port, VALUE_PAIR *send)
329 SERVER *acctserver = rc_conf_srv("acctserver");
330 if (!acctserver) return (ERROR_RC);
332 return rc_acct_using_server(acctserver, client_port, send);
336 * Function: rc_acct_proxy
338 * Purpose: Builds an accounting request with the value_pairs send
342 int rc_acct_proxy(VALUE_PAIR *send)
348 SERVER *acctserver = rc_conf_srv("authserver");
349 int timeout = rc_conf_int("radius_timeout");
350 int retries = rc_conf_int("radius_retries");
352 data.send_pairs = send;
353 data.receive_pairs = NULL;
356 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
359 if (data.receive_pairs != NULL) {
360 rc_avpair_free(data.receive_pairs);
361 data.receive_pairs = NULL;
363 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
364 acctserver->port[i], timeout, retries);
366 result = rc_send_server (&data, msg);
369 rc_avpair_free(data.receive_pairs);
377 * Purpose: ask the server hostname on the specified port for a
382 int rc_check(char *host, unsigned short port, char *msg)
386 UINT4 client_id, service_type;
387 int timeout = rc_conf_int("radius_timeout");
388 int retries = rc_conf_int("radius_retries");
390 data.send_pairs = data.receive_pairs = NULL;
393 * Fill in NAS-IP-Address, although it isn't neccessary
396 if ((client_id = rc_own_ipaddress()) == 0)
399 rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE);
402 * Fill in Service-Type
405 service_type = PW_ADMINISTRATIVE;
406 rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE);
408 rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries);
409 result = rc_send_server (&data, msg);
411 rc_avpair_free(data.receive_pairs);