2 * rlm_jradius - The FreeRADIUS JRadius Server Module
3 * Copyright (C) 2004-2006 PicoPoint, B.V.
4 * Copyright (c) 2007-2008 David Bird
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * This module is used to connect FreeRADIUS to the JRadius server.
21 * JRadius is a Java RADIUS client and server framework, see doc/rlm_jradius
22 * and http://jradius.net/ for more information.
24 * Author(s): David Bird <dbird@acm.org>
26 * Connection pooling code based on rlm_sql, see rlm_sql/sql.c for copyright and license.
32 #include <sys/signal.h>
33 #include <sys/types.h>
37 #include <freeradius-devel/ident.h>
40 #include <freeradius-devel/autoconf.h>
41 #include <freeradius-devel/libradius.h>
42 #include <freeradius-devel/radiusd.h>
43 #include <freeradius-devel/modules.h>
44 #include <freeradius-devel/conffile.h>
50 #ifdef HAVE_SYS_SOCKET_H
51 #include <sys/socket.h>
55 #define O_NONBLOCK O_NDELAY
58 static const int JRADIUS_PORT = 1814;
59 static const int HALF_MESSAGE_LEN = 16384;
60 static const int MESSAGE_LEN = 32768;
62 static const int JRADIUS_authenticate = 1;
63 static const int JRADIUS_authorize = 2;
64 static const int JRADIUS_preacct = 3;
65 static const int JRADIUS_accounting = 4;
66 static const int JRADIUS_checksimul = 5;
67 static const int JRADIUS_pre_proxy = 6;
68 static const int JRADIUS_post_proxy = 7;
69 static const int JRADIUS_post_auth = 8;
71 static const int JRADIUS_recv_coa = 9;
72 static const int JRADIUS_send_coa = 10;
75 #define LOG_PREFIX "rlm_jradius: "
78 typedef struct jradius_socket {
81 pthread_mutex_t mutex;
83 struct jradius_socket *next;
84 enum { is_connected, not_connected } state;
91 typedef struct jradius_inst {
97 char * host [MAX_HOSTS];
98 uint32_t ipaddr [MAX_HOSTS];
103 int allow_codechange;
111 typedef struct _byte_array
119 static CONF_PARSER module_config[] = {
120 { "name", PW_TYPE_STRING_PTR, offsetof(JRADIUS, name), NULL, "localhost"},
121 { "primary", PW_TYPE_STRING_PTR, offsetof(JRADIUS, host[0]), NULL, "localhost"},
122 { "secondary", PW_TYPE_STRING_PTR, offsetof(JRADIUS, host[1]), NULL, NULL},
123 { "tertiary", PW_TYPE_STRING_PTR, offsetof(JRADIUS, host[2]), NULL, NULL},
124 { "timeout", PW_TYPE_INTEGER, offsetof(JRADIUS, timeout), NULL, "5"},
125 { "read_timeout", PW_TYPE_INTEGER, offsetof(JRADIUS, read_timeout), NULL, "90"},
126 { "write_timeout",PW_TYPE_INTEGER, offsetof(JRADIUS, write_timeout),NULL, "90"},
127 { "onfail", PW_TYPE_STRING_PTR, offsetof(JRADIUS, onfail_s), NULL, NULL},
128 { "keepalive", PW_TYPE_BOOLEAN, offsetof(JRADIUS, keepalive), NULL, "yes"},
129 { "connections", PW_TYPE_INTEGER, offsetof(JRADIUS, jrsock_cnt), NULL, "8"},
130 { "allow_codechange", PW_TYPE_BOOLEAN, offsetof(JRADIUS, allow_codechange), NULL, "no"},
131 { "allow_idchange", PW_TYPE_BOOLEAN, offsetof(JRADIUS, allow_idchange), NULL, "no"},
132 { NULL, -1, 0, NULL, NULL }
136 sock_read(JRADIUS * inst, JRSOCK *jrsock, uint8_t *b, size_t blen) {
137 int fd = jrsock->con.sock;
138 int timeout = inst->read_timeout;
144 while (recd < blen) {
152 if (select(fd + 1, &fds, (fd_set *) 0, (fd_set *) 0, &tv) == -1)
155 if (FD_ISSET(fd, &fds))
157 c = recv(fd, b + recd, blen-recd, 0);
159 c = read(fd, b + recd, blen-recd);
164 if (c <= 0) return -1;
168 if (recd < blen) return -1;
173 sock_write(JRADIUS * inst, JRSOCK *jrsock, uint8_t *b, size_t blen) {
174 int fd = jrsock->con.sock;
175 int timeout = inst->write_timeout;
181 while (sent < blen) {
189 if (select(fd + 1, (fd_set *) 0, &fds, (fd_set *) 0, &tv) == -1)
192 if (FD_ISSET(fd, &fds))
194 c = send(fd, b+sent, blen-sent, 0);
196 c = write(fd, b+sent, blen-sent);
201 if (c <= 0) return -1;
205 if (sent != blen) return -1;
209 static int connect_socket(JRSOCK *jrsock, JRADIUS *inst)
211 struct sockaddr_in local_addr, serv_addr;
212 int i, connected = 0;
217 * Connect to jradius servers until we succeed or die trying
219 for (i = 0; !connected && i < MAX_HOSTS && inst->ipaddr[i] > 0; i++) {
222 * Allocate a TCP socket
224 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
225 radlog(L_ERR, LOG_PREFIX "could not allocate TCP socket");
230 * If we have a timeout value set, make the socket non-blocking
232 if (inst->timeout > 0 &&
233 fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK) == -1) {
234 radlog(L_ERR, LOG_PREFIX "could not set non-blocking on socket");
239 * Bind to any local port
241 memset(&local_addr, 0, sizeof(local_addr));
242 local_addr.sin_family = AF_INET;
243 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
244 local_addr.sin_port = htons(0);
246 if (bind(sock, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0) {
247 radlog(L_ERR, LOG_PREFIX "could not locally bind TCP socket");
252 * Attempt connection to remote server
254 memset(&serv_addr, 0, sizeof(serv_addr));
255 serv_addr.sin_family = AF_INET;
256 memcpy((char *) &serv_addr.sin_addr, &(inst->ipaddr[i]), 4);
257 serv_addr.sin_port = htons(inst->port[i]);
259 if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
260 if (inst->timeout > 0 && (errno == EINPROGRESS || errno == EWOULDBLOCK)) {
262 * Wait to see if non-blocking socket connects or times-out
265 memset(&pfd, 0, sizeof(pfd));
268 pfd.events = POLLOUT;
270 if (poll(&pfd, 1, inst->timeout * 1000) == 1 && pfd.revents) {
272 * Lets make absolutely sure we are connected
274 struct sockaddr_in sa;
275 unsigned int salen = sizeof(sa);
276 if (getpeername(sock, (struct sockaddr *) &sa, &salen) != -1) {
278 * CONNECTED! break out of for-loop
289 radlog(L_ERR, LOG_PREFIX "could not connect to %s:%d",
290 ip_ntoa(buff, inst->ipaddr[i]), inst->port[i]);
294 * CONNECTED (instantly)! break out of for-loop
301 * Unable to connect, cleanup and start over
307 radlog(L_ERR, LOG_PREFIX "could not find any jradius server!");
312 * If we previously set the socket to non-blocking, restore blocking
313 if (inst->timeout > 0 &&
314 fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK) == -1) {
315 radlog(L_ERR, LOG_PREFIX "could not set blocking on socket");
320 jrsock->state = is_connected;
321 jrsock->con.sock = sock;
325 if (sock > 0) { shutdown(sock, 2); close(sock); }
326 jrsock->state = not_connected;
330 static void close_socket(UNUSED JRADIUS * inst, JRSOCK *jrsock)
332 radlog(L_INFO, "rlm_jradius: Closing JRadius connection %d", jrsock->id);
333 if (jrsock->con.sock > 0) {
334 shutdown(jrsock->con.sock, 2);
335 close(jrsock->con.sock);
337 jrsock->state = not_connected;
338 jrsock->con.sock = 0;
341 static void free_socket(JRADIUS * inst, JRSOCK *jrsock) {
342 close_socket(inst, jrsock);
343 if (inst->keepalive) {
344 #ifdef HAVE_PTHREAD_H
345 pthread_mutex_destroy(&jrsock->mutex);
351 static int init_socketpool(JRADIUS * inst)
357 inst->connect_after = 0;
358 inst->sock_pool = NULL;
360 for (i = 0; i < inst->jrsock_cnt; i++) {
361 radlog(L_INFO, "rlm_jradius: starting JRadius connection %d", i);
363 if ((jrsock = rad_malloc(sizeof(*jrsock))) == 0) return -1;
365 memset(jrsock, 0, sizeof(*jrsock));
367 jrsock->state = not_connected;
369 #ifdef HAVE_PTHREAD_H
370 rcode = pthread_mutex_init(&jrsock->mutex,NULL);
372 radlog(L_ERR, "rlm_jradius: Failed to init lock: %s", strerror(errno));
377 if (time(NULL) > inst->connect_after)
378 if (connect_socket(jrsock, inst))
381 jrsock->next = inst->sock_pool;
382 inst->sock_pool = jrsock;
384 inst->last_used = NULL;
387 radlog(L_DBG, "rlm_jradius: Failed to connect to JRadius server.");
393 static void free_socketpool(JRADIUS * inst)
398 for (cur = inst->sock_pool; cur; cur = next) {
400 free_socket(inst, cur);
403 inst->sock_pool = NULL;
406 static JRSOCK * get_socket(JRADIUS * inst)
409 int tried_to_connect = 0;
412 start = inst->last_used;
413 if (!start) start = inst->sock_pool;
418 #ifdef HAVE_PTHREAD_H
419 if (pthread_mutex_trylock(&cur->mutex) != 0) {
424 if ((cur->state == not_connected) && (time(NULL) > inst->connect_after)) {
425 radlog(L_INFO, "rlm_jradius: Trying to (re)connect unconnected handle %d", cur->id);
427 connect_socket(cur, inst);
430 if (cur->state == not_connected) {
431 radlog(L_DBG, "rlm_jradius: Ignoring unconnected handle %d", cur->id);
433 #ifdef HAVE_PTHREAD_H
434 pthread_mutex_unlock(&cur->mutex);
439 radlog(L_DBG, "rlm_jradius: Reserving JRadius socket id: %d", cur->id);
441 if (unconnected != 0 || tried_to_connect != 0) {
442 radlog(L_INFO, "rlm_jradius: got socket %d after skipping %d unconnected handles, tried to reconnect %d though",
443 cur->id, unconnected, tried_to_connect);
446 inst->last_used = cur->next;
451 if (!cur) cur = inst->sock_pool;
452 if (cur == start) break;
455 radlog(L_INFO, "rlm_jradius: There are no sockets to use! skipped %d, tried to connect %d",
456 unconnected, tried_to_connect);
460 static int release_socket(UNUSED JRADIUS * inst, JRSOCK * jrsock)
462 #ifdef HAVE_PTHREAD_H
463 pthread_mutex_unlock(&jrsock->mutex);
466 radlog(L_DBG, "rlm_jradius: Released JRadius socket id: %d", jrsock->id);
473 * Initialize the jradius module
475 static int jradius_instantiate(CONF_SECTION *conf, void **instance)
477 JRADIUS *inst = (JRADIUS *) instance;
478 char host[128], b[128], *h;
481 inst = rad_malloc(sizeof(JRADIUS));
482 memset(inst, 0, sizeof(JRADIUS));
484 if (cf_section_parse(conf, inst, module_config) < 0) {
489 for (i = 0, idx = 0; i < MAX_HOSTS; i++) {
490 if (inst->host[i] && strlen(inst->host[i]) < sizeof(host)) {
495 if (sscanf(b, "%[^:]:%d", host, &port) == 2) { h = host; p = port; }
499 if (ip_hton(h, AF_INET, &ipaddr) < 0) {
500 radlog(L_ERR, "Can't find IP address for host %s", h);
503 if ((inst->ipaddr[idx] = ipaddr.ipaddr.ip4addr.s_addr) != htonl(INADDR_NONE)) {
505 radlog(L_INFO, LOG_PREFIX "configuring jradius server %s:%d", h, p);
508 radlog(L_ERR, LOG_PREFIX "invalid jradius server %s", h);
514 if (inst->keepalive) init_socketpool(inst);
516 inst->onfail = RLM_MODULE_FAIL;
518 if (inst->onfail_s) {
519 if (!strcmp(inst->onfail_s, "NOOP")) inst->onfail = RLM_MODULE_NOOP;
520 else if (!strcmp(inst->onfail_s, "REJECT")) inst->onfail = RLM_MODULE_REJECT;
521 else if (!strcmp(inst->onfail_s, "OK")) inst->onfail = RLM_MODULE_OK;
522 else if (!strcmp(inst->onfail_s, "FAIL")) inst->onfail = RLM_MODULE_FAIL;
523 else radlog(L_ERR, LOG_PREFIX "invalid jradius 'onfail' state %s", inst->onfail_s);
532 * Initialize a byte array buffer structure
534 static void init_byte_array(byte_array * ba, unsigned char *b, int blen)
537 ba->size = ba->left = blen;
542 * Pack a single byte into a byte array buffer
544 static int pack_byte(byte_array * ba, unsigned char c)
546 if (ba->left < 1) return -1;
556 * Pack an array of bytes into a byte array buffer
558 static int pack_bytes(byte_array * ba, unsigned char *d, unsigned int dlen)
560 if (ba->left < dlen) return -1;
562 memcpy((void *)(ba->b + ba->pos), d, dlen);
570 * Pack an integer into a byte array buffer (adjusting for byte-order)
572 static int pack_uint32(byte_array * ba, uint32_t i)
574 if (ba->left < 4) return -1;
578 memcpy((void *)(ba->b + ba->pos), (void *)&i, 4);
586 * Pack a short into a byte array buffer (adjusting for byte-order)
588 static int pack_uint16(byte_array * ba, uint16_t i)
590 if (ba->left < 2) return -1;
594 memcpy((void *)(ba->b + ba->pos), (void *)&i, 2);
602 * Pack a byte into a byte array buffer
604 static int pack_uint8(byte_array * ba, uint8_t i)
606 if (ba->left < 1) return -1;
608 memcpy((void *)(ba->b + ba->pos), (void *)&i, 1);
616 * Pack one byte array buffer into another byte array buffer
618 static int pack_array(byte_array * ba, byte_array * a)
620 if (ba->left < a->pos) return -1;
622 memcpy((void *)(ba->b + ba->pos), (void *)a->b, a->pos);
630 * Pack radius attributes into a byte array buffer
632 static int pack_vps(byte_array * ba, VALUE_PAIR * vps)
637 for (vp = vps; vp != NULL; vp = vp->next) {
639 radlog(L_DBG, LOG_PREFIX "packing attribute %s (type: %d; len: %u)", vp->name, vp->attribute, (unsigned int) vp->length);
641 i = vp->attribute; /* element is int, not uint32_t */
642 if (pack_uint32(ba, i) == -1) return -1;
644 if (pack_uint32(ba, i) == -1) return -1;
646 if (pack_uint32(ba, i) == -1) return -1;
650 if (pack_uint8(ba, vp->lvalue) == -1) return -1;
653 if (pack_uint16(ba, vp->lvalue) == -1) return -1;
655 case PW_TYPE_INTEGER:
657 if (pack_uint32(ba, vp->lvalue) == -1) return -1;
660 if (pack_bytes(ba, (void *)&vp->vp_ipaddr, vp->length) == -1) return -1;
663 if (pack_bytes(ba, (void *)vp->vp_octets, vp->length) == -1) return -1;
672 * Pack a radius packet into a byte array buffer
674 static int pack_packet(byte_array * ba, RADIUS_PACKET * p)
676 /*unsigned char code = p->code;*/
677 unsigned char buff[HALF_MESSAGE_LEN];
680 init_byte_array(&pba, buff, sizeof(buff));
682 if (pack_vps(&pba, p->vps) == -1) return -1;
684 radlog(L_DBG, LOG_PREFIX "packing packet with code: %d (attr length: %d)", p->code, pba.pos);
687 if (pack_uint32(ba, p->code) == -1) return -1;
688 if (pack_uint32(ba, p->id) == -1) return -1;
690 if (pack_byte(ba, p->code) == -1) return -1;
691 if (pack_byte(ba, p->id) == -1) return -1;
693 if (pack_uint32(ba, pba.pos) == -1) return -1;
694 if (pba.pos == 0) return 0;
695 if (pack_array(ba, &pba) == -1) return -1;
700 static int pack_request(byte_array * ba, REQUEST *r)
702 unsigned char buff[HALF_MESSAGE_LEN];
705 init_byte_array(&pba, buff, sizeof(buff));
707 if (pack_vps(&pba, r->config_items) == -1) return -1;
708 if (pack_uint32(ba, pba.pos) == -1) return -1;
709 if (pba.pos == 0) return 0;
710 if (pack_array(ba, &pba) == -1) return -1;
715 static uint32_t unpack_uint32(unsigned char *c)
718 memcpy((void *)&ii, c, 4);
722 static uint16_t unpack_uint16(unsigned char *c)
725 memcpy((void *)&ii, c, 2);
729 static uint8_t unpack_uint8(unsigned char *c)
732 memcpy((void *)&ii, c, 1);
739 * Read a single byte from socket
741 static int read_byte(JRADIUS *inst, JRSOCK *jrsock, uint8_t *b)
743 return (sock_read(inst, jrsock, b, 1) == 1) ? 0 : -1;
747 * Read an integer from the socket (adjusting for byte-order)
749 static int read_uint32(JRADIUS *inst, JRSOCK *jrsock, uint32_t *i)
753 if (sock_read(inst, jrsock, (uint8_t *)&ii, 4) != 4) return -1;
760 * Read a value-pair list from the socket
762 static int read_vps(JRADIUS *inst, JRSOCK *jrsock, VALUE_PAIR **pl, int plen)
765 unsigned char buff[MESSAGE_LEN];
766 uint32_t alen, atype, aop;
769 while (rlen < plen) {
770 if (read_uint32(inst, jrsock, &atype) == -1) return -1; rlen += 4;
771 if (read_uint32(inst, jrsock, &alen) == -1) return -1; rlen += 4;
772 if (read_uint32(inst, jrsock, &aop) == -1) return -1; rlen += 4;
774 radlog(L_DBG, LOG_PREFIX "reading attribute: type=%d; len=%d", atype, alen);
776 if (alen >= sizeof(buff)) {
777 radlog(L_ERR, LOG_PREFIX "packet value too large (len: %d)", alen);
781 if (sock_read(inst, jrsock, buff, alen) != (int)alen) return -1; rlen += alen;
785 * Create new attribute
787 vp = paircreate(atype, 0, -1);
790 if (vp->type == -1) {
792 * FreeRADIUS should know about the same attributes that JRadius knows
794 radlog(L_ERR, LOG_PREFIX "received attribute we do not recognize (type: %d)", atype);
800 * WiMAX combo-ip address
801 * paircreate() cannot recognize the real type of the address.
804 if (vp->type==PW_TYPE_COMBO_IP) {
807 vp->type = PW_TYPE_IPADDR;
810 vp->type = PW_TYPE_IPV6ADDR;
816 * Fill in the attribute value based on type
820 vp->lvalue = unpack_uint8(buff);
825 vp->lvalue = unpack_uint16(buff);
829 case PW_TYPE_INTEGER:
831 vp->lvalue = unpack_uint32(buff);
836 memcpy((void *)&vp->vp_ipaddr, buff, 4);
841 if (alen >= sizeof(vp->vp_octets)) alen = sizeof(vp->vp_octets) - 1;
842 memcpy((void *)vp->vp_octets, buff, alen);
848 * Add the attribute to the packet
857 * Read a radius packet from the socket
859 static int read_packet(JRADIUS * inst, JRSOCK *jrsock, RADIUS_PACKET *p)
866 if (read_uint32(inst, jrsock, &code) == -1) return -1;
867 if (read_uint32(inst, jrsock, &id) == -1) return -1;
870 if (read_byte(inst, jrsock, &c) == -1) return -1;
872 if (read_byte(inst, jrsock, &c) == -1) return -1;
876 if (read_uint32(inst, jrsock, &plen) == -1) return -1;
878 radlog(L_DBG, LOG_PREFIX "reading packet: code=%d len=%d", (int)code, plen);
880 if (inst->allow_codechange)
881 if (code != p->code) {
882 radlog(L_INFO, LOG_PREFIX "changing packet code from %d to %d", p->code, code);
886 if (inst->allow_idchange)
887 if ((int)id != p->id) {
888 radlog(L_INFO, LOG_PREFIX "changing packet id from %d to %d", p->id, id);
893 * Delete previous attribute list
897 if (plen == 0) return 0;
899 if (read_vps(inst, jrsock, &p->vps, plen) == -1) return -1;
904 static int read_request(JRADIUS *inst, JRSOCK *jrsock, REQUEST *p)
908 if (read_uint32(inst, jrsock, &plen) == -1) return -1;
910 radlog(L_DBG, LOG_PREFIX "reading request: config_item: len=%d", plen);
913 * Delete previous attribute list
915 pairfree(&p->config_items);
917 if (plen == 0) return 0;
919 if (read_vps(inst, jrsock, &p->config_items, plen) == -1) return -1;
924 static int rlm_jradius_call(char func, void *instance, REQUEST *req, int isproxy)
926 JRADIUS * inst = instance;
927 RADIUS_PACKET * request = req->packet;
928 RADIUS_PACKET * reply = req->reply;
932 int exitstatus = inst->onfail;
933 unsigned char rcode, pcount;
935 unsigned char buff[MESSAGE_LEN];
938 char * n = inst->name;
939 unsigned int nlen = strlen(n);
940 const char * err = 0;
943 #define W_ERR(s) { err=s; goto packerror; }
944 #define R_ERR(s) { err=s; goto parseerror; }
948 request = req->proxy;
949 reply = req->proxy_reply;
953 if (inst->keepalive) {
954 jrsock = get_socket(inst);
955 if (!jrsock) return exitstatus;
958 memset(jrsock, 0, sizeof(*jrsock));
959 jrsock->state = not_connected;
962 init_byte_array(&ba, buff, sizeof(buff));
965 if (request) pcount++;
969 * Create byte array to send to jradius
971 if ((rc = pack_uint32 (&ba, nlen)) == -1) W_ERR("pack_uint32(nlen)");
972 if ((rc = pack_bytes (&ba, (void *)n, nlen)) == -1) W_ERR("pack_bytes(name)");
973 if ((rc = pack_byte (&ba, func)) == -1) W_ERR("pack_byte(fun)");
974 if ((rc = pack_byte (&ba, pcount)) == -1) W_ERR("pack_byte(pcnt)");
975 if (pcount > 0 && (rc = pack_packet (&ba, request)) == -1) W_ERR("pack_packet(req)");
976 if (pcount > 1 && (rc = pack_packet (&ba, reply)) == -1) W_ERR("pack_packet(rep)");
977 if ((rc = pack_request(&ba, req)) == -1) W_ERR("pack_request()");
983 if (jrsock->state == not_connected) {
984 if (attempt2) radlog(L_ERR, LOG_PREFIX "reconnecting socket id %d", jrsock->id);
985 if (!connect_socket(jrsock, inst)) {
986 if (attempt2) radlog(L_ERR, LOG_PREFIX "could not reconnect socket %d, giving up", jrsock->id);
990 radlog(L_DBG, LOG_PREFIX "sending %d bytes to socket %d", ba.pos, jrsock->id);
991 if (sock_write(inst, jrsock, ba.b, ba.pos) != (int)ba.pos ||
992 (rc = read_byte(inst, jrsock, &rcode)) == -1) {
994 * With an error on the write or the first read, try closing the socket
995 * and reconnecting to see if that improves matters any (tries this only once)
997 radlog(L_ERR, LOG_PREFIX "error sending request with socket %d", jrsock->id);
998 if (!inst->keepalive || attempt2) W_ERR("socket_send/first_read");
999 close_socket(inst, jrsock);
1007 if ((rc = read_byte(inst, jrsock, &pcount)) == -1) R_ERR("read_byte(pcnt)");
1009 radlog(L_DBG, LOG_PREFIX "return code %d; receiving %d packets", (int)rcode, (int)pcount);
1011 if (pcount > 0 && request) if ((rc = read_packet (inst, jrsock, request)) == -1) R_ERR("read_packet(req)");
1012 if (pcount > 1 && reply) if ((rc = read_packet (inst, jrsock, reply)) == -1) R_ERR("read_packet(rep)");
1014 if ((rc = read_request(inst, jrsock, req)) == -1) R_ERR("read_request()");
1017 * Since we deleted all the attribute lists in the request,
1018 * we need to reconfigure a few pointers in the REQUEST object
1020 if (req->username) {
1021 req->username = pairfind(request->vps, PW_USER_NAME, 0);
1023 if (req->password) {
1024 req->password = pairfind(request->vps, PW_PASSWORD, 0);
1025 if (!req->password) req->password = pairfind(request->vps, PW_CHAP_PASSWORD, 0);
1029 * All done, set return code and cleanup
1031 exitstatus = (int)rcode;
1035 radlog(L_ERR, LOG_PREFIX "problem parsing the data [%s]",err);
1036 if (inst->keepalive) close_socket(inst, jrsock);
1040 radlog(L_ERR, LOG_PREFIX "problem packing the data[%s]",err);
1041 if (inst->keepalive) close_socket(inst, jrsock);
1044 if (inst->keepalive)
1045 release_socket(inst, jrsock);
1047 close_socket(inst, jrsock);
1052 static int jradius_authenticate(void *instance, REQUEST *request)
1054 return rlm_jradius_call(JRADIUS_authenticate, instance, request, 0);
1057 static int jradius_authorize(void *instance, REQUEST *request)
1059 return rlm_jradius_call(JRADIUS_authorize, instance, request, 0);
1062 static int jradius_preacct(void *instance, REQUEST *request)
1064 return rlm_jradius_call(JRADIUS_preacct, instance, request, 0);
1067 static int jradius_accounting(void *instance, REQUEST *request)
1069 return rlm_jradius_call(JRADIUS_accounting, instance, request, 0);
1072 static int jradius_checksimul(void *instance, REQUEST *request)
1074 return rlm_jradius_call(JRADIUS_checksimul, instance, request, 0);
1077 static int jradius_pre_proxy(void *instance, REQUEST *request)
1079 return rlm_jradius_call(JRADIUS_pre_proxy, instance, request, 1);
1082 static int jradius_post_proxy(void *instance, REQUEST *request)
1084 return rlm_jradius_call(JRADIUS_post_proxy, instance, request, 1);
1087 static int jradius_post_auth(void *instance, REQUEST *request)
1089 return rlm_jradius_call(JRADIUS_post_auth, instance, request, 0);
1093 static int jradius_recv_coa(void *instance, REQUEST *request)
1095 return rlm_jradius_call(JRADIUS_recv_coa, instance, request, 0);
1097 static int jradius_send_coa(void *instance, REQUEST *request)
1099 return rlm_jradius_call(JRADIUS_send_coa, instance, request, 0);
1103 static int jradius_detach(void *instance)
1105 JRADIUS *inst = (JRADIUS *) instance;
1106 free_socketpool(inst);
1111 module_t rlm_jradius = {
1114 RLM_TYPE_THREAD_SAFE,
1115 jradius_instantiate,
1118 jradius_authenticate,