static int handle_pool6_config(struct nlmsghdr *nl_hdr, struct request_hdr *jool_hdr, union request_pool6 *request) { __u64 count; int error; switch (jool_hdr->operation) { case OP_DISPLAY: return handle_pool6_display(nl_hdr, request); case OP_COUNT: log_debug("Returning IPv6 prefix count."); error = pool6_count(&count); if (error) return respond_error(nl_hdr, error); return respond_setcfg(nl_hdr, &count, sizeof(count)); case OP_ADD: case OP_UPDATE: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Adding a prefix to the IPv6 pool."); return respond_error(nl_hdr, pool6_add(&request->add.prefix)); case OP_REMOVE: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Removing a prefix from the IPv6 pool."); error = pool6_remove(&request->rm.prefix); if (error) return respond_error(nl_hdr, error); if (xlat_is_nat64() && !request->flush.quick) sessiondb_delete_taddr6s(&request->rm.prefix); return respond_error(nl_hdr, error); case OP_FLUSH: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Flushing the IPv6 pool..."); error = pool6_flush(); if (xlat_is_nat64() && !request->flush.quick) sessiondb_flush(); return respond_error(nl_hdr, error); default: log_err("Unknown operation: %d", jool_hdr->operation); return respond_error(nl_hdr, -EINVAL); } }
static int handle_eamt_config(struct nlmsghdr *nl_hdr, struct request_hdr *jool_hdr, union request_eamt *request) { __u64 count; int error; if (xlat_is_nat64()) { log_err("Stateful NAT64 doesn't have an EAMT."); return -EINVAL; } switch (jool_hdr->operation) { case OP_DISPLAY: return handle_eamt_display(nl_hdr, request); case OP_COUNT: log_debug("Returning EAMT count."); error = eamt_count(&count); if (error) return respond_error(nl_hdr, error); return respond_setcfg(nl_hdr, &count, sizeof(count)); case OP_TEST: return handle_eamt_test(nl_hdr, request); case OP_ADD: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Adding EAMT entry."); return respond_error(nl_hdr, eamt_add(&request->add.prefix6, &request->add.prefix4, request->add.force)); case OP_REMOVE: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Removing EAMT entry."); return respond_error(nl_hdr, eamt_rm( request->rm.prefix6_set ? &request->rm.prefix6 : NULL, request->rm.prefix4_set ? &request->rm.prefix4 : NULL)); case OP_FLUSH: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); eamt_flush(); return respond_error(nl_hdr, 0); default: log_err("Unknown operation: %d", jool_hdr->operation); return respond_error(nl_hdr, -EINVAL); } }
static int handle_blacklist_config(struct nlmsghdr *nl_hdr, struct request_hdr *jool_hdr, union request_pool *request) { __u64 count; int error; if (xlat_is_nat64()) { log_err("Blacklist does not apply to Stateful NAT64."); return -EINVAL; } switch (jool_hdr->operation) { case OP_DISPLAY: log_debug("Sending Blacklist pool to userspace."); return handle_blacklist_display(nl_hdr, request); case OP_COUNT: log_debug("Returning address count in the Blacklist pool."); error = blacklist_count(&count); if (error) return respond_error(nl_hdr, error); return respond_setcfg(nl_hdr, &count, sizeof(count)); case OP_ADD: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Adding an address to the Blacklist pool."); return respond_error(nl_hdr, blacklist_add(&request->add.addrs)); case OP_REMOVE: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Removing an address from the Blacklist pool."); return respond_error(nl_hdr, blacklist_rm(&request->rm.addrs)); case OP_FLUSH: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Flushing the Blacklist pool..."); return respond_error(nl_hdr, blacklist_flush()); default: log_err("Unknown operation: %d", jool_hdr->operation); return respond_error(nl_hdr, -EINVAL); } }
static int validate_version(struct request_hdr *hdr) { if (hdr->magic[0] != 'j' || hdr->magic[1] != 'o') goto magic_fail; if (hdr->magic[2] != 'o' || hdr->magic[3] != 'l') goto magic_fail; switch (hdr->type) { case 's': if (xlat_is_nat64()) { log_err("You're speaking to NAT64 Jool using " "the SIIT Jool application."); return -EINVAL; } break; case 'n': if (xlat_is_siit()) { log_err("You're speaking to SIIT Jool using " "the NAT64 Jool application."); return -EINVAL; } break; default: goto magic_fail; } if (xlat_version() == hdr->version) return 0; log_err("Version mismatch. The kernel module is %u.%u.%u.%u, " "but the userspace application is %u.%u.%u.%u. " "Please update Jool's %s.", JOOL_VERSION_MAJOR, JOOL_VERSION_MINOR, JOOL_VERSION_REV, JOOL_VERSION_DEV, hdr->version >> 24, (hdr->version >> 16) & 0xFFU, (hdr->version >> 8) & 0xFFU, hdr->version & 0xFFU, (xlat_version() > hdr->version) ? "userspace application" : "kernel module"); return -EINVAL; magic_fail: log_err("It appears you're trying to speak to Jool using some other " "Netlink client or an older userspace application. " "If the latter is true, please update your userspace " "application."); return -EINVAL; }
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); }
static int handle_pool4_rm(struct xlator *jool, struct genl_info *info, union request_pool4 *request) { int error; log_debug("Removing elements from pool4."); error = pool4db_rm_usr(jool->nat64.pool4, &request->rm.entry); if (xlat_is_nat64() && !request->rm.quick) { bib_rm_range(jool, request->rm.entry.proto, &request->rm.entry.range); } return nlcore_respond(info, error); }
static int handle_pool4_flush(struct xlator *jool, struct genl_info *info, union request_pool4 *request) { log_debug("Flushing pool4."); pool4db_flush(jool->nat64.pool4); if (xlat_is_nat64() && !request->flush.quick) { /* * This will also clear *previously* orphaned entries, but given * that "not quick" generally means "please clean up", this is * more likely what people wants. */ bib_flush(jool); } return nlcore_respond(info, 0); }
static int handle_pool4_rm(struct nlmsghdr *nl_hdr, union request_pool4 *request) { int error; if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Removing elements from the IPv4 pool."); error = pool4db_rm(request->rm.mark, request->rm.proto, &request->rm.addrs, &request->rm.ports); if (xlat_is_nat64() && !request->rm.quick) { sessiondb_delete_taddr4s(&request->rm.addrs, &request->rm.ports); bibdb_delete_taddr4s(&request->rm.addrs, &request->rm.ports); } return respond_error(nl_hdr, error); }
int handle_eamt_config(struct xlator *jool, struct genl_info *info) { struct request_hdr *hdr; union request_eamt *request; int error; if (xlat_is_nat64()) { log_err("Stateful NAT64 doesn't have an EAMT."); return nlcore_respond(info, -EINVAL); } hdr = get_jool_hdr(info); request = (union request_eamt *)(hdr + 1); error = validate_request_size(info, sizeof(*request)); if (error) return nlcore_respond(info, error); switch (be16_to_cpu(hdr->operation)) { case OP_DISPLAY: return handle_eamt_display(jool->siit.eamt, info, request); case OP_COUNT: return handle_eamt_count(jool->siit.eamt, info); case OP_ADD: error = handle_eamt_add(jool->siit.eamt, request); break; case OP_REMOVE: error = handle_eamt_rm(jool->siit.eamt, request); break; case OP_FLUSH: error = handle_eamt_flush(jool->siit.eamt); break; default: log_err("Unknown operation: %u", be16_to_cpu(hdr->operation)); error = -EINVAL; } return nlcore_respond(info, error); }
static int handle_pool4_flush(struct nlmsghdr *nl_hdr, union request_pool4 *request) { int error; if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Flushing the IPv4 pool..."); error = pool4db_flush(); /* * Well, pool4db_flush only errors on memory allocation failures, * so I guess clearing BIB and session even if pool4db_flush fails * is a good idea. */ if (xlat_is_nat64() && !request->flush.quick) { sessiondb_flush(); bibdb_flush(); } return respond_error(nl_hdr, error); }