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->remove.prefix); if (error) return respond_error(nl_hdr, error); if (nat64_is_stateful() && !request->flush.quick) error = sessiondb_delete_by_prefix6(&request->remove.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 (error) return respond_error(nl_hdr, error); if (nat64_is_stateful() && !request->flush.quick) error = 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_rfc6791_config(struct nlmsghdr *nl_hdr, struct request_hdr *nat64_hdr, union request_pool4 *request) { __u64 count; int error; if (nat64_is_stateful()) { log_err("RFC 6791 does not apply to Stateful NAT64."); return -EINVAL; } switch (nat64_hdr->operation) { case OP_DISPLAY: return handle_pool6791_display(nl_hdr, request); case OP_COUNT: log_debug("Returning IPv4 address count."); error = rfc6791_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 IPv4 pool."); return respond_error(nl_hdr, rfc6791_add(&request->add.addrs)); case OP_REMOVE: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Removing an address from the IPv4 pool."); error = rfc6791_remove(&request->remove.addrs); if (error) return respond_error(nl_hdr, error); return respond_error(nl_hdr, error); case OP_FLUSH: if (verify_superpriv()) { return respond_error(nl_hdr, -EPERM); } log_debug("Flushing the IPv4 pool..."); error = rfc6791_flush(); if (error) return respond_error(nl_hdr, error); return respond_error(nl_hdr, error); default: log_err("Unknown operation: %d", nat64_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 handle_expect_add(struct genl_info *info) { struct expected_packet pkt; struct nlattr *attr; if (verify_superpriv()) return -EPERM; attr = info->attrs[ATTR_FILENAME]; if (!attr) { log_err("Request lacks a file name."); return -EINVAL; } pkt.filename = nla_data(attr); attr = info->attrs[ATTR_PKT]; if (!attr) { log_err("Request lacks a packet."); return -EINVAL; } pkt.bytes = nla_data(attr); pkt.bytes_len = nla_len(attr); attr = info->attrs[ATTR_EXCEPTIONS]; pkt.exceptions = attr ? nla_data(attr) : NULL; pkt.exceptions_len = attr ? (nla_len(attr) / sizeof(*pkt.exceptions)) : 0; return genl_respond(info, expecter_add(&pkt)); }
static int handle_send(struct genl_info *info) { char *filename; struct nlattr *attr; int error; if (verify_superpriv()) return -EPERM; attr = info->attrs[ATTR_FILENAME]; if (!attr) { log_err("Request lacks a file name."); return -EINVAL; } filename = nla_data(attr); attr = info->attrs[ATTR_PKT]; if (!attr) { log_err("Request lacks a packet."); return -EINVAL; } error = sender_send(filename, nla_data(attr), nla_len(attr)); return genl_respond(info, error); }
static int handle_expect_flush(struct genl_info *info) { if (verify_superpriv()) return -EPERM; expecter_flush(); return genl_respond(info, 0); }
static int handle_eamt_flush(struct eam_table *eamt) { if (verify_superpriv()) return -EPERM; eamt_flush(eamt); return 0; }
static int handle_eamt_add(struct eam_table *eamt, union request_eamt *request) { if (verify_superpriv()) return -EPERM; log_debug("Adding EAMT entry."); return eamt_add(eamt, &request->add.prefix6, &request->add.prefix4, request->add.force); }
static int handle_pool4_add(struct nlmsghdr *nl_hdr, union request_pool4 *request) { if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Adding elements to the IPv4 pool."); return respond_error(nl_hdr, pool4db_add(request->add.mark, request->add.proto, &request->add.addrs, &request->add.ports)); }
static int handle_bib_config(struct nlmsghdr *nl_hdr, struct request_hdr *nat64_hdr, struct request_bib *request) { __u64 count; int error; if (nat64_is_stateless()) { log_err("SIIT doesn't have BIBs."); return -EINVAL; } switch (nat64_hdr->operation) { case OP_DISPLAY: return handle_bib_display(nl_hdr, request); case OP_COUNT: log_debug("Returning BIB count."); error = bibdb_count(request->l4_proto, &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 BIB entry."); return respond_error(nl_hdr, add_static_route(request)); case OP_REMOVE: if (verify_superpriv()) return respond_error(nl_hdr, -EPERM); log_debug("Removing BIB entry."); return respond_error(nl_hdr, delete_static_route(request)); default: log_err("Unknown operation: %d", nat64_hdr->operation); return respond_error(nl_hdr, -EINVAL); } }
static int handle_eamt_rm(struct eam_table *eamt, union request_eamt *request) { struct ipv6_prefix *prefix6; struct ipv4_prefix *prefix4; if (verify_superpriv()) return -EPERM; log_debug("Removing EAMT entry."); prefix6 = request->rm.prefix6_set ? &request->rm.prefix6 : NULL; prefix4 = request->rm.prefix4_set ? &request->rm.prefix4 : NULL; return eamt_rm(eamt, prefix6, prefix4); }
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 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 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); }
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); }
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; }