static int handle_global_config(struct nlmsghdr *nl_hdr, struct request_hdr *jool_hdr, union request_global *request) { struct global_config response = { .mtu_plateaus = NULL }; unsigned char *buffer; size_t buffer_len; bool disabled; int error; switch (jool_hdr->operation) { case OP_DISPLAY: log_debug("Returning 'Global' options."); error = config_clone(&response); if (error) goto end; disabled = xlat_is_nat64() ? pool6_is_empty() : (pool6_is_empty() && eamt_is_empty()); error = serialize_global_config(&response, disabled, &buffer, &buffer_len); if (error) goto end; error = respond_setcfg(nl_hdr, buffer, buffer_len); kfree(buffer); break; case OP_UPDATE: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Updating 'Global' options."); buffer = (unsigned char *) (request + 1); buffer_len = jool_hdr->length - sizeof(*jool_hdr) - sizeof(*request); error = handle_global_update(request->update.type, buffer_len, buffer); break; default: log_err("Unknown operation: %d", jool_hdr->operation); error = -EINVAL; } end: return respond_error(nl_hdr, error); }
int serialize_global_config(struct global_config *config, unsigned char **buffer_out, size_t *buffer_len_out) { unsigned char *buffer; struct global_config *tmp; size_t mtus_len; bool disabled; mtus_len = config->mtu_plateau_count * sizeof(*config->mtu_plateaus); buffer = kmalloc(sizeof(*config) + mtus_len, GFP_KERNEL); if (!buffer) { log_debug("Could not allocate the configuration structure."); return -ENOMEM; } memcpy(buffer, config, sizeof(*config)); memcpy(buffer + sizeof(*config), config->mtu_plateaus, mtus_len); tmp = (struct global_config *) buffer; #ifdef STATEFUL tmp->ttl.udp = jiffies_to_msecs(config->ttl.udp); tmp->ttl.tcp_est = jiffies_to_msecs(config->ttl.tcp_est); tmp->ttl.tcp_trans = jiffies_to_msecs(config->ttl.tcp_trans); tmp->ttl.icmp = jiffies_to_msecs(config->ttl.icmp); tmp->ttl.frag = jiffies_to_msecs(config->ttl.frag); disabled = config->is_disable || pool6_is_empty() || pool4_is_empty(); #else disabled = config->is_disable || (pool6_is_empty() && eamt_is_empty()); #endif tmp->jool_status = !disabled; *buffer_out = buffer; *buffer_len_out = sizeof(*config) + mtus_len; return 0; }