int handle_pool4_config(struct xlator *jool, struct genl_info *info) { struct request_hdr *hdr = get_jool_hdr(info); union request_pool4 *request = (union request_pool4 *)(hdr + 1); int error; if (xlat_is_siit()) { log_err("SIIT doesn't have pool4."); return nlcore_respond(info, -EINVAL); } error = validate_request_size(info, sizeof(*request)); if (error) return nlcore_respond(info, error); switch (hdr->operation) { case OP_FOREACH: return handle_pool4_display(jool->nat64.pool4, info, request); case OP_ADD: return handle_pool4_add(jool->nat64.pool4, info, request); case OP_UPDATE: return handle_pool4_update(jool->nat64.pool4, info, request); case OP_REMOVE: return handle_pool4_rm(jool, info, request); case OP_FLUSH: return handle_pool4_flush(jool, info, request); } log_err("Unknown operation: %u", hdr->operation); return nlcore_respond(info, -EINVAL); }
static int __handle_jool_message(struct genl_info *info) { struct xlator translator; bool client_is_jool; int error; log_debug("==============================================="); log_debug("Received a request from userspace."); error = validate_request(nla_data(info->attrs[ATTR_DATA]), nla_len(info->attrs[ATTR_DATA]), "userspace client", "kernel module", &client_is_jool); if (error) return client_is_jool ? nlcore_respond(info, error) : error; if (be16_to_cpu(get_jool_hdr(info)->mode) == MODE_INSTANCE) return handle_instance_request(info); error = xlator_find_current(&translator); if (error == -ESRCH) { log_err("This namespace lacks a Jool instance."); return nlcore_respond(info, -ESRCH); } if (error) { log_err("Unknown error %d; Jool instance not found.", error); return nlcore_respond(info, error); } error = multiplex_request(&translator, info); xlator_put(&translator); return error; }
static int handle_pool4_display(struct pool4 *pool, struct genl_info *info, union request_pool4 *request) { struct nlcore_buffer buffer; struct pool4_sample *offset = NULL; int error = 0; log_debug("Sending pool4 to userspace."); error = nlbuffer_init_response(&buffer, info, nlbuffer_response_max_size()); if (error) return nlcore_respond(info, error); if (request->display.offset_set) offset = &request->display.offset; error = pool4db_foreach_sample(pool, request->display.proto, pool4_to_usr, &buffer, offset); nlbuffer_set_pending_data(&buffer, error > 0); error = (error >= 0) ? nlbuffer_send(info, &buffer) : nlcore_respond(info, error); nlbuffer_clean(&buffer); return error; }
int handle_session_config(struct xlator *jool, struct genl_info *info) { struct request_hdr *hdr; struct request_session *request; int error; if (xlat_is_siit()) { log_err("SIIT doesn't have session tables."); return nlcore_respond(info, -EINVAL); } hdr = get_jool_hdr(info); request = (struct request_session *)(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_session_display(jool->nat64.bib, info, request); case OP_COUNT: return handle_session_count(jool->nat64.bib, info, request); } log_err("Unknown operation: %u", be16_to_cpu(hdr->operation)); return nlcore_respond(info, -EINVAL); }
int handle_atomconfig_request(struct xlator *jool, struct genl_info *info) { struct request_hdr *hdr; size_t total_len; int error; if (verify_superpriv()) return nlcore_respond(info, -EPERM); hdr = nla_data(info->attrs[ATTR_DATA]); total_len = nla_len(info->attrs[ATTR_DATA]); error = atomconfig_add(jool, hdr + 1, total_len - sizeof(*hdr)); return nlcore_respond(info, error); }
static int multiplex_request(struct xlator *jool, struct genl_info *info) { struct request_hdr *hdr = get_jool_hdr(info); switch (be16_to_cpu(hdr->mode)) { case MODE_POOL6: return handle_pool6_config(jool, info); case MODE_POOL4: return handle_pool4_config(jool, info); case MODE_BIB: return handle_bib_config(jool, info); case MODE_SESSION: return handle_session_config(jool, info); case MODE_EAMT: return handle_eamt_config(jool, info); case MODE_RFC6791: return handle_pool6791_config(jool, info); case MODE_BLACKLIST: return handle_blacklist_config(jool, info); case MODE_LOGTIME: return handle_logtime_config(info); case MODE_GLOBAL: return handle_global_config(jool, info); case MODE_PARSE_FILE: return handle_atomconfig_request(jool, info); case MODE_JOOLD: return handle_joold_request(jool, info); case MODE_INSTANCE: return handle_instance_request(info); } log_err("Unknown configuration mode: %d", be16_to_cpu(hdr->mode)); return nlcore_respond(info, -EINVAL); }
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_eamt_count(struct eam_table *eamt, struct genl_info *info) { __u64 count; int error; log_debug("Returning EAMT count."); error = eamt_count(eamt, &count); if (error) return nlcore_respond(info, error); return nlcore_respond_struct(info, &count, sizeof(count)); }
static int handle_eamt_display(struct eam_table *eamt, struct genl_info *info, union request_eamt *request) { struct nlcore_buffer buffer; struct ipv4_prefix *prefix4; int error; log_debug("Sending EAMT to userspace."); error = nlbuffer_init_response(&buffer, info, nlbuffer_response_max_size()); if (error) nlcore_respond(info, error); prefix4 = request->display.prefix4_set ? &request->display.prefix4 : NULL; error = eamt_foreach(eamt, eam_entry_to_userspace, &buffer, prefix4); nlbuffer_set_pending_data(&buffer, error > 0); error = (error >= 0) ? nlbuffer_send(info, &buffer) : nlcore_respond(info, error); nlbuffer_clean(&buffer); return error; }
static int handle_session_count(struct bib *db, struct genl_info *info, struct request_session *request) { int error; __u64 count; log_debug("Returning session count."); error = bib_count_sessions(db, request->l4_proto, &count); if (error) return nlcore_respond(info, error); return nlcore_respond_struct(info, &count, sizeof(count)); }
static int handle_session_display(struct bib *db, struct genl_info *info, struct request_session *request) { struct nlcore_buffer buffer; struct session_foreach_func func = { .cb = session_entry_to_userspace, .arg = &buffer, }; struct session_foreach_offset offset_struct; struct session_foreach_offset *offset = NULL; int error; if (verify_superpriv()) return nlcore_respond(info, -EPERM); log_debug("Sending session table to userspace."); error = nlbuffer_init_response(&buffer, info, nlbuffer_response_max_size()); if (error) return nlcore_respond(info, error); if (request->display.offset_set) { offset_struct.offset = request->display.offset; offset_struct.include_offset = false; offset = &offset_struct; } error = bib_foreach_session(db, request->l4_proto, &func, offset); nlbuffer_set_pending_data(&buffer, error > 0); error = (error >= 0) ? nlbuffer_send(info, &buffer) : nlcore_respond(info, error); nlbuffer_free(&buffer); return 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_update(struct pool4 *pool, struct genl_info *info, union request_pool4 *request) { log_debug("Updating pool4 table."); return nlcore_respond(info, pool4db_update(pool, &request->update)); }
static int handle_pool4_add(struct pool4 *pool, struct genl_info *info, union request_pool4 *request) { log_debug("Adding elements to pool4."); return nlcore_respond(info, pool4db_add(pool, &request->add)); }