done
distclean: clean
- rm -f config.cache config.log config.status
+ rm -f config.cache config.log config.status libtool \
+ src/include/radpaths.h src/include/stamp-h \
+ src/libltdl/config.log src/libltdl/config.status \
+ src/libltdl/libtool
-find . ! -name configure.in -name \*.in -print | \
sed 's/\.in$$//' | \
while read file; do rm -f $$file; done
extern int acct_port;
extern int proxy_port;
extern int proxyfd;
+extern int proxy_retry_count;
+extern int proxy_retry_delay;
/*
* Function prototypes.
/* proxy.c */
int proxy_receive(REQUEST *request);
int proxy_send(REQUEST *request);
-struct timeval *proxy_setuptimeout(struct timeval *);
-void proxy_retry(void);
/* auth.c */
char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli);
if ((pair = pairfind(request->packet->vps, PW_NAS_PORT_ID)) != NULL)
port = pair->lvalue;
- snprintf(buf, buflen, "from nas %.128s/S%d%s%.128s",
+ snprintf(buf, buflen, "from nas %.128s port %d%s%.128s",
nas_name2(request->packet), port,
(do_cli ? " cli " : ""), (do_cli ? (char *)cli->strvalue : ""));
#
# The finger response format is version-dependent. To do this *right*, you
# need to know exactly where the port number and username are. I know that
-# for 1.7.2, but for others I just guess.
+# for 1.7.2, and 3.0.4 but for others I just guess.
# Oh yeah and on top of it all, the thing truncates usernames. --Pac.
#
-# 1.7.2 looks like this:
+# 1.7.2 and 3.0.4 both look like this:
#
# 0 0 000 00:56 luser pppfsm Incoming PPP, ppp00, 10.0.0.1
#
# and the truncated ones look like this:
#
-# 25 0 000 00:15 longnameluse..pppfsm Incoming PPP, ppp25, 209.43.25.164
+# 25 0 000 00:15 longnameluse..pppfsm Incoming PPP, ppp25, 10.0.0.26
#
# Yes, the fields run together. Long Usernames Considered Harmful.
#
$ver = $1;
next;
}
- # Check for 1.7.2
- if ($ver eq '1.7.2') {
+ # Check for known versions
+ if ($ver eq '1.7.2' || $ver eq '3.0.4') {
if (/^\Q$ARGV[2]\E\s+\S+\s+\S+\s+\S+\s+\Q$trunc\E(\s+|\.\.)/) {
close FD;
return 1;
static uint32_t proxy_id = 1;
-static REQUEST *proxy_requests = NULL;
-
static const int allowed[] = {
PW_SERVICE_TYPE,
PW_FRAMED_PROTOCOL,
char *realmname;
int replicating;
+#if 0 /* This looks bad to me... the timestamp is used below to figure the
+ * next_try. The request needs to "hang around" until either the
+ * other server sends a reply or the retry count has been exceeded.
+ * Until then, it should not be eligible for the time-based cleanup.
+ * --Pac. */
/*
* Ensure that the request hangs around for a little
* while longer.
* FIXME: This is a hack... it should be more intelligent.
*/
request->timestamp += 5;
+#endif
/* Look for proxy/replicate signs */
/* FIXME - What to do if multiple Proxy-To/Replicate-To attrs are
if (proxypair) {
realmpair = proxypair;
replicating = 0;
- } else if( replicatepair) {
+ } else if (replicatepair) {
realmpair = replicatepair;
replicating = 1;
} else {
rad_send(request->proxy, (char *)realm->secret);
memcpy(request->proxysecret, realm->secret, sizeof(request->proxysecret));
request->proxy_is_replicate = replicating;
- request->proxy_try_count = RETRY_COUNT - 1;
- request->proxy_next_try = request->timestamp + RETRY_DELAY;
+ request->proxy_try_count = proxy_retry_count - 1;
+ request->proxy_next_try = request->timestamp + proxy_retry_delay;
delaypair = pairfind(vps, PW_ACCT_DELAY_TIME);
request->proxy->timestamp = request->timestamp - (delaypair ? delaypair->lvalue : 0);
+#if 0 /* You can't do this - the pairs are needed for the retries! --Pac. */
/*
* We can free proxy->vps now, not needed anymore.
*/
pairfree(request->proxy->vps);
request->proxy->vps = NULL;
+#endif
return replicating?2:1;
}
-
-/*
- * FIXME: Maybe keeping the proxy_requests list sorted by
- * proxy_next_try would be cheaper than all this searching.
- */
-struct timeval *proxy_setuptimeout(struct timeval *tv)
-{
- time_t now = time(NULL);
- time_t difference, smallest;
- int foundone = 0;
- REQUEST *p;
-
- smallest = 0;
- for (p = proxy_requests; p; p = p->next) {
- if (!p->proxy_is_replicate)
- continue;
- difference = p->proxy_next_try - now;
- if (!foundone) {
- foundone = 1;
- smallest = difference;
- } else {
- if (difference < smallest)
- smallest = difference;
- }
- }
-
- /*
- * Not found one, tell the server to wake up a second
- * later anyways, so that it can service the lists.
- */
- if ((!foundone) ||
- (smallest == 0)) {
- tv->tv_sec = 1;
- tv->tv_usec = 0;
- return tv;
- }
-
- tv->tv_sec = smallest;
- tv->tv_usec = 0;
- return tv;
-}
-
-void proxy_retry(void)
-{
- time_t now = time(NULL);
- REQUEST *p;
-
- for (p = proxy_requests; p; p = p->next) {
- if (p->proxy_next_try <= now) {
- if (p->proxy_try_count) {
- --p->proxy_try_count;
- p->proxy_next_try = now + RETRY_DELAY;
-
- /* Fix up Acct-Delay-Time */
- if (p->proxy->code == PW_ACCOUNTING_REQUEST) {
- VALUE_PAIR *delaypair;
- delaypair = pairfind(p->proxy->vps, PW_ACCT_DELAY_TIME);
-
- if (!delaypair) {
- delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
- if (!delaypair) {
- log(L_ERR|L_CONS, "no memory");
- exit(1);
- }
- pairadd(&p->proxy->vps, delaypair);
- }
- delaypair->lvalue = now - p->proxy->timestamp;
-
- /* Must recompile the valuepairs to wire format */
- free(p->proxy->data);
- p->proxy->data = NULL;
- }
-
- rad_send(p->proxy, p->proxysecret);
- }
- }
- }
-}
static void usage(void)
{
- fprintf(stderr, "Usage: radclient [ -c count] [-d raddb ] [-f file] [-r retries] [-t timeout] [-i id] [-qvx]\n server acct|auth <secret>\n");
+ fprintf(stderr, "Usage: radclient [-c count] [-d raddb] [-f file] [-r retries] [-t timeout]\n [-i id] [-qvx] server acct|auth <secret>\n");
fprintf(stderr, " -c count Send 'count' packets.\n");
fprintf(stderr, " -d raddb Set dictionary directory.\n");
static int rad_clean_list(void);
static REQUEST *rad_check_list(REQUEST *);
static REQUEST *proxy_check_list(REQUEST *request);
+struct timeval *proxy_setuptimeout(struct timeval *);
+void proxy_retry(void);
#ifndef WITH_THREAD_POOL
static int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
#else
{
RADIUS_PACKET *packet, *original;
const char *secret;
- int replicating;
int finished = FALSE;
+ int proxy_sent = 0;
/*
* Put the decoded packet into it's proper place.
* attributes from the list of VP's.
*/
if (request->proxy) {
+ int replicating;
replicating = proxy_receive(request);
if (replicating != 0) {
goto next_request;
*/
if (proxy_requests) {
if (request->proxy == NULL) {
- int sent;
- sent = proxy_send(request);
+ proxy_sent = proxy_send(request);
/*
* sent==1 means it's been proxied. The child
* is done handling the request, but the request
* is NOT finished!
*/
- if (sent == 1) {
- goto next_request;
+ if (proxy_sent == 1) {
+ goto postpone_request;
}
}
} else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
* Hmm... cleaning them up in the child thread also seems
* to make the server run more efficiently!
*/
+
+ /* If we proxied this request, it's not safe to delete it until
+ * after the proxy reply
+ */
+ if (proxy_sent)
+ goto postpone_request;
+
if (request->packet && request->packet->vps) {
pairfree(request->packet->vps);
request->packet->vps = NULL;
request->child_pid = NO_SUCH_CHILD_PID;
#endif
request->finished = finished; /* do as the LAST thing before exiting */
+
+ postpone_request:
return 0;
}
/*
* Do a proxy check of the REQUEST_LIST when using the new proxy code.
*
- * This function is here because it has to access the REQUEST_LIST
- * structure, which is 'static' to this C file.
+ * This function and the next two are here because they have to access
+ * the REQUEST_LIST structure, which is 'static' to this C file.
*/
static REQUEST *proxy_check_list(REQUEST *request)
{
* If we haven't found the old request, complain.
*/
if (oldreq == NULL) {
- request_free(request);
log(L_PROXY, "Unrecognized proxy reply from server %s - ID %d",
client_name(request->packet->src_ipaddr),
request->packet->id);
+ request_free(request);
return NULL;
}
request_free(request);
return oldreq;
}
+
+struct timeval *proxy_setuptimeout(struct timeval *tv)
+{
+ time_t now = time(NULL);
+ time_t difference, smallest = 0;
+ int foundone = 0;
+ int id;
+ REQUEST *p;
+
+ if (proxy_requests) {
+ for (id = 0; id < 256; id++) {
+ for (p = request_list[id].first_request; p; p = p->next)
+ {
+ if (!p->proxy)
+ continue;
+ if (!p->proxy_is_replicate)
+ continue;
+ difference = p->proxy_next_try - now;
+ if (!foundone) {
+ foundone = 1;
+ smallest = difference;
+ } else {
+ if (difference < smallest)
+ smallest = difference;
+ }
+ }
+ }
+ }
+
+ /*
+ * Not found one, tell the server to wake up a second
+ * later anyways, so that it can service the lists.
+ *
+ * FIXME: It would be better if the select() would
+ * actually wake up when there's something to do, and
+ * no sooner. Waking up _every_ second is kludgy
+ */
+ if ((!foundone) ||
+ (smallest == 0)) {
+ tv->tv_sec = 1;
+ tv->tv_usec = 0;
+ return tv;
+ }
+
+ tv->tv_sec = smallest;
+ tv->tv_usec = 0;
+ return tv;
+}
+
+void proxy_retry(void)
+{
+ time_t now = time(NULL);
+ REQUEST *p;
+ int id;
+
+ for (id = 0; id < 256; id++) {
+ for (p = request_list[id].first_request; p; p = p->next) {
+ if (!p->proxy)
+ continue;
+ if (p->proxy_next_try <= now) {
+ if (p->proxy_try_count) {
+ --p->proxy_try_count;
+ p->proxy_next_try = now + proxy_retry_delay;
+
+ /* Fix up Acct-Delay-Time */
+ if (p->proxy->code == PW_ACCOUNTING_REQUEST) {
+ VALUE_PAIR *delaypair;
+ delaypair = pairfind(p->proxy->vps, PW_ACCT_DELAY_TIME);
+
+ if (!delaypair) {
+ delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
+ if (!delaypair) {
+ log(L_ERR|L_CONS, "no memory");
+ exit(1);
+ }
+ pairadd(&p->proxy->vps, delaypair);
+ }
+ delaypair->lvalue = now - p->proxy->timestamp;
+
+ /* Must recompile the valuepairs to wire format */
+ free(p->proxy->data);
+ p->proxy->data = NULL;
+ }
+
+ rad_send(p->proxy, p->proxysecret);
+ } else {
+ p->finished = TRUE;
+ }
+ }
+ }
+ }
+}