net/netfilter/ipvs/ip_vs_proto_sctp.c

Source file repositories/reference/linux-study-clean/net/netfilter/ipvs/ip_vs_proto_sctp.c

File Facts

System
Linux kernel
Corpus path
net/netfilter/ipvs/ip_vs_proto_sctp.c
Extension
.c
Size
18296 bytes
Lines
592
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (sh) {
			sch = skb_header_pointer(skb, iph->len + sizeof(_sctph),
						 sizeof(_schunkh), &_schunkh);
			if (sch) {
				if (sch->type == SCTP_CID_ABORT ||
				    !(sysctl_sloppy_sctp(ipvs) ||
				      sch->type == SCTP_CID_INIT))
					return 1;
				ports = &sh->source;
			}
		}
	} else {
		ports = skb_header_pointer(
			skb, iph->len, sizeof(_ports), &_ports);
	}

	if (!ports) {
		*verdict = NF_DROP;
		return 0;
	}

	if (likely(!ip_vs_iph_inverse(iph)))
		svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
					 &iph->daddr, ports[1]);
	else
		svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
					 &iph->saddr, ports[0]);
	if (svc) {
		int ignored;

		if (ip_vs_todrop(ipvs)) {
			/*
			 * It seems that we are very loaded.
			 * We have to drop this packet :(
			 */
			*verdict = NF_DROP;
			return 0;
		}
		/*
		 * Let the virtual server select a real server for the
		 * incoming connection, and create a connection entry.
		 */
		*cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
		if (!*cpp && ignored <= 0) {
			if (!ignored)
				*verdict = ip_vs_leave(svc, skb, pd, iph);
			else
				*verdict = NF_DROP;
			return 0;
		}
	}
	/* NF_ACCEPT */
	return 1;
}

static void sctp_nat_csum(struct sk_buff *skb, struct sctphdr *sctph,
			  unsigned int sctphoff)
{
	sctph->checksum = sctp_compute_cksum(skb, sctphoff);
	skb->ip_summed = CHECKSUM_UNNECESSARY;
}

static int
sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
		  struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
	struct sctphdr *sctph;
	unsigned int sctphoff = iph->len;
	bool payload_csum = false;

#ifdef CONFIG_IP_VS_IPV6
	if (cp->af == AF_INET6 && iph->fragoffs)
		return 1;
#endif

	/* csum_check requires unshared skb */
	if (skb_ensure_writable(skb, sctphoff + sizeof(*sctph)))
		return 0;

	if (unlikely(cp->app != NULL)) {
		int ret;

		/* Some checks before mangling */
		if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
			return 0;

		/* Call application helper if needed */
		ret = ip_vs_app_pkt_out(cp, skb, iph);
		if (ret == 0)
			return 0;

Annotation

Implementation Notes