Beispiel #1
0
static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
{
	/* Charge it to the socket. */

	if (ip_queue_rcv_skb(sk, skb) < 0) {
		kfree_skb(skb);
		return NET_RX_DROP;
	}

	return NET_RX_SUCCESS;
}
Beispiel #2
0
static int mptp_rcv(struct sk_buff *skb)
{
	struct mptphdr *shdr;
	struct mptp_sock *ssk;
	__be16 len;
	uint16_t src, dst;
	struct sockaddr_mptp *mptp_addr;
	int err;
	int addr_size = sizeof(struct sockaddr_mptp) + sizeof(struct mptp_dest);

	if (unlikely(!pskb_may_pull(skb, sizeof(struct mptphdr)))) {
		log_error("Insufficient space for header\n");
		goto drop;
	}

	shdr = (struct mptphdr *)skb->data;
	len = ntohs(shdr->len);

	if (unlikely(skb->len < len)) {
		log_error("Malformed packet (packet_len=%u, skb_len=%u)\n", len,
			  skb->len);
		goto drop;
	}

	if (unlikely(len < sizeof(struct mptphdr))) {
		log_error
		    ("Malformed packet (packet_len=%u sizeof(mptphdr)=%u\n",
		     len, sizeof(struct mptphdr));
		goto drop;
	}

	src = ntohs(shdr->src);
	dst = ntohs(shdr->dst);
	if (unlikely
	    (src == 0 || dst == 0 || src >= MAX_MPTP_PORT
	     || dst >= MAX_MPTP_PORT)) {
		log_error("Malformed packet (src=%u, dst=%u)\n", shdr->src,
			  shdr->dst);
		goto drop;
	}

	skb_pull(skb, sizeof(struct mptphdr));
	len -= sizeof(struct mptphdr);

	pskb_trim(skb, len);

	log_debug("Received %u bytes from from port=%u to port=%u\n",
		  len - sizeof(struct mptphdr), src, dst);

	ssk = mptp_lookup(dst);
	if (ssk == NULL) {
		log_error("MPTP lookup failed for port %u\n", dst);
		goto drop;
	}

	BUG_ON(addr_size > sizeof(skb->cb));

	mptp_addr = (struct sockaddr_mptp *)skb->cb;
	mptp_addr->dests[0].port = shdr->src;
	mptp_addr->dests[0].addr = ip_hdr(skb)->saddr;

	log_debug("Setting sin_port=%u, sin_addr=%u\n", ntohs(shdr->src),
		  mptp_addr->dests[0].addr);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
	err = ip_queue_rcv_skb((struct sock *)&ssk->sock, skb);
#else
	err = sock_queue_rcv_skb((struct sock *)&ssk->sock, skb);
#endif

	if (unlikely(err)) {
		log_error("ip_queue_rcv_skb failed with %d\n", err);
		consume_skb(skb);
	}
	return NET_RX_SUCCESS;

 drop:
	kfree(skb);
	return NET_RX_DROP;
}