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); }
unsigned int core_4to6(struct sk_buff *skb) { struct packet pkt; struct iphdr *hdr = ip_hdr(skb); int error; if (config_get_is_disable()) return NF_ACCEPT; /* Translation is disabled; let the packet pass. */ if (is_blacklisted4(hdr->saddr) || is_blacklisted4(hdr->daddr)) return NF_ACCEPT; if (nat64_is_stateful()) { if (!pool4_contains(hdr->daddr) || pool6_is_empty()) return NF_ACCEPT; /* Not meant for translation; let the kernel handle it. */ } log_debug("==============================================="); log_debug("Catching IPv4 packet: %pI4->%pI4", &hdr->saddr, &hdr->daddr); error = pkt_init_ipv4(&pkt, skb); /* Reminder: This function might change pointers. */ if (error) return NF_DROP; error = validate_icmp4_csum(&pkt); if (error) { inc_stats(&pkt, IPSTATS_MIB_INHDRERRORS); return NF_DROP; } return core_common(&pkt); }
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; }