/** * Assumes that "tuple" represents a IPv4-UDP or ICMP packet, and filters and updates based on it. * * This is RFC 6146, second halves of both sections 3.5.1 and 3.5.3. * * @param[in] skb tuple's packet. This is actually only used for error reporting. * @param[in] tuple summary of the packet Jool is currently translating. * @return VER_CONTINUE if everything went OK, VER_DROP otherwise. */ static verdict ipv4_simple(struct packet *pkt, struct tuple *tuple4) { int error; struct bib_entry *bib; struct session_entry *session; error = get_bib_ipv4(pkt, tuple4, &bib); if (error == -ESRCH) return VERDICT_ACCEPT; else if (error) return VERDICT_DROP; log_bib(bib); error = sessiondb_get_or_create_ipv4(tuple4, bib, &session); if (error) { inc_stats(pkt, IPSTATS_MIB_INDISCARDS); bib_return(bib); return VERDICT_DROP; } log_session(session); session_return(session); bib_return(bib); return VERDICT_CONTINUE; }
/** * Assumes that "tuple" represents a IPv6-UDP or ICMP packet, and filters and updates based on it. * * This is RFC 6146, first halves of both sections 3.5.1 and 3.5.3. * * @param[in] skb tuple's packet. This is actually only used for error reporting. * @param[in] tuple summary of the packet Jool is currently translating. * @return VER_CONTINUE if everything went OK, VER_DROP otherwise. */ static verdict ipv6_simple(struct packet *pkt, struct tuple *tuple6) { struct bib_entry *bib; struct session_entry *session; int error; error = bibdb_get_or_create_ipv6(pkt, tuple6, &bib); if (error) { inc_stats(pkt, IPSTATS_MIB_INDISCARDS); return VERDICT_DROP; } log_bib(bib); error = sessiondb_get_or_create_ipv6(tuple6, bib, &session); if (error) { inc_stats(pkt, IPSTATS_MIB_INDISCARDS); bib_return(bib); return VERDICT_DROP; } log_session(session); session_return(session); bib_return(bib); return VERDICT_CONTINUE; }
int delete_static_route(struct request_bib *req) { struct bib_entry *bib; int error = 0; if (req->remove.addr6_set) { error = bibdb_get_by_ipv6(&req->remove.addr6, req->l4_proto, &bib); } else if (req->remove.addr4_set) { error = bibdb_get_by_ipv4(&req->remove.addr4, req->l4_proto, &bib); } else { log_err("You need to provide an address so I can find the entry you want to remove."); return -EINVAL; } if (error == -ESRCH) { log_err("Could not find the BIB entry requested by the user."); return error; } if (error) return error; if (req->remove.addr6_set && req->remove.addr4_set) { if (!ipv4_transport_addr_equals(&bib->ipv4, &req->remove.addr4)) { log_err("There's no BIB entry with BOTH of the addresses you requested."); bib_return(bib); return -ESRCH; } } /* Remove the fake user. */ if (bib->is_static) { bib_return(bib); bib->is_static = false; } /* Remove bib's sessions and their references. */ error = sessiondb_delete_by_bib(bib); if (error) { bib_return(bib); return error; } /* Remove our own reference. If it was the last one, the entry should be no more. */ if (bib_return(bib) == 0) { log_err("Looks like some packet was using the BIB entry, " "so it couldn't be deleted immediately. If the entry still exists, " "you might want to try again."); return -EAGAIN; } return 0; }
/** * Attempts to find "tuple"'s BIB entry and returns it in "bib". * Assumes "tuple" represents a IPv4 packet. */ static int get_bib_ipv4(struct packet *pkt, struct tuple *tuple4, struct bib_entry **bib) { int error; error = bibdb_get(tuple4, bib); if (error) { if (error == -ESRCH) { log_debug("There is no BIB entry for the incoming IPv4 packet."); inc_stats(pkt, IPSTATS_MIB_INNOROUTES); } else { log_debug("Error code %d while finding a BIB entry for the incoming packet.", error); inc_stats(pkt, IPSTATS_MIB_INDISCARDS); icmp64_send(pkt, ICMPERR_ADDR_UNREACHABLE, 0); } return error; } if (config_get_addr_dependent_filtering() && !sessiondb_allow(tuple4)) { log_debug("Packet was blocked by address-dependent filtering."); icmp64_send(pkt, ICMPERR_FILTER, 0); inc_stats(pkt, IPSTATS_MIB_INDISCARDS); bib_return(*bib); return -EPERM; } return 0; }
/** * First half of the filtering and updating done during the CLOSED state of the TCP state machine. * Processes IPv6 SYN packets when there's no state. * Part of RFC 6146 section 3.5.2.2. */ static int tcp_closed_v6_syn(struct packet *pkt, struct tuple *tuple6) { struct bib_entry *bib; struct session_entry *session; int error; error = bibdb_get_or_create_ipv6(pkt, tuple6, &bib); if (error) return error; log_bib(bib); error = create_session_ipv6(tuple6, bib, &session, SESSIONTIMER_TRANS, V6_INIT); if (error) { bib_return(bib); return error; } log_session(session); session_return(session); bib_return(bib); return 0; }
/** * Assumes that "tuple" represents a IPv4-UDP or ICMP packet, and filters and updates based on it. * * This is RFC 6146, second halves of both sections 3.5.1 and 3.5.3. * * @param[in] skb tuple's packet. This is actually only used for error reporting. * @param[in] tuple summary of the packet Jool is currently translating. * @return VER_CONTINUE if everything went OK, VER_DROP otherwise. */ static verdict ipv4_simple(struct sk_buff *skb, struct tuple *tuple4) { int error; struct bib_entry *bib; struct session_entry *session; error = get_bib_ipv4(skb, tuple4, &bib); if (error) return VER_DROP; log_bib(bib); error = sessiondb_get_or_create_ipv4(tuple4, bib, &session); if (error) { inc_stats(skb, IPSTATS_MIB_INDISCARDS); bib_return(bib); return VER_DROP; } log_session(session); session_return(session); bib_return(bib); return VER_CONTINUE; }
/** * Filtering and updating done during the CLOSED state of the TCP state machine. * Part of RFC 6146 section 3.5.2.2. */ static verdict tcp_closed_state_handle(struct packet *pkt, struct tuple *tuple) { struct bib_entry *bib; verdict result; int error; switch (pkt_l3_proto(pkt)) { case L3PROTO_IPV6: if (pkt_tcp_hdr(pkt)->syn) { result = is_error(tcp_closed_v6_syn(pkt, tuple)) ? VERDICT_DROP : VERDICT_CONTINUE; goto syn_out; } break; case L3PROTO_IPV4: if (pkt_tcp_hdr(pkt)->syn) { result = tcp_closed_v4_syn(pkt, tuple); goto syn_out; } break; } error = bibdb_get(tuple, &bib); if (error) { log_debug("Closed state: Packet is not SYN and there is no BIB entry, so discarding. " "ERRcode %d", error); inc_stats(pkt, IPSTATS_MIB_INNOROUTES); return VERDICT_DROP; } bib_return(bib); return VERDICT_CONTINUE; syn_out: if (result == VERDICT_DROP) inc_stats(pkt, IPSTATS_MIB_INDISCARDS); return result; }
/** * Second half of the filtering and updating done during the CLOSED state of the TCP state machine. * Processes IPv4 SYN packets when there's no state. * Part of RFC 6146 section 3.5.2.2. */ static verdict tcp_closed_v4_syn(struct packet *pkt, struct tuple *tuple4) { struct bib_entry *bib; struct session_entry *session; int error; verdict result = VERDICT_DROP; if (config_get_drop_external_connections()) { log_debug("Applying policy: Dropping externally initiated TCP connections."); return VERDICT_DROP; } error = bibdb_get(tuple4, &bib); if (error) { if (error != -ESRCH) return VERDICT_DROP; bib = NULL; } log_bib(bib); error = create_session_ipv4(tuple4, bib, &session); if (error) goto end_bib; log_session(session); session->state = V4_INIT; if (!bib || config_get_addr_dependent_filtering()) { error = pktqueue_add(session, pkt); if (error) { if (error == -E2BIG) { /* Fall back to assume there's no Simultaneous Open. */ icmp64_send(pkt, ICMPERR_PORT_UNREACHABLE, 0); } goto end_session; } /* At this point, skb's original skb completely belongs to pktqueue. */ result = VERDICT_STOLEN; error = sessiondb_add(session, SESSIONTIMER_SYN); if (error) { log_debug("Error code %d while adding the session to the DB.", error); pktqueue_remove(session); goto end_session; } } else { error = sessiondb_add(session, SESSIONTIMER_TRANS); if (error) { log_debug("Error code %d while adding the session to the DB.", error); goto end_session; } result = VERDICT_CONTINUE; } /* Fall through. */ end_session: session_return(session); /* Fall through. */ end_bib: if (bib) bib_return(bib); return result; }