All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Schiller <ms@dev.tdt.de>
To: andrew.hendry@gmail.com, davem@davemloft.net, kuba@kernel.org,
	xie.he.0141@gmail.com
Cc: linux-x25@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Martin Schiller <ms@dev.tdt.de>
Subject: [PATCH 2/6] net/x25: make neighbour params configurable
Date: Mon, 16 Nov 2020 08:31:45 +0100	[thread overview]
Message-ID: <20201116073149.23219-2-ms@dev.tdt.de> (raw)
In-Reply-To: <20201116073149.23219-1-ms@dev.tdt.de>

Extended struct x25_neigh and x25_subscrip_struct to configure following
params through SIOCX25SSUBSCRIP:
  o mode (DTE/DCE)
  o number of channels
  o facilities (packet size, window size)
  o timer T20

Based on this configuration options the follwing changes/extensions
where made:
  o DTE/DCE handling to select the next lc (DCE=from bottom / DTE=from
    top)
  o DTE/DCE handling to set correct clear/reset/restart cause
  o take default facilities from neighbour settings

Signed-off-by: Martin Schiller <ms@dev.tdt.de>
---
 include/net/x25.h        |   7 ++-
 include/uapi/linux/x25.h |  54 ++++++++--------
 net/x25/af_x25.c         | 132 ++++++++++++++++++++++++++++++++-------
 net/x25/x25_facilities.c |   6 +-
 net/x25/x25_link.c       | 104 +++++++++++++++++++++++++-----
 net/x25/x25_subr.c       |  22 ++++++-
 6 files changed, 255 insertions(+), 70 deletions(-)

diff --git a/include/net/x25.h b/include/net/x25.h
index af841c5ede28..6e8600456d39 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -140,6 +140,9 @@ struct x25_neigh {
 	struct net_device	*dev;
 	unsigned int		state;
 	unsigned int		extended;
+	unsigned int		dce;
+	unsigned int		lc;
+	struct x25_facilities	facilities;
 	struct sk_buff_head	queue;
 	unsigned long		t20;
 	struct timer_list	t20timer;
@@ -164,6 +167,7 @@ struct x25_sock {
 	struct timer_list	timer;
 	struct x25_causediag	causediag;
 	struct x25_facilities	facilities;
+	unsigned int		socket_defined_facilities;	/* set, if facilities changed by SIOCX25SFACILITIES */
 	struct x25_dte_facilities dte_facilities;
 	struct x25_calluserdata	calluserdata;
 	unsigned long 		vc_facil_mask;	/* inc_call facilities mask */
@@ -215,7 +219,8 @@ int x25_create_facilities(unsigned char *, struct x25_facilities *,
 			  struct x25_dte_facilities *, unsigned long);
 int x25_negotiate_facilities(struct sk_buff *, struct sock *,
 			     struct x25_facilities *,
-			     struct x25_dte_facilities *);
+				struct x25_dte_facilities *,
+				struct x25_neigh *);
 void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
 
 /* x25_forward.c */
diff --git a/include/uapi/linux/x25.h b/include/uapi/linux/x25.h
index 034b7dc5593a..963848e94880 100644
--- a/include/uapi/linux/x25.h
+++ b/include/uapi/linux/x25.h
@@ -63,31 +63,6 @@ struct sockaddr_x25 {
 	struct x25_address sx25_addr;		/* X.121 Address */
 };
 
-/*
- *	DTE/DCE subscription options.
- *
- *      As this is missing lots of options, user should expect major
- *	changes of this structure in 2.5.x which might break compatibilty.
- *      The somewhat ugly dimension 200-sizeof() is needed to maintain
- *	backward compatibility.
- */
-struct x25_subscrip_struct {
-	char device[200-sizeof(unsigned long)];
-	unsigned long	global_facil_mask;	/* 0 to disable negotiation */
-	unsigned int	extended;
-};
-
-/* values for above global_facil_mask */
-
-#define	X25_MASK_REVERSE	0x01	
-#define	X25_MASK_THROUGHPUT	0x02
-#define	X25_MASK_PACKET_SIZE	0x04
-#define	X25_MASK_WINDOW_SIZE	0x08
-
-#define X25_MASK_CALLING_AE 0x10
-#define X25_MASK_CALLED_AE 0x20
-
-
 /*
  *	Routing table control structure.
  */
@@ -127,6 +102,35 @@ struct x25_dte_facilities {
 	__u8 called_ae[20];
 };
 
+/*
+ *	DTE/DCE subscription options.
+ *
+ *      As this is missing lots of options, user should expect major
+ *	changes of this structure in 2.5.x which might break compatibilty.
+ *      The somewhat ugly dimension 200-sizeof() is needed to maintain
+ *	backward compatibility.
+ */
+struct x25_subscrip_struct {
+	char device[200-((2 * sizeof(unsigned long)) + sizeof(struct x25_facilities) + (2 * sizeof(unsigned int)))];
+	unsigned int		dce;
+	unsigned int		lc;
+	struct x25_facilities	facilities;
+	unsigned long		t20;
+	unsigned long		global_facil_mask;	/* 0 to disable negotiation */
+	unsigned int		extended;
+};
+
+/* values for above global_facil_mask */
+
+#define	X25_MASK_REVERSE	0x01
+#define	X25_MASK_THROUGHPUT	0x02
+#define	X25_MASK_PACKET_SIZE	0x04
+#define	X25_MASK_WINDOW_SIZE	0x08
+
+#define X25_MASK_CALLING_AE 0x10
+#define X25_MASK_CALLED_AE 0x20
+
+
 /*
  *	Call User Data structure.
  */
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index d8e5ca251801..439ae65ab7a8 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -72,8 +72,19 @@ static const struct proto_ops x25_proto_ops;
 static const struct x25_address null_x25_address = {"               "};
 
 #ifdef CONFIG_COMPAT
+struct compat_x25_facilities {
+	compat_uint_t	winsize_in, winsize_out;
+	compat_uint_t	pacsize_in, pacsize_out;
+	compat_uint_t	throughput;
+	compat_uint_t	reverse;
+};
+
 struct compat_x25_subscrip_struct {
-	char device[200-sizeof(compat_ulong_t)];
+	char device[200-((2 * sizeof(compat_ulong_t)) + sizeof(struct compat_x25_facilities) + (2 * sizeof(compat_uint_t)))];
+	compat_uint_t		dce;
+	compat_uint_t		lc;
+	struct compat_x25_facilities	facilities;
+	compat_ulong_t		t20;
 	compat_ulong_t global_facil_mask;
 	compat_uint_t extended;
 };
@@ -366,13 +377,26 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
 	unsigned int lci = 1;
 	struct sock *sk;
 
-	while ((sk = x25_find_socket(lci, nb)) != NULL) {
-		sock_put(sk);
-		if (++lci == 4096) {
-			lci = 0;
-			break;
+	if (nb->dce) {
+		while ((sk = x25_find_socket(lci, nb)) != NULL) {
+			sock_put(sk);
+			if (++lci > nb->lc) {
+				lci = 0;
+				break;
+			}
+			cond_resched();
+		}
+	} else {
+		lci = nb->lc;
+
+		while ((sk = x25_find_socket(lci, nb)) != NULL) {
+			sock_put(sk);
+			if (--lci == 0) {
+				lci = 0;
+				break;
+			}
+			cond_resched();
 		}
-		cond_resched();
 	}
 
 	return lci;
@@ -806,6 +830,10 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
 	if (!x25->neighbour)
 		goto out_put_route;
 
+	if (!x25->socket_defined_facilities)
+		memcpy(&x25->facilities, &x25->neighbour->facilities,
+		       sizeof(struct x25_facilities));
+
 	x25_limit_facilities(&x25->facilities, x25->neighbour);
 
 	x25->lci = x25_new_lci(x25->neighbour);
@@ -1039,7 +1067,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
 	/*
 	 *	Try to reach a compromise on the requested facilities.
 	 */
-	len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities);
+	len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities, nb);
 	if (len == -1)
 		goto out_sock_put;
 
@@ -1454,10 +1482,15 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		rc = x25_subscr_ioctl(cmd, argp);
 		break;
 	case SIOCX25GFACILITIES: {
+		rc = -EINVAL;
 		lock_sock(sk);
+		if (sk->sk_state != TCP_ESTABLISHED &&
+		    !x25->socket_defined_facilities)
+			goto out_gfac_release;
 		rc = copy_to_user(argp, &x25->facilities,
 				  sizeof(x25->facilities))
 			? -EFAULT : 0;
+out_gfac_release:
 		release_sock(sk);
 		break;
 	}
@@ -1471,16 +1504,16 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		lock_sock(sk);
 		if (sk->sk_state != TCP_LISTEN &&
 		    sk->sk_state != TCP_CLOSE)
-			goto out_fac_release;
+			goto out_sfac_release;
 		if (facilities.pacsize_in < X25_PS16 ||
 		    facilities.pacsize_in > X25_PS4096)
-			goto out_fac_release;
+			goto out_sfac_release;
 		if (facilities.pacsize_out < X25_PS16 ||
 		    facilities.pacsize_out > X25_PS4096)
-			goto out_fac_release;
+			goto out_sfac_release;
 		if (facilities.winsize_in < 1 ||
 		    facilities.winsize_in > 127)
-			goto out_fac_release;
+			goto out_sfac_release;
 		if (facilities.throughput) {
 			int out = facilities.throughput & 0xf0;
 			int in  = facilities.throughput & 0x0f;
@@ -1488,19 +1521,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 				facilities.throughput |=
 					X25_DEFAULT_THROUGHPUT << 4;
 			else if (out < 0x30 || out > 0xD0)
-				goto out_fac_release;
+				goto out_sfac_release;
 			if (!in)
 				facilities.throughput |=
 					X25_DEFAULT_THROUGHPUT;
 			else if (in < 0x03 || in > 0x0D)
-				goto out_fac_release;
+				goto out_sfac_release;
 		}
 		if (facilities.reverse &&
 		    (facilities.reverse & 0x81) != 0x81)
-			goto out_fac_release;
+			goto out_sfac_release;
 		x25->facilities = facilities;
+		x25->socket_defined_facilities = 1;
 		rc = 0;
-out_fac_release:
+out_sfac_release:
 		release_sock(sk);
 		break;
 	}
@@ -1652,6 +1686,9 @@ static int compat_x25_subscr_ioctl(unsigned int cmd,
 	struct net_device *dev;
 	int rc = -EINVAL;
 
+	if (cmd != SIOCX25GSUBSCRIP && cmd != SIOCX25SSUBSCRIP)
+		goto out;
+
 	rc = -EFAULT;
 	if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
 		goto out;
@@ -1665,28 +1702,75 @@ static int compat_x25_subscr_ioctl(unsigned int cmd,
 	if (nb == NULL)
 		goto out_dev_put;
 
-	dev_put(dev);
-
 	if (cmd == SIOCX25GSUBSCRIP) {
 		read_lock_bh(&x25_neigh_list_lock);
 		x25_subscr.extended = nb->extended;
+		x25_subscr.dce		     = nb->dce;
+		x25_subscr.lc		     = nb->lc;
+		x25_subscr.facilities	     = nb->facilities;
+		x25_subscr.t20		     = nb->t20;
 		x25_subscr.global_facil_mask = nb->global_facil_mask;
 		read_unlock_bh(&x25_neigh_list_lock);
 		rc = copy_to_user(x25_subscr32, &x25_subscr,
 				sizeof(*x25_subscr32)) ? -EFAULT : 0;
 	} else {
 		rc = -EINVAL;
-		if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
-			rc = 0;
-			write_lock_bh(&x25_neigh_list_lock);
-			nb->extended = x25_subscr.extended;
-			nb->global_facil_mask = x25_subscr.global_facil_mask;
-			write_unlock_bh(&x25_neigh_list_lock);
+
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+
+		if (x25_subscr.extended != 0 && x25_subscr.extended != 1)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.dce != 0 && x25_subscr.dce != 1)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.lc < 1 || x25_subscr.lc > 4095)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.pacsize_in < X25_PS16 ||
+		    x25_subscr.facilities.pacsize_in > X25_PS4096)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.pacsize_out < X25_PS16 ||
+		    x25_subscr.facilities.pacsize_out > X25_PS4096)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.winsize_in < 1 ||
+		    x25_subscr.facilities.winsize_in > 127)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.throughput) {
+			int out = x25_subscr.facilities.throughput & 0xf0;
+			int in  = x25_subscr.facilities.throughput & 0x0f;
+			if (!out)
+				x25_subscr.facilities.throughput |=
+					X25_DEFAULT_THROUGHPUT << 4;
+			else if (out < 0x30 || out > 0xD0)
+				goto out_dev_and_neigh_put;
+			if (!in)
+				x25_subscr.facilities.throughput |=
+					X25_DEFAULT_THROUGHPUT;
+			else if (in < 0x03 || in > 0x0D)
+				goto out_dev_and_neigh_put;
 		}
+		if (x25_subscr.facilities.reverse &&
+		    (x25_subscr.facilities.reverse & 0x81) != 0x81)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.t20 < 1 * HZ || x25_subscr.t20 > 300 * HZ)
+			goto out_dev_and_neigh_put;
+
+		rc = 0;
+		write_lock_bh(&x25_neigh_list_lock);
+		nb->extended	      = x25_subscr.extended;
+		nb->dce		      = x25_subscr.dce;
+		nb->lc		      = x25_subscr.lc;
+		nb->facilities	      = x25_subscr.facilities;
+		nb->t20		      = x25_subscr.t20;
+		nb->global_facil_mask = x25_subscr.global_facil_mask;
+		write_unlock_bh(&x25_neigh_list_lock);
 	}
+	dev_put(dev);
+
 	x25_neigh_put(nb);
 out:
 	return rc;
+out_dev_and_neigh_put:
+	x25_neigh_put(nb);
 out_dev_put:
 	dev_put(dev);
 	goto out;
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 8e1a49b0c0dc..e6c9f9376206 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -263,13 +263,17 @@ int x25_create_facilities(unsigned char *buffer,
  *	The only real problem is with reverse charging.
  */
 int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
-		struct x25_facilities *new, struct x25_dte_facilities *dte)
+		struct x25_facilities *new, struct x25_dte_facilities *dte,
+		struct x25_neigh *nb)
 {
 	struct x25_sock *x25 = x25_sk(sk);
 	struct x25_facilities *ours = &x25->facilities;
 	struct x25_facilities theirs;
 	int len;
 
+	if (!x25->socket_defined_facilities)
+		ours = &nb->facilities;
+
 	memset(&theirs, 0, sizeof(theirs));
 	memcpy(new, ours, sizeof(*new));
 	memset(dte, 0, sizeof(*dte));
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index 22055ee40056..fabac6331a59 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -125,8 +125,16 @@ static void x25_transmit_restart_request(struct x25_neigh *nb)
 	*dptr++ = nb->extended ? X25_GFI_EXTSEQ : X25_GFI_STDSEQ;
 	*dptr++ = 0x00;
 	*dptr++ = X25_RESTART_REQUEST;
-	*dptr++ = 0x00;
-	*dptr++ = 0;
+
+	*dptr = 0x00;	/* cause */
+
+	/* set bit 8, if DTE and cause != 0x00 */
+	if (!nb->dce && *dptr != 0x00)
+		*dptr |= (unsigned char) 0x80;
+
+	dptr++;
+
+	*dptr++ = 0x00;	/* diagnostic */
 
 	skb->sk = NULL;
 
@@ -181,8 +189,16 @@ void x25_transmit_clear_request(struct x25_neigh *nb, unsigned int lci,
 					 X25_GFI_STDSEQ);
 	*dptr++ = (lci >> 0) & 0xFF;
 	*dptr++ = X25_CLEAR_REQUEST;
-	*dptr++ = cause;
-	*dptr++ = 0x00;
+
+	*dptr = cause;	/* cause */
+
+	/* set bit 8, if DTE and cause != 0x00 */
+	if (!nb->dce && *dptr != 0x00)
+		*dptr |= (unsigned char) 0x80;
+
+	dptr++;
+
+	*dptr++ = 0x00;	/* diagnostic */
 
 	skb->sk = NULL;
 
@@ -260,9 +276,19 @@ void x25_link_device_add(struct net_device *dev)
 	timer_setup(&nb->t20timer, x25_t20timer_expiry, 0);
 
 	dev_hold(dev);
-	nb->dev      = dev;
-	nb->state    = X25_LINK_STATE_0;
-	nb->extended = 0;
+	nb->dev                    = dev;
+	nb->state                  = X25_LINK_STATE_0;
+	nb->extended               = 0;
+	nb->dce                    = 0;
+	nb->lc                     = 10;
+	nb->facilities.winsize_in  = X25_DEFAULT_WINDOW_SIZE;
+	nb->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
+	nb->facilities.pacsize_in  = X25_DEFAULT_PACKET_SIZE;
+	nb->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
+	nb->facilities.throughput  = 0;	/* by default don't negotiate
+						   throughput */
+	nb->facilities.reverse     = X25_DEFAULT_REVERSE;
+	nb->t20                    = sysctl_x25_restart_request_timeout;
 	/*
 	 * Enables negotiation
 	 */
@@ -270,7 +296,6 @@ void x25_link_device_add(struct net_device *dev)
 				       X25_MASK_THROUGHPUT |
 				       X25_MASK_PACKET_SIZE |
 				       X25_MASK_WINDOW_SIZE;
-	nb->t20      = sysctl_x25_restart_request_timeout;
 	refcount_set(&nb->refcnt, 1);
 
 	write_lock_bh(&x25_neigh_list_lock);
@@ -395,28 +420,75 @@ int x25_subscr_ioctl(unsigned int cmd, void __user *arg)
 	if ((nb = x25_get_neigh(dev)) == NULL)
 		goto out_dev_put;
 
-	dev_put(dev);
-
 	if (cmd == SIOCX25GSUBSCRIP) {
 		read_lock_bh(&x25_neigh_list_lock);
 		x25_subscr.extended	     = nb->extended;
+		x25_subscr.dce		     = nb->dce;
+		x25_subscr.lc		     = nb->lc;
+		x25_subscr.facilities	     = nb->facilities;
+		x25_subscr.t20		     = nb->t20;
 		x25_subscr.global_facil_mask = nb->global_facil_mask;
 		read_unlock_bh(&x25_neigh_list_lock);
 		rc = copy_to_user(arg, &x25_subscr,
 				  sizeof(x25_subscr)) ? -EFAULT : 0;
 	} else {
 		rc = -EINVAL;
-		if (!(x25_subscr.extended && x25_subscr.extended != 1)) {
-			rc = 0;
-			write_lock_bh(&x25_neigh_list_lock);
-			nb->extended	     = x25_subscr.extended;
-			nb->global_facil_mask = x25_subscr.global_facil_mask;
-			write_unlock_bh(&x25_neigh_list_lock);
+
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+
+		if (x25_subscr.extended != 0 && x25_subscr.extended != 1)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.dce != 0 && x25_subscr.dce != 1)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.lc < 1 || x25_subscr.lc > 4095)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.pacsize_in < X25_PS16 ||
+		    x25_subscr.facilities.pacsize_in > X25_PS4096)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.pacsize_out < X25_PS16 ||
+		    x25_subscr.facilities.pacsize_out > X25_PS4096)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.winsize_in < 1 ||
+		    x25_subscr.facilities.winsize_in > 127)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.facilities.throughput) {
+			int out = x25_subscr.facilities.throughput & 0xf0;
+			int in  = x25_subscr.facilities.throughput & 0x0f;
+			if (!out)
+				x25_subscr.facilities.throughput |=
+					X25_DEFAULT_THROUGHPUT << 4;
+			else if (out < 0x30 || out > 0xD0)
+				goto out_dev_and_neigh_put;
+			if (!in)
+				x25_subscr.facilities.throughput |=
+					X25_DEFAULT_THROUGHPUT;
+			else if (in < 0x03 || in > 0x0D)
+				goto out_dev_and_neigh_put;
 		}
+		if (x25_subscr.facilities.reverse &&
+		    (x25_subscr.facilities.reverse & 0x81) != 0x81)
+			goto out_dev_and_neigh_put;
+		if (x25_subscr.t20 < 1 * HZ || x25_subscr.t20 > 300 * HZ)
+			goto out_dev_and_neigh_put;
+
+		rc = 0;
+		write_lock_bh(&x25_neigh_list_lock);
+		nb->extended	      = x25_subscr.extended;
+		nb->dce		      = x25_subscr.dce;
+		nb->lc		      = x25_subscr.lc;
+		nb->facilities	      = x25_subscr.facilities;
+		nb->t20		      = x25_subscr.t20;
+		nb->global_facil_mask = x25_subscr.global_facil_mask;
+		write_unlock_bh(&x25_neigh_list_lock);
 	}
+	dev_put(dev);
+
 	x25_neigh_put(nb);
 out:
 	return rc;
+out_dev_and_neigh_put:
+	x25_neigh_put(nb);
 out_dev_put:
 	dev_put(dev);
 	goto out;
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 0285aaa1e93c..b1bbabfbe26f 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -218,15 +218,31 @@ void x25_write_internal(struct sock *sk, int frametype)
 		case X25_CLEAR_REQUEST:
 			dptr    = skb_put(skb, 3);
 			*dptr++ = frametype;
-			*dptr++ = x25->causediag.cause;
+
+			*dptr = x25->causediag.cause;
+
+			/* set bit 8, if DTE and cause != 0x00 */
+			if (!x25->neighbour->dce && *dptr != 0x00)
+				*dptr |= (unsigned char) 0x80;
+
+			dptr++;
+
 			*dptr++ = x25->causediag.diagnostic;
 			break;
 
 		case X25_RESET_REQUEST:
 			dptr    = skb_put(skb, 3);
 			*dptr++ = frametype;
-			*dptr++ = 0x00;		/* XXX */
-			*dptr++ = 0x00;		/* XXX */
+
+			*dptr = 0x00;	/* cause */
+
+			/* set bit 8, if DTE and cause != 0x00 */
+			if (!x25->neighbour->dce && *dptr != 0x00)
+				*dptr |= (unsigned char) 0x80;
+
+			dptr++;
+
+			*dptr++ = 0x00;	/* diagnostic */
 			break;
 
 		case X25_RR:
-- 
2.20.1


  reply	other threads:[~2020-11-16  7:31 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-16  7:31 [PATCH 1/6] net/x25: add/remove x25_link_device by NETDEV_REGISTER/UNREGISTER Martin Schiller
2020-11-16  7:31 ` Martin Schiller [this message]
2020-11-16 13:10   ` [PATCH 2/6] net/x25: make neighbour params configurable kernel test robot
2020-11-16 13:10     ` kernel test robot
2020-11-16  7:31 ` [PATCH 3/6] net/x25: replace x25_kill_by_device with x25_kill_by_neigh Martin Schiller
2020-11-16  7:31 ` [PATCH 4/6] net/x25: support NETDEV_CHANGE notifier Martin Schiller
2020-11-16  7:31 ` [PATCH 5/6] net/lapb: support netdev events Martin Schiller
2020-11-16  7:31 ` [PATCH 6/6] net/lapb: fix t1 timer handling Martin Schiller
2020-11-16  8:45 ` [PATCH 1/6] net/x25: add/remove x25_link_device by NETDEV_REGISTER/UNREGISTER Xie He
2020-11-16  8:59   ` Martin Schiller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201116073149.23219-2-ms@dev.tdt.de \
    --to=ms@dev.tdt.de \
    --cc=andrew.hendry@gmail.com \
    --cc=davem@davemloft.net \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-x25@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=xie.he.0141@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.