Add these files, used with TDB.
[mpls-ppp.git] / pppd / plugins / radius / radiusclient / lib / buildreq.c
bloba24a20ba66c5b1c4ead9e5ed1249c56a0d78c481
1 /*
2 * $Id: buildreq.c,v 1.5 2003/04/25 08:10:46 fcusack 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.
12 #include <config.h>
13 #include <includes.h>
14 #include <radiusclient.h>
16 unsigned char rc_get_seqnbr(void);
19 * Function: rc_get_nas_id
21 * Purpose: fills in NAS-Identifier or NAS-IP-Address in request
25 int rc_get_nas_id(VALUE_PAIR **sendpairs)
27 UINT4 client_id;
28 char *nasid;
30 nasid = rc_conf_str("nas_identifier");
31 if (strlen(nasid)) {
33 * Fill in NAS-Identifier
35 if (rc_avpair_add(sendpairs, PW_NAS_IDENTIFIER, nasid, 0,
36 VENDOR_NONE) == NULL)
37 return (ERROR_RC);
39 return (OK_RC);
41 } else {
43 * Fill in NAS-IP-Address
45 if ((client_id = rc_own_ipaddress()) == 0)
46 return (ERROR_RC);
48 if (rc_avpair_add(sendpairs, PW_NAS_IP_ADDRESS, &client_id,
49 0, VENDOR_NONE) == NULL)
50 return (ERROR_RC);
53 return (OK_RC);
57 * Function: rc_buildreq
59 * Purpose: builds a skeleton RADIUS request using information from the
60 * config file.
64 void rc_buildreq(SEND_DATA *data, int code, char *server, unsigned short port,
65 int timeout, int retries)
67 data->server = server;
68 data->svc_port = port;
69 data->seq_nbr = rc_get_seqnbr();
70 data->timeout = timeout;
71 data->retries = retries;
72 data->code = code;
76 * Function: rc_guess_seqnbr
78 * Purpose: return a random sequence number
82 static unsigned char rc_guess_seqnbr(void)
84 srandom((unsigned int)(time(NULL)+getpid()));
85 return (unsigned char)(random() & UCHAR_MAX);
89 * Function: rc_get_seqnbr
91 * Purpose: generate a sequence number
95 unsigned char rc_get_seqnbr(void)
97 FILE *sf;
98 int tries = 1;
99 int seq_nbr, pos;
100 char *seqfile = rc_conf_str("seqfile");
102 if ((sf = fopen(seqfile, "a+")) == NULL)
104 rc_log(LOG_ERR,"rc_get_seqnbr: couldn't open sequence file %s: %s", seqfile, strerror(errno));
105 /* well, so guess a sequence number */
106 return rc_guess_seqnbr();
109 while (do_lock_exclusive(fileno(sf))!= 0)
111 if (errno != EWOULDBLOCK) {
112 rc_log(LOG_ERR, "rc_get_seqnbr: flock failure: %s: %s", seqfile, strerror(errno));
113 fclose(sf);
114 return rc_guess_seqnbr();
116 tries++;
117 if (tries <= 10)
118 rc_mdelay(500);
119 else
120 break;
123 if (tries > 10) {
124 rc_log(LOG_ERR,"rc_get_seqnbr: couldn't get lock after %d tries: %s", tries-1, seqfile);
125 fclose(sf);
126 return rc_guess_seqnbr();
129 pos = ftell(sf);
130 rewind(sf);
131 if (fscanf(sf, "%d", &seq_nbr) != 1) {
132 if (pos != ftell(sf)) {
133 /* file was not empty */
134 rc_log(LOG_ERR,"rc_get_seqnbr: fscanf failure: %s", seqfile);
136 seq_nbr = rc_guess_seqnbr();
139 rewind(sf);
140 ftruncate(fileno(sf),0);
141 fprintf(sf,"%d\n", (seq_nbr+1) & UCHAR_MAX);
143 fflush(sf); /* fflush because a process may read it between the do_unlock and fclose */
145 if (do_unlock(fileno(sf)) != 0)
146 rc_log(LOG_ERR, "rc_get_seqnbr: couldn't release lock on %s: %s", seqfile, strerror(errno));
148 fclose(sf);
150 return (unsigned char)seq_nbr;
154 * Function: rc_auth
156 * Purpose: Builds an authentication request for port id client_port
157 * with the value_pairs send and submits it to a server
159 * Returns: received value_pairs in received, messages from the server in msg
160 * and 0 on success, negative on failure as return value
164 int rc_auth(UINT4 client_port, VALUE_PAIR *send, VALUE_PAIR **received,
165 char *msg, REQUEST_INFO *info)
167 SERVER *authserver = rc_conf_srv("authserver");
169 if (!authserver) {
170 return (ERROR_RC);
172 return rc_auth_using_server(authserver, client_port, send, received,
173 msg, info);
177 * Function: rc_auth_using_server
179 * Purpose: Builds an authentication request for port id client_port
180 * with the value_pairs send and submits it to a server. You
181 * explicitly supply a server list.
183 * Returns: received value_pairs in received, messages from the server in msg
184 * and 0 on success, negative on failure as return value
188 int rc_auth_using_server(SERVER *authserver,
189 UINT4 client_port,
190 VALUE_PAIR *send,
191 VALUE_PAIR **received,
192 char *msg, REQUEST_INFO *info)
194 SEND_DATA data;
195 int result;
196 int i;
197 int timeout = rc_conf_int("radius_timeout");
198 int retries = rc_conf_int("radius_retries");
200 data.send_pairs = send;
201 data.receive_pairs = NULL;
204 * Fill in NAS-IP-Address or NAS-Identifier
207 if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
208 return (ERROR_RC);
211 * Fill in NAS-Port
214 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
215 return (ERROR_RC);
217 result = ERROR_RC;
218 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
219 ; i++)
221 if (data.receive_pairs != NULL) {
222 rc_avpair_free(data.receive_pairs);
223 data.receive_pairs = NULL;
225 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
226 authserver->port[i], timeout, retries);
228 result = rc_send_server (&data, msg, info);
231 *received = data.receive_pairs;
233 return result;
237 * Function: rc_auth_proxy
239 * Purpose: Builds an authentication request
240 * with the value_pairs send and submits it to a server.
241 * Works for a proxy; does not add IP address, and does
242 * does not rely on config file.
244 * Returns: received value_pairs in received, messages from the server in msg
245 * and 0 on success, negative on failure as return value
249 int rc_auth_proxy(VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
251 SEND_DATA data;
252 int result;
253 int i;
254 SERVER *authserver = rc_conf_srv("authserver");
255 int timeout = rc_conf_int("radius_timeout");
256 int retries = rc_conf_int("radius_retries");
258 data.send_pairs = send;
259 data.receive_pairs = NULL;
261 result = ERROR_RC;
262 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
263 ; i++)
265 if (data.receive_pairs != NULL) {
266 rc_avpair_free(data.receive_pairs);
267 data.receive_pairs = NULL;
269 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
270 authserver->port[i], timeout, retries);
272 result = rc_send_server (&data, msg, NULL);
275 *received = data.receive_pairs;
277 return result;
282 * Function: rc_acct_using_server
284 * Purpose: Builds an accounting request for port id client_port
285 * with the value_pairs send. You explicitly supply server list.
287 * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
288 * filled in by this function, the rest has to be supplied.
291 int rc_acct_using_server(SERVER *acctserver,
292 UINT4 client_port,
293 VALUE_PAIR *send)
295 SEND_DATA data;
296 VALUE_PAIR *adt_vp;
297 int result;
298 time_t start_time, dtime;
299 char msg[4096];
300 int i;
301 int timeout = rc_conf_int("radius_timeout");
302 int retries = rc_conf_int("radius_retries");
304 data.send_pairs = send;
305 data.receive_pairs = NULL;
308 * Fill in NAS-IP-Address or NAS-Identifier
311 if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
312 return (ERROR_RC);
315 * Fill in NAS-Port
318 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
319 return (ERROR_RC);
322 * Fill in Acct-Delay-Time
325 dtime = 0;
326 if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL)
327 return (ERROR_RC);
329 start_time = time(NULL);
330 result = ERROR_RC;
331 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
332 ; i++)
334 if (data.receive_pairs != NULL) {
335 rc_avpair_free(data.receive_pairs);
336 data.receive_pairs = NULL;
338 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
339 acctserver->port[i], timeout, retries);
341 dtime = time(NULL) - start_time;
342 rc_avpair_assign(adt_vp, &dtime, 0);
344 result = rc_send_server (&data, msg, NULL);
347 rc_avpair_free(data.receive_pairs);
349 return result;
353 * Function: rc_acct
355 * Purpose: Builds an accounting request for port id client_port
356 * with the value_pairs send
358 * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
359 * filled in by this function, the rest has to be supplied.
362 int rc_acct(UINT4 client_port, VALUE_PAIR *send)
364 SERVER *acctserver = rc_conf_srv("acctserver");
365 if (!acctserver) return (ERROR_RC);
367 return rc_acct_using_server(acctserver, client_port, send);
371 * Function: rc_acct_proxy
373 * Purpose: Builds an accounting request with the value_pairs send
377 int rc_acct_proxy(VALUE_PAIR *send)
379 SEND_DATA data;
380 int result;
381 char msg[4096];
382 int i;
383 SERVER *acctserver = rc_conf_srv("authserver");
384 int timeout = rc_conf_int("radius_timeout");
385 int retries = rc_conf_int("radius_retries");
387 data.send_pairs = send;
388 data.receive_pairs = NULL;
390 result = ERROR_RC;
391 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
392 ; i++)
394 if (data.receive_pairs != NULL) {
395 rc_avpair_free(data.receive_pairs);
396 data.receive_pairs = NULL;
398 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
399 acctserver->port[i], timeout, retries);
401 result = rc_send_server (&data, msg, NULL);
404 rc_avpair_free(data.receive_pairs);
406 return result;
410 * Function: rc_check
412 * Purpose: ask the server hostname on the specified port for a
413 * status message
417 int rc_check(char *host, unsigned short port, char *msg)
419 SEND_DATA data;
420 int result;
421 UINT4 service_type;
422 int timeout = rc_conf_int("radius_timeout");
423 int retries = rc_conf_int("radius_retries");
425 data.send_pairs = data.receive_pairs = NULL;
428 * Fill in NAS-IP-Address or NAS-Identifier,
429 * although it isn't neccessary
432 if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
433 return (ERROR_RC);
436 * Fill in Service-Type
439 service_type = PW_ADMINISTRATIVE;
440 rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE);
442 rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries);
443 result = rc_send_server (&data, msg, NULL);
445 rc_avpair_free(data.receive_pairs);
447 return result;