return 0;
}
-int fr_master_io_listen(TALLOC_CTX *ctx, fr_io_instance_t *inst, fr_schedule_t *sc,
+int fr_master_io_listen(fr_io_instance_t *inst, fr_schedule_t *sc,
size_t default_message_size, size_t num_messages)
{
fr_listen_t *li, *child;
extern fr_app_io_t fr_master_app_io;
fr_trie_t *fr_master_io_network(TALLOC_CTX *ctx, int af, fr_ipaddr_t *allow, fr_ipaddr_t *deny);
-int fr_master_io_listen(TALLOC_CTX *ctx, fr_io_instance_t *io, fr_schedule_t *sc,
+int fr_master_io_listen(fr_io_instance_t *io, fr_schedule_t *sc,
size_t default_message_size, size_t num_messages) CC_HINT(nonnull);
fr_io_track_t *fr_master_io_track_alloc(fr_listen_t *li, fr_client_t *client, fr_ipaddr_t const *src_ipaddr, int src_port,
fr_ipaddr_t const *dst_ipaddr, int dst_port);
if (pool->start == NULL) return 0; /* noop */
DEBUG("Protecting data %s %p-%p", mi->name, pool->start, (uint8_t *)pool->start + pool->len);
-#if 0
+
if (unlikely(mprotect(pool->start, pool->len, PROT_READ) < 0)) {
fr_strerror_printf("Protecting \"%s\" module data failed: %s", mi->name, fr_syserror(errno));
return -1;
}
-#endif
+
return 0;
}
* - -1 on failure.
*/
static inline CC_HINT(always_inline)
-int module_data_unprotect(module_instance_t *mi, module_data_pool_t *pool)
+int module_data_unprotect(module_instance_t const *mi, module_data_pool_t const *pool)
{
if (pool->start == NULL) return 0; /* noop */
DEBUG("Unprotecting data %s %p-%p", mi->name, pool->start, (uint8_t *)pool->start + pool->len);
-#if 0
+
if (unlikely(mprotect(pool->start, pool->len, PROT_READ | PROT_WRITE) < 0)) {
fr_strerror_printf("Unprotecting \"%s\" data failed: %s", mi->name, fr_syserror(errno));
return -1;
}
-#endif
+
return 0;
}
+/** Mark module data as read only
+ *
+ * @param[in] mi Instance data to protect (mark as read only).
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int module_instance_data_protect(module_instance_t const *mi)
+{
+ return module_data_unprotect(mi, &mi->inst_pool);
+}
+
+/** Mark module data as read/write
+ *
+ * @param[in] mi Instance data to unprotect (mark as read/write).
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int module_instance_data_unprotect(module_instance_t const *mi)
+{
+ return module_data_unprotect(mi, &mi->inst_pool);
+}
+
/** Return the prefix string for the deepest module
*
* This is useful for submodules which don't have a prefix of their own.
void module_list_debug(module_list_t const *ml) CC_HINT(nonnull);
/** @} */
+/** @name Toggle protection on module instance data
+ *
+ * This is used for module lists which implement additional instantiation phases
+ * (like li->open). It should NOT be used by modules to hack around instance
+ * data being read-only after instantiation completes.
+ *
+ * @{
+ */
+int module_instance_data_protect(module_instance_t const *mi);
+
+int module_instance_data_unprotect(module_instance_t const *mi);
+ /** @} */
+
/** @name Module and module thread lookup
*
* @{
* Even then, proto_radius usually calls fr_master_io_listen() in order
* to create the fr_listen_t structure.
*/
- if (listener->proto_module->open &&
- listener->proto_module->open(listener->proto_mi->data, sc,
- listener->proto_mi->conf) < 0) {
- cf_log_err(listener->proto_mi->conf,
- "Opening %s I/O interface failed",
- listener->proto_module->common.name);
- return -1;
+ if (listener->proto_module->open) {
+ int ret;
+
+ /*
+ * Sometimes the open function needs to modify instance
+ * data, so we need to temporarily remove the protection.
+ */
+ module_instance_data_unprotect(listener->proto_mi);
+ ret = listener->proto_module->open(listener->proto_mi->data, sc,
+ listener->proto_mi->conf);
+ module_instance_data_protect(listener->proto_mi);
+ if (unlikely(ret < 0)) {
+ cf_log_err(listener->proto_mi->conf,
+ "Opening %s I/O interface failed",
+ listener->proto_module->common.name);
+
+ return -1;
+ }
+
}
/*
/*
* io.app_io should already be set
*/
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
inst->io.app = &proto_control;
inst->io.app_instance = instance;
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
/*
* io.app_io should already be set
*/
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
* path, data takes from the socket to the decoder and
* back again.
*/
- li = talloc_zero(inst, fr_listen_t);
+ MEM(li = talloc_zero(NULL, fr_listen_t)); /* Assigned thread steals the memory */
talloc_set_destructor(li, fr_io_listen_free);
li->app_io = inst->app_io;
- li->thread_instance = talloc_zero_array(NULL, uint8_t, li->app_io->common.thread_inst_size);
+ li->thread_instance = talloc_zero_array(li, uint8_t, li->app_io->common.thread_inst_size);
talloc_set_name(li->thread_instance, "proto_%s_thread_t", inst->app_io->common.name);
li->app_io_instance = inst->app_io_instance;
inst->io.app = &proto_dhcpv4;
inst->io.app_instance = instance;
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
inst->io.app = &proto_dhcpv6;
inst->io.app_instance = instance;
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
inst->io.app = &proto_dns;
inst->io.app_instance = instance;
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
/*
* io.app_io should already be set
*/
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
/*
* io.app_io should already be set
*/
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}
/*
* @todo - check for F5 load balancer packets. <sigh>
*/
- DEBUG2("proto_radius_udp got a packet which isn't RADIUS");
+ DEBUG2("proto_radius_udp got a packet which isn't RADIUS: %s", fr_strerror());
thread->stats.total_malformed_requests++;
return 0;
}
/*
* io.app_io should already be set
*/
- return fr_master_io_listen(inst, &inst->io, sc, inst->max_packet_size, inst->num_messages);
+ return fr_master_io_listen(&inst->io, sc, inst->max_packet_size, inst->num_messages);
}
/** Instantiate the application
inst->io.app = &proto_vmps;
inst->io.app_instance = instance;
- return fr_master_io_listen(inst, &inst->io, sc,
+ return fr_master_io_listen(&inst->io, sc,
inst->max_packet_size, inst->num_messages);
}