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; }
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; }