/** * 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; }
static int whine_if_too_big(struct packet *in, struct packet *out) { unsigned int len; unsigned int mtu; if (pkt_l3_proto(in) == L3PROTO_IPV4 && !is_dont_fragment_set(pkt_ip4_hdr(in))) return 0; len = pkt_len(out); mtu = get_nexthop_mtu(out); if (len > mtu) { /* * We don't have to worry about ICMP errors causing this because the translate code already * truncates them. */ log_debug("Packet is too big (len: %u, mtu: %u).", len, mtu); switch (pkt_l3_proto(out)) { case L3PROTO_IPV6: mtu -= 20; break; case L3PROTO_IPV4: mtu += 20; break; } icmp64_send(out, ICMPERR_FRAG_NEEDED, mtu); return -EINVAL; } return 0; }
/** * 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; }