Files
openwrt-R7800-nss/target/linux/ipq806x/patches-6.6/990-0347-net-l2tp-l2tp-chan-ops-support-get_addressing.patch
2025-08-04 12:58:18 +02:00

240 lines
6.8 KiB
Diff

From 974e8f230c2294f54d5151fe0dbbc68a3aecb347 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Fri, 26 Feb 2016 15:18:08 -0800
Subject: [PATCH 307/500] net :l2tp: l2tp chan ops support get_addressing
l2tp channel ops support get_addressing() function. This
function can get l2tp tunnel/session/ip/port info.
Change-Id: Ica87438505c20376478092b95faaa3ecb8251596
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
---
drivers/net/ppp/ppp_generic.c | 79 +++++++++++++++++++++++++++++++++++
include/linux/if_pppol2tp.h | 23 ++++++++++
include/linux/ppp_channel.h | 7 ++++
net/l2tp/l2tp_ppp.c | 53 +++++++++++++++++++----
4 files changed, 155 insertions(+), 7 deletions(-)
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -3737,6 +3737,32 @@ int ppp_is_multilink(struct net_device *
}
EXPORT_SYMBOL(ppp_is_multilink);
+/* __ppp_is_multilink()
+ * Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0
+ * if the device is not PPP. Caller should acquire ppp_lock before calling
+ * this function
+ */
+int __ppp_is_multilink(struct net_device *dev)
+{
+ struct ppp *ppp;
+ unsigned int flags;
+
+ if (!dev)
+ return -1;
+
+ if (dev->type != ARPHRD_PPP)
+ return -1;
+
+ ppp = netdev_priv(dev);
+ flags = ppp->flags;
+
+ if (flags & SC_MULTILINK)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(__ppp_is_multilink);
+
/* ppp_channel_get_protocol()
* Call this to obtain the underlying protocol of the PPP channel,
* e.g. PX_PROTO_OE
@@ -3841,6 +3867,59 @@ int ppp_hold_channels(struct net_device
}
EXPORT_SYMBOL(ppp_hold_channels);
+/* __ppp_hold_channels()
+ * Returns the PPP channels of the PPP device, storing each one
+ * into channels[].
+ *
+ * channels[] has chan_sz elements.
+ * This function returns the number of channels stored, up to chan_sz.
+ * It will return < 0 if the device is not PPP.
+ *
+ * You MUST acquire ppp_lock and release the channels using
+ * ppp_release_channels().
+ */
+int __ppp_hold_channels(struct net_device *dev, struct ppp_channel *channels[],
+ unsigned int chan_sz)
+{
+ struct ppp *ppp;
+ int c;
+ struct channel *pch;
+
+ if (!dev)
+ return -1;
+
+ if (dev->type != ARPHRD_PPP)
+ return -1;
+
+ ppp = netdev_priv(dev);
+
+ c = 0;
+ list_for_each_entry(pch, &ppp->channels, clist) {
+ struct ppp_channel *chan;
+
+ if (!pch->chan) {
+ /* Channel is going / gone away*/
+ continue;
+ }
+ if (c == chan_sz) {
+ /* No space to record channel */
+ return c;
+ }
+
+ /* Hold the channel, if supported */
+ chan = pch->chan;
+ if (!chan->ops->hold)
+ continue;
+
+ chan->ops->hold(chan);
+
+ /* Record the channel */
+ channels[c++] = chan;
+ }
+ return c;
+}
+EXPORT_SYMBOL(__ppp_hold_channels);
+
/* ppp_release_channels()
* Releases channels
*/
--- a/include/linux/if_pppol2tp.h
+++ b/include/linux/if_pppol2tp.h
@@ -12,4 +12,27 @@
#include <linux/in6.h>
#include <uapi/linux/if_pppol2tp.h>
+/*
+ * Holds L2TP channel info
+ */
+struct pppol2tp_common_addr {
+ int tunnel_version; /* v2 or v3 */
+ __u32 local_tunnel_id, remote_tunnel_id; /* tunnel id */
+ __u32 local_session_id, remote_session_id; /* session id */
+ struct sockaddr_in local_addr, remote_addr; /* ip address and port */
+};
+
+/*
+ * L2TP channel operations
+ */
+struct pppol2tp_channel_ops {
+ struct ppp_channel_ops ops; /* ppp channel ops */
+};
+
+/*
+ * exported function which calls pppol2tp channel's get addressing
+ * function
+ */
+extern int pppol2tp_channel_addressing_get(struct ppp_channel *,
+ struct pppol2tp_common_addr *);
#endif
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -83,10 +83,17 @@ extern int ppp_hold_channels(struct net_
unsigned int chan_sz);
bool ppp_is_cp_enabled(struct net_device *dev);
+/* Hold PPP channels for the PPP device */
+extern int __ppp_hold_channels(struct net_device *dev,
+ struct ppp_channel *channels[],
+ unsigned int chan_sz);
/* Test if the ppp device is a multi-link ppp device */
extern int ppp_is_multilink(struct net_device *dev);
+/* Test if the ppp device is a multi-link ppp device */
+extern int __ppp_is_multilink(struct net_device *dev);
+
/* Update statistics of the PPP net_device by incrementing related
* statistics field value with corresponding parameter
*/
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -126,12 +126,11 @@ static int pppol2tp_xmit(struct ppp_chan
static int pppol2tp_get_channel_protocol(struct ppp_channel *);
static void pppol2tp_hold_chan(struct ppp_channel *);
static void pppol2tp_release_chan(struct ppp_channel *);
-
-static const struct ppp_channel_ops pppol2tp_chan_ops = {
- .start_xmit = pppol2tp_xmit,
- .get_channel_protocol = pppol2tp_get_channel_protocol,
- .hold = pppol2tp_hold_chan,
- .release = pppol2tp_release_chan,
+static const struct pppol2tp_channel_ops pppol2tp_chan_ops = {
+ .ops.start_xmit = pppol2tp_xmit,
+ .ops.get_channel_protocol = pppol2tp_get_channel_protocol,
+ .ops.hold = pppol2tp_hold_chan,
+ .ops.release = pppol2tp_release_chan,
};
static const struct proto_ops pppol2tp_ops;
@@ -359,6 +358,46 @@ static int pppol2tp_get_channel_protocol
return PX_PROTO_OL2TP;
}
+/* pppol2tp_get_addressing() */
+static int pppol2tp_get_addressing(struct ppp_channel *chan,
+ struct pppol2tp_common_addr *addr)
+{
+ struct sock *sk = (struct sock *)chan->private;
+ struct l2tp_session *session;
+ struct l2tp_tunnel *tunnel;
+ struct inet_sock *isk = NULL;
+ int err = -ENXIO;
+
+ /* Get session and tunnel contexts from the socket */
+ session = pppol2tp_sock_to_session(sk);
+ if (!session)
+ return err;
+
+ tunnel = session->tunnel;
+ isk = inet_sk(tunnel->sock);
+
+ addr->local_tunnel_id = tunnel->tunnel_id;
+ addr->remote_tunnel_id = tunnel->peer_tunnel_id;
+ addr->local_session_id = session->session_id;
+ addr->remote_session_id = session->peer_session_id;
+
+ addr->local_addr.sin_port = isk->inet_sport;
+ addr->remote_addr.sin_port = isk->inet_dport;
+ addr->local_addr.sin_addr.s_addr = isk->inet_saddr;
+ addr->remote_addr.sin_addr.s_addr = isk->inet_daddr;
+
+ sock_put(sk);
+ return 0;
+}
+
+/* pppol2tp_channel_addressing_get() */
+int pppol2tp_channel_addressing_get(struct ppp_channel *chan,
+ struct pppol2tp_common_addr *addr)
+{
+ return pppol2tp_get_addressing(chan, addr);
+}
+EXPORT_SYMBOL(pppol2tp_channel_addressing_get);
+
/* Transmit function called by generic PPP driver. Sends PPP frame
* over PPPoL2TP socket.
*
@@ -852,7 +891,7 @@ static int pppol2tp_connect(struct socke
po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
po->chan.private = sk;
- po->chan.ops = &pppol2tp_chan_ops;
+ po->chan.ops = &pppol2tp_chan_ops.ops;
po->chan.mtu = pppol2tp_tunnel_mtu(tunnel);
error = ppp_register_net_channel(sock_net(sk), &po->chan);