2 * $Id: buildreq.c,v 1.3 2002/04/02 14:09:35 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,
123 char *msg, REQUEST_INFO *info)
125 SERVER *authserver = rc_conf_srv("authserver");
130 return rc_auth_using_server(authserver, client_port, send, received,
135 * Function: rc_auth_using_server
137 * Purpose: Builds an authentication request for port id client_port
138 * with the value_pairs send and submits it to a server. You
139 * explicitly supply a server list.
141 * Returns: received value_pairs in received, messages from the server in msg
142 * and 0 on success, negative on failure as return value
146 int rc_auth_using_server(SERVER *authserver,
149 VALUE_PAIR **received,
150 char *msg, REQUEST_INFO *info)
156 int timeout = rc_conf_int("radius_timeout");
157 int retries = rc_conf_int("radius_retries");
159 data.send_pairs = send;
160 data.receive_pairs = NULL;
163 * Fill in NAS-IP-Address
166 if ((client_id = rc_own_ipaddress()) == 0)
169 if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL)
176 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
180 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
183 if (data.receive_pairs != NULL) {
184 rc_avpair_free(data.receive_pairs);
185 data.receive_pairs = NULL;
187 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
188 authserver->port[i], timeout, retries);
190 result = rc_send_server (&data, msg, info);
193 *received = data.receive_pairs;
199 * Function: rc_auth_proxy
201 * Purpose: Builds an authentication request
202 * with the value_pairs send and submits it to a server.
203 * Works for a proxy; does not add IP address, and does
204 * does not rely on config file.
206 * Returns: received value_pairs in received, messages from the server in msg
207 * and 0 on success, negative on failure as return value
211 int rc_auth_proxy(VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
216 SERVER *authserver = rc_conf_srv("authserver");
217 int timeout = rc_conf_int("radius_timeout");
218 int retries = rc_conf_int("radius_retries");
220 data.send_pairs = send;
221 data.receive_pairs = NULL;
224 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
227 if (data.receive_pairs != NULL) {
228 rc_avpair_free(data.receive_pairs);
229 data.receive_pairs = NULL;
231 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
232 authserver->port[i], timeout, retries);
234 result = rc_send_server (&data, msg, NULL);
237 *received = data.receive_pairs;
244 * Function: rc_acct_using_server
246 * Purpose: Builds an accounting request for port id client_port
247 * with the value_pairs send. You explicitly supply server list.
249 * Remarks: NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled
250 * in by this function, the rest has to be supplied.
253 int rc_acct_using_server(SERVER *acctserver,
261 time_t start_time, dtime;
264 int timeout = rc_conf_int("radius_timeout");
265 int retries = rc_conf_int("radius_retries");
267 data.send_pairs = send;
268 data.receive_pairs = NULL;
271 * Fill in NAS-IP-Address
274 if ((client_id = rc_own_ipaddress()) == 0)
277 if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL)
284 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
288 * Fill in Acct-Delay-Time
292 if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL)
295 start_time = time(NULL);
297 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
300 if (data.receive_pairs != NULL) {
301 rc_avpair_free(data.receive_pairs);
302 data.receive_pairs = NULL;
304 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
305 acctserver->port[i], timeout, retries);
307 dtime = time(NULL) - start_time;
308 rc_avpair_assign(adt_vp, &dtime, 0);
310 result = rc_send_server (&data, msg, NULL);
313 rc_avpair_free(data.receive_pairs);
321 * Purpose: Builds an accounting request for port id client_port
322 * with the value_pairs send
324 * Remarks: NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled
325 * in by this function, the rest has to be supplied.
328 int rc_acct(UINT4 client_port, VALUE_PAIR *send)
330 SERVER *acctserver = rc_conf_srv("acctserver");
331 if (!acctserver) return (ERROR_RC);
333 return rc_acct_using_server(acctserver, client_port, send);
337 * Function: rc_acct_proxy
339 * Purpose: Builds an accounting request with the value_pairs send
343 int rc_acct_proxy(VALUE_PAIR *send)
349 SERVER *acctserver = rc_conf_srv("authserver");
350 int timeout = rc_conf_int("radius_timeout");
351 int retries = rc_conf_int("radius_retries");
353 data.send_pairs = send;
354 data.receive_pairs = NULL;
357 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
360 if (data.receive_pairs != NULL) {
361 rc_avpair_free(data.receive_pairs);
362 data.receive_pairs = NULL;
364 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
365 acctserver->port[i], timeout, retries);
367 result = rc_send_server (&data, msg, NULL);
370 rc_avpair_free(data.receive_pairs);
378 * Purpose: ask the server hostname on the specified port for a
383 int rc_check(char *host, unsigned short port, char *msg)
387 UINT4 client_id, service_type;
388 int timeout = rc_conf_int("radius_timeout");
389 int retries = rc_conf_int("radius_retries");
391 data.send_pairs = data.receive_pairs = NULL;
394 * Fill in NAS-IP-Address, although it isn't neccessary
397 if ((client_id = rc_own_ipaddress()) == 0)
400 rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE);
403 * Fill in Service-Type
406 service_type = PW_ADMINISTRATIVE;
407 rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE);
409 rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries);
410 result = rc_send_server (&data, msg, NULL);
412 rc_avpair_free(data.receive_pairs);