242 lines
6.4 KiB
Diff
242 lines
6.4 KiB
Diff
From 98f71e72955490c9a1dcdb0f290e4a874a92ae4e Mon Sep 17 00:00:00 2001
|
|
From: pavir <pavir@codeaurora.org>
|
|
Date: Mon, 26 Dec 2016 14:41:20 +0530
|
|
Subject: [PATCH 308/500] net: l2tp: ppp_channel_proto_version API
|
|
|
|
New API added to retrieve channel version info
|
|
|
|
Change-Id: Ia4fd236c7cf6170a5034609e75de8c6e4ef79f7b
|
|
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
|
|
Signed-off-by: pavir <pavir@codeaurora.org>
|
|
|
|
ppp: Fix ppp_connect_channel function's return value
|
|
|
|
The function should return 0 after all the successful
|
|
checks. The patch fixes failed PPPoE connections.
|
|
|
|
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
|
Change-Id: I6c4755b0b158ca9bd75403e01cb3c0dda193e9e0
|
|
Signed-off-by: Amruth S <quic_amrus@quicinc.com>
|
|
---
|
|
drivers/net/ppp/ppp_generic.c | 61 +++++++++++++++++++++++++++++++++++
|
|
include/linux/netdevice.h | 1 -
|
|
include/linux/ppp_channel.h | 9 ++++++
|
|
net/l2tp/l2tp_ppp.c | 40 ++++++++++++++++++++++-
|
|
4 files changed, 109 insertions(+), 2 deletions(-)
|
|
|
|
--- a/drivers/net/ppp/ppp_generic.c
|
|
+++ b/drivers/net/ppp/ppp_generic.c
|
|
@@ -48,6 +48,7 @@
|
|
#include <net/slhc_vj.h>
|
|
#include <linux/atomic.h>
|
|
#include <linux/refcount.h>
|
|
+#include <linux/if_pppox.h>
|
|
|
|
#include <linux/nsproxy.h>
|
|
#include <net/net_namespace.h>
|
|
@@ -3500,6 +3501,8 @@ ppp_connect_channel(struct channel *pch,
|
|
struct ppp_net *pn;
|
|
int ret = -ENXIO;
|
|
int hdrlen;
|
|
+ int ppp_proto;
|
|
+ int version;
|
|
int notify = 0;
|
|
|
|
pn = ppp_pernet(pch->chan_net);
|
|
@@ -3533,6 +3536,30 @@ ppp_connect_channel(struct channel *pch,
|
|
++ppp->n_channels;
|
|
pch->ppp = ppp;
|
|
refcount_inc(&ppp->file.refcnt);
|
|
+
|
|
+ ppp_proto = ppp_channel_get_protocol(pch->chan);
|
|
+ switch (ppp_proto) {
|
|
+ case PX_PROTO_OL2TP:
|
|
+ version = ppp_channel_get_proto_version(pch->chan);
|
|
+ switch (version) {
|
|
+ case 2:
|
|
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV2;
|
|
+ break;
|
|
+ case 3:
|
|
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV3;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case PX_PROTO_PPTP:
|
|
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_PPTP;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
notify = 1;
|
|
|
|
ppp_unlock(ppp);
|
|
@@ -3783,6 +3810,18 @@ int ppp_channel_get_protocol(struct ppp_
|
|
}
|
|
EXPORT_SYMBOL(ppp_channel_get_protocol);
|
|
|
|
+/* ppp_channel_get_proto_version()
|
|
+ * Call this to get channel protocol version
|
|
+ */
|
|
+int ppp_channel_get_proto_version(struct ppp_channel *chan)
|
|
+{
|
|
+ if (!chan->ops->get_channel_protocol_ver)
|
|
+ return -1;
|
|
+
|
|
+ return chan->ops->get_channel_protocol_ver(chan);
|
|
+}
|
|
+EXPORT_SYMBOL(ppp_channel_get_proto_version);
|
|
+
|
|
/* ppp_channel_hold()
|
|
* Call this to hold a channel.
|
|
*
|
|
@@ -3936,6 +3975,28 @@ void ppp_release_channels(struct ppp_cha
|
|
}
|
|
EXPORT_SYMBOL(ppp_release_channels);
|
|
|
|
+/* Check if ppp xmit lock is on hold */
|
|
+bool ppp_is_xmit_locked(struct net_device *dev)
|
|
+{
|
|
+ struct ppp *ppp;
|
|
+
|
|
+ if (!dev)
|
|
+ return false;
|
|
+
|
|
+ if (dev->type != ARPHRD_PPP)
|
|
+ return false;
|
|
+
|
|
+ ppp = netdev_priv(dev);
|
|
+ if (!ppp)
|
|
+ return false;
|
|
+
|
|
+ if (spin_is_locked(&(ppp)->wlock))
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+EXPORT_SYMBOL(ppp_is_xmit_locked);
|
|
+
|
|
/* Module/initialization stuff */
|
|
|
|
module_init(ppp_init);
|
|
--- a/include/linux/netdevice.h
|
|
+++ b/include/linux/netdevice.h
|
|
@@ -2259,7 +2259,6 @@ struct net_device {
|
|
unsigned char nested_level;
|
|
#endif
|
|
|
|
-
|
|
/* Protocol-specific pointers */
|
|
|
|
struct in_device __rcu *ip_ptr;
|
|
--- a/include/linux/ppp_channel.h
|
|
+++ b/include/linux/ppp_channel.h
|
|
@@ -44,6 +44,8 @@ struct ppp_channel_ops {
|
|
* the channel subtype
|
|
*/
|
|
int (*get_channel_protocol)(struct ppp_channel *);
|
|
+ /* Get channel protocol version */
|
|
+ int (*get_channel_protocol_ver)(struct ppp_channel *);
|
|
/* Hold the channel from being destroyed */
|
|
void (*hold)(struct ppp_channel *);
|
|
/* Release hold on the channel */
|
|
@@ -67,6 +69,9 @@ struct ppp_channel {
|
|
*/
|
|
extern int ppp_channel_get_protocol(struct ppp_channel *);
|
|
|
|
+/* Call this get protocol version */
|
|
+extern int ppp_channel_get_proto_version(struct ppp_channel *);
|
|
+
|
|
/* Call this to hold a channel */
|
|
extern bool ppp_channel_hold(struct ppp_channel *);
|
|
|
|
@@ -83,6 +88,10 @@ extern int ppp_hold_channels(struct net_
|
|
unsigned int chan_sz);
|
|
|
|
bool ppp_is_cp_enabled(struct net_device *dev);
|
|
+
|
|
+/* Test if ppp xmit lock is locked */
|
|
+extern bool ppp_is_xmit_locked(struct net_device *dev);
|
|
+
|
|
/* Hold PPP channels for the PPP device */
|
|
extern int __ppp_hold_channels(struct net_device *dev,
|
|
struct ppp_channel *channels[],
|
|
--- a/net/l2tp/l2tp_ppp.c
|
|
+++ b/net/l2tp/l2tp_ppp.c
|
|
@@ -92,6 +92,7 @@
|
|
#include <net/ip.h>
|
|
#include <net/udp.h>
|
|
#include <net/inet_common.h>
|
|
+#include <linux/if_pppox.h>
|
|
|
|
#include <asm/byteorder.h>
|
|
#include <linux/atomic.h>
|
|
@@ -124,11 +125,13 @@ struct pppol2tp_session {
|
|
|
|
static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
|
|
static int pppol2tp_get_channel_protocol(struct ppp_channel *);
|
|
+static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *);
|
|
static void pppol2tp_hold_chan(struct ppp_channel *);
|
|
static void pppol2tp_release_chan(struct ppp_channel *);
|
|
static const struct pppol2tp_channel_ops pppol2tp_chan_ops = {
|
|
.ops.start_xmit = pppol2tp_xmit,
|
|
.ops.get_channel_protocol = pppol2tp_get_channel_protocol,
|
|
+ .ops.get_channel_protocol_ver = pppol2tp_get_channel_protocol_ver,
|
|
.ops.hold = pppol2tp_hold_chan,
|
|
.ops.release = pppol2tp_release_chan,
|
|
};
|
|
@@ -358,6 +361,40 @@ static int pppol2tp_get_channel_protocol
|
|
return PX_PROTO_OL2TP;
|
|
}
|
|
|
|
+/* pppol2tp_get_channel_protocol_ver()
|
|
+ * Return the protocol version of the L2TP over PPP protocol
|
|
+ */
|
|
+static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *chan)
|
|
+{
|
|
+ struct sock *sk;
|
|
+ struct l2tp_session *session;
|
|
+ struct l2tp_tunnel *tunnel;
|
|
+ int version = 0;
|
|
+
|
|
+ if (!(chan && chan->private)) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ sk = (struct sock *)chan->private;
|
|
+
|
|
+ /* Get session and tunnel contexts from the socket */
|
|
+ session = pppol2tp_sock_to_session(sk);
|
|
+ if (!session) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ tunnel = session->tunnel;
|
|
+ if (!tunnel) {
|
|
+ sock_put(sk);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ version = tunnel->version;
|
|
+
|
|
+ sock_put(sk);
|
|
+ return version;
|
|
+}
|
|
+
|
|
/* pppol2tp_get_addressing() */
|
|
static int pppol2tp_get_addressing(struct ppp_channel *chan,
|
|
struct pppol2tp_common_addr *addr)
|
|
@@ -443,7 +480,8 @@ static int pppol2tp_xmit(struct ppp_chan
|
|
skb->data[0] = PPP_ALLSTATIONS;
|
|
skb->data[1] = PPP_UI;
|
|
/* set incoming interface as the ppp interface */
|
|
- if (skb->skb_iif)
|
|
+ if ((skb->protocol == htons(ETH_P_IP)) ||
|
|
+ (skb->protocol == htons(ETH_P_IPV6)))
|
|
skb->skb_iif = ppp_dev_index(chan);
|
|
|
|
local_bh_disable();
|