#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/detail.h>
#include <sys/stat.h>
#include <ctype.h>
#define DIRLEN 8192
-static const char *packet_codes[] = {
- "",
- "Access-Request",
- "Access-Accept",
- "Access-Reject",
- "Accounting-Request",
- "Accounting-Response",
- "Accounting-Status",
- "Password-Request",
- "Password-Accept",
- "Password-Reject",
- "Accounting-Message",
- "Access-Challenge"
-};
-
-
struct detail_instance {
/* detail file */
char *detailfile;
/* log src/dst information */
int log_srcdst;
- lrad_hash_table_t *ht;
+ fr_hash_table_t *ht;
};
static const CONF_PARSER module_config[] = {
{
struct detail_instance *inst = instance;
free((char*) inst->last_made_directory);
- if (inst->ht) lrad_hash_table_free(inst->ht);
+ if (inst->ht) fr_hash_table_free(inst->ht);
free(inst);
return 0;
static uint32_t detail_hash(const void *data)
{
const DICT_ATTR *da = data;
- return lrad_hash(&(da->attr), sizeof(da->attr));
+ return fr_hash(&(da->attr), sizeof(da->attr));
}
static int detail_cmp(const void *a, const void *b)
if (cs) {
CONF_ITEM *ci;
- inst->ht = lrad_hash_table_create(detail_hash, detail_cmp,
+ inst->ht = fr_hash_table_create(detail_hash, detail_cmp,
NULL);
for (ci = cf_item_find_next(cs, NULL);
DICT_ATTR *da;
if (!cf_item_is_pair(ci)) continue;
-
+
attr = cf_pair_attr(cf_itemtopair(ci));
if (!attr) continue; /* pair-anoia */
* since the suppression list will usually
* be small, it doesn't matter.
*/
- if (!lrad_hash_table_insert(inst->ht, da)) {
+ if (!fr_hash_table_insert(inst->ht, da)) {
radlog(L_ERR, "rlm_detail: Failed trying to remember %s", attr);
detail_detach(inst);
return -1;
struct detail_instance *inst = instance;
+ rad_assert(request != NULL);
+
/*
* Nothing to log: don't do anything.
*/
* variables.
*/
radius_xlat(buffer, sizeof(buffer), inst->detailfile, request, NULL);
- DEBUG2("rlm_detail: %s expands to %s", inst->detailfile, buffer);
+ RDEBUG2("%s expands to %s", inst->detailfile, buffer);
/*
* Grab the last directory delimiter.
* deleted a directory that the server was using.
*/
if (rad_mkdir(inst->last_made_directory, inst->dirperm) < 0) {
- radlog(L_ERR, "rlm_detail: Failed to create directory %s: %s", inst->last_made_directory, strerror(errno));
+ radlog_request(L_ERR, 0, request, "rlm_detail: Failed to create directory %s: %s", inst->last_made_directory, strerror(errno));
return RLM_MODULE_FAIL;
}
*/
if ((outfd = open(buffer, O_WRONLY | O_APPEND | O_CREAT,
inst->detailperm)) < 0) {
- radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
+ radlog_request(L_ERR, 0, request, "rlm_detail: Couldn't open file %s: %s",
buffer, strerror(errno));
return RLM_MODULE_FAIL;
}
* the lock (race condition)
*/
if (fstat(outfd, &st) != 0) {
- radlog(L_ERR, "rlm_detail: Couldn't stat file %s: %s",
+ radlog_request(L_ERR, 0, request, "rlm_detail: Couldn't stat file %s: %s",
buffer, strerror(errno));
close(outfd);
return RLM_MODULE_FAIL;
}
if (st.st_nlink == 0) {
- DEBUG("rlm_detail: File %s removed by another program, retrying",
+ RDEBUG2("File %s removed by another program, retrying",
buffer);
close(outfd);
lock_count = 0;
continue;
}
- DEBUG("rlm_detail: Acquired filelock, tried %d time(s)",
+ RDEBUG2("Acquired filelock, tried %d time(s)",
lock_count + 1);
locked = 1;
}
if (inst->locking && !locked) {
close(outfd);
- radlog(L_ERR, "rlm_detail: Failed to acquire filelock for %s, giving up",
+ radlog_request(L_ERR, 0, request, "rlm_detail: Failed to acquire filelock for %s, giving up",
buffer);
return RLM_MODULE_FAIL;
}
* after this operation.
*/
if ((outfp = fdopen(outfd, "a")) == NULL) {
- radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
+ radlog_request(L_ERR, 0, request, "rlm_detail: Couldn't open file %s: %s",
buffer, strerror(errno));
if (inst->locking) {
lseek(outfd, 0L, SEEK_SET);
rad_unlockfd(outfd, 0);
- DEBUG("rlm_detail: Released filelock");
+ RDEBUG2("Released filelock");
}
close(outfd); /* automatically releases the lock */
* Numbers, if not.
*/
if ((packet->code > 0) &&
- (packet->code <= PW_ACCESS_CHALLENGE)) {
+ (packet->code < FR_MAX_PACKET_CODE)) {
fprintf(outfp, "\tPacket-Type = %s\n",
- packet_codes[packet->code]);
+ fr_packet_codes[packet->code]);
} else {
fprintf(outfp, "\tPacket-Type = %d\n", packet->code);
}
if (inst->log_srcdst) {
VALUE_PAIR src_vp, dst_vp;
- src_vp.name[0] = dst_vp.name[0] = '\0'; /* for vp_prints() */
+ memset(&src_vp, 0, sizeof(src_vp));
+ memset(&dst_vp, 0, sizeof(dst_vp));
src_vp.operator = dst_vp.operator = T_OP_EQ;
switch (packet->src_ipaddr.af) {
dst_vp.vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
break;
case AF_INET6:
- src_vp.type = PW_TYPE_IPV6ADDR;
+ src_vp.type = PW_TYPE_IPV6ADDR;
src_vp.attribute = PW_PACKET_SRC_IPV6_ADDRESS;
memcpy(src_vp.vp_strvalue,
&packet->src_ipaddr.ipaddr.ip6addr,
sizeof(packet->src_ipaddr.ipaddr.ip6addr));
- dst_vp.type = PW_TYPE_IPV6ADDR;
+ dst_vp.type = PW_TYPE_IPV6ADDR;
dst_vp.attribute = PW_PACKET_DST_IPV6_ADDRESS;
memcpy(dst_vp.vp_strvalue,
&packet->dst_ipaddr.ipaddr.ip6addr,
da.attr = pair->attribute;
if (inst->ht &&
- lrad_hash_table_finddata(inst->ht, &da)) continue;
+ fr_hash_table_finddata(inst->ht, &da)) continue;
/*
* Don't print passwords in old format...
* Add non-protocol attibutes.
*/
if (compat) {
+#ifdef WITH_PROXY
if (request->proxy) {
char proxy_buffer[128];
proxy_buffer, sizeof(proxy_buffer));
fprintf(outfp, "\tFreeradius-Proxied-To = %s\n",
proxy_buffer);
- DEBUG("rlm_detail: Freeradius-Proxied-To = %s",
+ RDEBUG("Freeradius-Proxied-To = %s",
proxy_buffer);
}
+#endif
fprintf(outfp, "\tTimestamp = %ld\n",
(unsigned long) request->timestamp);
fflush(outfp);
lseek(outfd, 0L, SEEK_SET);
rad_unlockfd(outfd, 0);
- DEBUG("rlm_detail: Released filelock");
+ RDEBUG2("Released filelock");
}
fclose(outfp);
*/
static int detail_accounting(void *instance, REQUEST *request)
{
- if (request->listener->type == RAD_LISTEN_DETAIL) {
- DEBUG2(" rlm_detail: Suppressing writes to detail file as the request was just read from a detail file.");
+ if (request->listener->type == RAD_LISTEN_DETAIL &&
+ strcmp(((struct detail_instance *)instance)->detailfile,
+ ((listen_detail_t *)request->listener->data)->filename) == 0) {
+ RDEBUG("Suppressing writes to detail file as the request was just read from a detail file.");
return RLM_MODULE_NOOP;
}
return do_detail(instance,request,request->reply, FALSE);
}
+#ifdef WITH_COA
+/*
+ * Incoming CoA - write the detail files.
+ */
+static int detail_recv_coa(void *instance, REQUEST *request)
+{
+ return do_detail(instance,request,request->packet, FALSE);
+}
+
+/*
+ * Outgoing CoA - write the detail files.
+ */
+static int detail_send_coa(void *instance, REQUEST *request)
+{
+ return do_detail(instance,request,request->reply, FALSE);
+}
+#endif
/*
* Outgoing Access-Request to home server - write the detail files.
*/
+#ifdef WITH_PROXY
static int detail_pre_proxy(void *instance, REQUEST *request)
{
if (request->proxy &&
* it's doing normal accounting.
*/
if (!request->proxy_reply) {
- return detail_accounting(instance, request);
+ int rcode;
+
+ rcode = detail_accounting(instance, request);
+ if (rcode == RLM_MODULE_OK) {
+ request->reply->code = PW_ACCOUNTING_RESPONSE;
+ }
+ return rcode;
}
return RLM_MODULE_NOOP;
}
+#endif
/* globally exported name */
module_t rlm_detail = {
RLM_MODULE_INIT,
"detail",
- RLM_TYPE_THREAD_UNSAFE, /* type: reserved */
+ RLM_TYPE_THREAD_UNSAFE | RLM_TYPE_CHECK_CONFIG_SAFE | RLM_TYPE_HUP_SAFE,
detail_instantiate, /* instantiation */
detail_detach, /* detach */
{
NULL, /* preaccounting */
detail_accounting, /* accounting */
NULL, /* checksimul */
+#ifdef WITH_PROXY
detail_pre_proxy, /* pre-proxy */
detail_post_proxy, /* post-proxy */
+#else
+ NULL, NULL,
+#endif
detail_postauth /* post-auth */
+#ifdef WITH_COA
+ , detail_recv_coa,
+ detail_send_coa
+#endif
},
};