140 lines
3.9 KiB
Diff
140 lines
3.9 KiB
Diff
From bd2254aed96e33fc84c24d54894fe606f474360d Mon Sep 17 00:00:00 2001
|
|
From: Murat Sezgin <msezgin@codeaurora.org>
|
|
Date: Fri, 26 Feb 2016 15:26:07 -0800
|
|
Subject: [PATCH 302/500] inet: pptp: Added API to get PPTP session info for
|
|
NSS acceleration
|
|
|
|
The API are needed by NSS modules to query PPTP session information
|
|
using the PPTP channel or session ID. The information is needed for
|
|
accelerating PPTP flows by NSS
|
|
|
|
Change-Id: I27408e9bee58f186a4ab99fa360bbef26b02c81b
|
|
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
|
|
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
|
---
|
|
drivers/net/ppp/pptp.c | 75 ++++++++++++++++++++++++++++++++++++++++
|
|
include/linux/if_pppox.h | 8 +++++
|
|
2 files changed, 83 insertions(+)
|
|
|
|
--- a/drivers/net/ppp/pptp.c
|
|
+++ b/drivers/net/ppp/pptp.c
|
|
@@ -91,6 +91,31 @@ static int lookup_chan_dst(u16 call_id,
|
|
return i < MAX_CALLID;
|
|
}
|
|
|
|
+/* Search a pptp session based on peer call id and peer ip address */
|
|
+static int lookup_session_dst(struct pptp_opt *opt, u16 call_id, __be32 d_addr)
|
|
+{
|
|
+ struct pppox_sock *sock;
|
|
+ int i = 1;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ for_each_set_bit_from(i, callid_bitmap, MAX_CALLID) {
|
|
+ sock = rcu_dereference(callid_sock[i]);
|
|
+ if (!sock)
|
|
+ continue;
|
|
+
|
|
+ if (sock->proto.pptp.dst_addr.call_id == call_id &&
|
|
+ sock->proto.pptp.dst_addr.sin_addr.s_addr == d_addr) {
|
|
+ sock_hold(sk_pppox(sock));
|
|
+ memcpy(opt, &sock->proto.pptp, sizeof(struct pptp_opt));
|
|
+ sock_put(sk_pppox(sock));
|
|
+ rcu_read_unlock();
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ rcu_read_unlock();
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
static int add_chan(struct pppox_sock *sock,
|
|
struct pptp_addr *sa)
|
|
{
|
|
@@ -258,7 +283,12 @@ static int pptp_xmit(struct ppp_channel
|
|
ip_select_ident(net, skb, NULL);
|
|
ip_send_check(iph);
|
|
|
|
+ /* set incoming interface as the ppp interface */
|
|
+ if (skb->skb_iif)
|
|
+ skb->skb_iif = ppp_dev_index(chan);
|
|
+
|
|
ip_local_out(net, skb->sk, skb);
|
|
+
|
|
return 1;
|
|
|
|
tx_error:
|
|
@@ -371,6 +401,7 @@ static int pptp_rcv(struct sk_buff *skb)
|
|
if (po) {
|
|
skb_dst_drop(skb);
|
|
nf_reset_ct(skb);
|
|
+ skb->skb_iif = ppp_dev_index(&po->chan);
|
|
return sk_receive_skb(sk_pppox(po), skb, 0);
|
|
}
|
|
drop:
|
|
@@ -603,6 +634,50 @@ static int pptp_ppp_ioctl(struct ppp_cha
|
|
return err;
|
|
}
|
|
|
|
+/* pptp_channel_addressing_get()
|
|
+ * Return PPTP channel specific addressing information.
|
|
+ */
|
|
+void pptp_channel_addressing_get(struct pptp_opt *opt, struct ppp_channel *chan)
|
|
+{
|
|
+ struct sock *sk;
|
|
+ struct pppox_sock *po;
|
|
+
|
|
+ if (!opt)
|
|
+ return;
|
|
+
|
|
+ sk = (struct sock *)chan->private;
|
|
+ if (!sk)
|
|
+ return;
|
|
+
|
|
+ sock_hold(sk);
|
|
+
|
|
+ /* This is very unlikely, but check the socket is connected state */
|
|
+ if (unlikely(sock_flag(sk, SOCK_DEAD) ||
|
|
+ !(sk->sk_state & PPPOX_CONNECTED))) {
|
|
+ sock_put(sk);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ po = pppox_sk(sk);
|
|
+ memcpy(opt, &po->proto.pptp, sizeof(struct pptp_opt));
|
|
+ sock_put(sk);
|
|
+}
|
|
+EXPORT_SYMBOL(pptp_channel_addressing_get);
|
|
+
|
|
+/* pptp_session_find()
|
|
+ * Search and return a PPTP session info based on peer callid and IP
|
|
+ * address. The function accepts the parameters in network byte order.
|
|
+ */
|
|
+int pptp_session_find(struct pptp_opt *opt, __be16 peer_call_id,
|
|
+ __be32 peer_ip_addr)
|
|
+{
|
|
+ if (!opt)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return lookup_session_dst(opt, ntohs(peer_call_id), peer_ip_addr);
|
|
+}
|
|
+EXPORT_SYMBOL(pptp_session_find);
|
|
+
|
|
/* pptp_hold_chan() */
|
|
static void pptp_hold_chan(struct ppp_channel *chan)
|
|
{
|
|
--- a/include/linux/if_pppox.h
|
|
+++ b/include/linux/if_pppox.h
|
|
@@ -105,4 +105,12 @@ struct pppoe_channel_ops {
|
|
extern int pppoe_channel_addressing_get(struct ppp_channel *chan,
|
|
struct pppoe_opt *addressing);
|
|
|
|
+/* Lookup PPTP session info and return PPTP session */
|
|
+extern int pptp_session_find(struct pptp_opt *opt, __be16 peer_call_id,
|
|
+ __be32 peer_ip_addr);
|
|
+
|
|
+/* Return PPTP session information given the channel */
|
|
+extern void pptp_channel_addressing_get(struct pptp_opt *opt,
|
|
+ struct ppp_channel *chan);
|
|
+
|
|
#endif /* !(__LINUX_IF_PPPOX_H) */
|