From: Raed Salem Create psp_rcv(), which drivers can call to psp decapsulate and attach a psp_skb_ext to an skb. psp_rcv() only supports what the PSP architecture specification refers to as "transport mode" packets, where the L3 header is IPv6. psp_rcv() also assumes that a psp trailer is present and should be pulled from the skb. Signed-off-by: Raed Salem Signed-off-by: Rahul Rameshbabu Signed-off-by: Daniel Zahka --- Notes: v3: - patch introduced include/net/psp/functions.h | 1 + net/psp/psp_main.c | 49 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/net/psp/functions.h b/include/net/psp/functions.h index afb4f5929eec..8ecc396bcfff 100644 --- a/include/net/psp/functions.h +++ b/include/net/psp/functions.h @@ -18,6 +18,7 @@ psp_dev_create(struct net_device *netdev, struct psp_dev_ops *psd_ops, void psp_dev_unregister(struct psp_dev *psd); bool psp_encapsulate(struct net *net, struct sk_buff *skb, __be32 spi, u8 ver, __be16 sport); +int psp_rcv(struct sk_buff *skb, u16 dev_id, u8 generation); /* Kernel-facing API */ void psp_assoc_put(struct psp_assoc *pas); diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index 8229a004ba6e..ec60e06cdf69 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -195,6 +195,55 @@ bool psp_encapsulate(struct net *net, struct sk_buff *skb, } EXPORT_SYMBOL(psp_encapsulate); +/* Receive handler for PSP packets. + * + * Presently it accepts only already-authenticated packets and does not + * support optional fields, such as virtualization cookies. + */ +int psp_rcv(struct sk_buff *skb, u16 dev_id, u8 generation) +{ + const struct psphdr *psph; + int depth = 0, end_depth; + struct psp_skb_ext *pse; + struct ipv6hdr *ipv6h; + struct ethhdr *eth; + __be16 proto; + u32 spi; + + eth = (struct ethhdr *)(skb->data); + proto = __vlan_get_protocol(skb, eth->h_proto, &depth); + if (proto != htons(ETH_P_IPV6)) + return -EINVAL; + + ipv6h = (struct ipv6hdr *)(skb->data + depth); + depth += sizeof(*ipv6h); + end_depth = depth + sizeof(struct udphdr) + sizeof(struct psphdr); + + if (unlikely(end_depth > skb_headlen(skb))) + return -EINVAL; + + pse = skb_ext_add(skb, SKB_EXT_PSP); + if (!pse) + return -EINVAL; + + psph = (const struct psphdr *)(skb->data + depth + sizeof(struct udphdr)); + pse->spi = psph->spi; + pse->dev_id = dev_id; + spi = ntohl(psph->spi); + pse->generation = generation; + pse->version = FIELD_GET(PSPHDR_VERFL_VERSION, psph->verfl); + + ipv6h->nexthdr = psph->nexthdr; + ipv6h->payload_len = + htons(ntohs(ipv6h->payload_len) - PSP_ENCAP_HLEN - PSP_TRL_SIZE); + + memmove(skb->data + PSP_ENCAP_HLEN, skb->data, depth); + skb_pull(skb, PSP_ENCAP_HLEN); + + return 0; +} +EXPORT_SYMBOL(psp_rcv); + static int __init psp_init(void) { mutex_init(&psp_devs_lock); -- 2.47.1