2019-05-21 01:08:06 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* X.25 Packet Layer release 002
|
|
|
|
*
|
|
|
|
* This is ALPHA test software. This code may break your machine,
|
|
|
|
* randomly fail to work with new releases, misbehave and/or generally
|
2007-02-09 22:25:27 +08:00
|
|
|
* screw up. It might even work.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* This code REQUIRES 2.1.15 or higher
|
|
|
|
*
|
|
|
|
* History
|
|
|
|
* X.25 001 Jonathan Naylor Started coding.
|
|
|
|
* X.25 002 Jonathan Naylor Centralised disconnect handling.
|
|
|
|
* New timer architecture.
|
|
|
|
* 2000-03-11 Henner Eisen MSG_EOR handling more POSIX compliant.
|
2007-02-09 22:25:27 +08:00
|
|
|
* 2000-03-22 Daniela Squassoni Allowed disabling/enabling of
|
|
|
|
* facilities negotiation and increased
|
2005-04-17 06:20:36 +08:00
|
|
|
* the throughput upper limit.
|
|
|
|
* 2000-08-27 Arnaldo C. Melo s/suser/capable/ + micro cleanups
|
2007-02-09 22:25:27 +08:00
|
|
|
* 2000-09-04 Henner Eisen Set sock->state in x25_accept().
|
2005-04-17 06:20:36 +08:00
|
|
|
* Fixed x25_output() related skb leakage.
|
|
|
|
* 2000-10-02 Henner Eisen Made x25_kick() single threaded per socket.
|
|
|
|
* 2000-10-27 Henner Eisen MSG_DONTWAIT for fragment allocation.
|
|
|
|
* 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN
|
|
|
|
* 2002-10-06 Arnaldo C. Melo Get rid of cli/sti, move proc stuff to
|
|
|
|
* x25_proc.c, using seq_file
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
* 2005-04-02 Shaun Pereira Selective sub address matching
|
|
|
|
* with call user data
|
[X25]: Fast select with no restriction on response
This patch is a follow up to patch 1 regarding "Selective Sub Address
matching with call user data". It allows use of the Fast-Select-Acceptance
optional user facility for X.25.
This patch just implements fast select with no restriction on response
(NRR). What this means (according to ITU-T Recomendation 10/96 section
6.16) is that if in an incoming call packet, the relevant facility bits are
set for fast-select-NRR, then the called DTE can issue a direct response to
the incoming packet using a call-accepted packet that contains
call-user-data. This patch allows such a response.
The called DTE can also respond with a clear-request packet that contains
call-user-data. However, this feature is currently not implemented by the
patch.
How is Fast Select Acceptance used?
By default, the system does not allow fast select acceptance (as before).
To enable a response to fast select acceptance,
After a listen socket in created and bound as follows
socket(AF_X25, SOCK_SEQPACKET, 0);
bind(call_soc, (struct sockaddr *)&locl_addr, sizeof(locl_addr));
but before a listen system call is made, the following ioctl should be used.
ioctl(call_soc,SIOCX25CALLACCPTAPPRV);
Now the listen system call can be made
listen(call_soc, 4);
After this, an incoming-call packet will be accepted, but no call-accepted
packet will be sent back until the following system call is made on the socket
that accepts the call
ioctl(vc_soc,SIOCX25SENDCALLACCPT);
The network (or cisco xot router used for testing here) will allow the
application server's call-user-data in the call-accepted packet,
provided the call-request was made with Fast-select NRR.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:16:17 +08:00
|
|
|
* 2005-04-15 Shaun Pereira Fast select with no restriction on
|
|
|
|
* response
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
|
2013-12-06 19:24:33 +08:00
|
|
|
#define pr_fmt(fmt) "X25: " fmt
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/module.h>
|
2006-01-12 04:17:47 +08:00
|
|
|
#include <linux/capability.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/kernel.h>
|
2017-02-09 01:51:30 +08:00
|
|
|
#include <linux/sched/signal.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/timer.h>
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/net.h>
|
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#include <linux/if_arp.h>
|
|
|
|
#include <linux/skbuff.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <net/sock.h>
|
2005-08-10 11:08:28 +08:00
|
|
|
#include <net/tcp_states.h>
|
2016-12-25 03:46:01 +08:00
|
|
|
#include <linux/uaccess.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/fcntl.h>
|
|
|
|
#include <linux/termios.h> /* For TIOCINQ/OUTQ */
|
|
|
|
#include <linux/notifier.h>
|
|
|
|
#include <linux/init.h>
|
2006-03-22 16:00:12 +08:00
|
|
|
#include <linux/compat.h>
|
2010-02-14 10:00:45 +08:00
|
|
|
#include <linux/ctype.h>
|
2006-03-22 16:00:12 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <net/x25.h>
|
2006-03-22 16:00:12 +08:00
|
|
|
#include <net/compat.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
|
|
|
|
int sysctl_x25_call_request_timeout = X25_DEFAULT_T21;
|
|
|
|
int sysctl_x25_reset_request_timeout = X25_DEFAULT_T22;
|
|
|
|
int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23;
|
|
|
|
int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2;
|
2007-02-09 05:34:36 +08:00
|
|
|
int sysctl_x25_forward = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
HLIST_HEAD(x25_list);
|
|
|
|
DEFINE_RWLOCK(x25_list_lock);
|
|
|
|
|
2005-12-23 04:49:22 +08:00
|
|
|
static const struct proto_ops x25_proto_ops;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-08-02 17:35:00 +08:00
|
|
|
static const struct x25_address null_x25_address = {" "};
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:00:12 +08:00
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
struct compat_x25_subscrip_struct {
|
|
|
|
char device[200-sizeof(compat_ulong_t)];
|
|
|
|
compat_ulong_t global_facil_mask;
|
|
|
|
compat_uint_t extended;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2010-04-08 12:29:25 +08:00
|
|
|
|
|
|
|
int x25_parse_address_block(struct sk_buff *skb,
|
|
|
|
struct x25_address *called_addr,
|
|
|
|
struct x25_address *calling_addr)
|
|
|
|
{
|
|
|
|
unsigned char len;
|
|
|
|
int needed;
|
|
|
|
int rc;
|
|
|
|
|
2011-10-15 02:45:04 +08:00
|
|
|
if (!pskb_may_pull(skb, 1)) {
|
2010-04-08 12:29:25 +08:00
|
|
|
/* packet has no address block */
|
|
|
|
rc = 0;
|
|
|
|
goto empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = *skb->data;
|
2018-11-27 16:50:27 +08:00
|
|
|
needed = 1 + ((len >> 4) + (len & 0x0f) + 1) / 2;
|
2010-04-08 12:29:25 +08:00
|
|
|
|
2011-10-15 02:45:04 +08:00
|
|
|
if (!pskb_may_pull(skb, needed)) {
|
2010-04-08 12:29:25 +08:00
|
|
|
/* packet is too short to hold the addresses it claims
|
|
|
|
to hold */
|
|
|
|
rc = -1;
|
|
|
|
goto empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
return x25_addr_ntoa(skb->data, called_addr, calling_addr);
|
|
|
|
|
|
|
|
empty:
|
|
|
|
*called_addr->x25_addr = 0;
|
|
|
|
*calling_addr->x25_addr = 0;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
|
|
|
|
struct x25_address *calling_addr)
|
|
|
|
{
|
2008-01-14 14:27:52 +08:00
|
|
|
unsigned int called_len, calling_len;
|
2005-04-17 06:20:36 +08:00
|
|
|
char *called, *calling;
|
2008-01-14 14:27:52 +08:00
|
|
|
unsigned int i;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
called_len = (*p >> 0) & 0x0F;
|
|
|
|
calling_len = (*p >> 4) & 0x0F;
|
|
|
|
|
|
|
|
called = called_addr->x25_addr;
|
|
|
|
calling = calling_addr->x25_addr;
|
|
|
|
p++;
|
|
|
|
|
|
|
|
for (i = 0; i < (called_len + calling_len); i++) {
|
|
|
|
if (i < called_len) {
|
|
|
|
if (i % 2 != 0) {
|
|
|
|
*called++ = ((*p >> 0) & 0x0F) + '0';
|
|
|
|
p++;
|
|
|
|
} else {
|
|
|
|
*called++ = ((*p >> 4) & 0x0F) + '0';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (i % 2 != 0) {
|
|
|
|
*calling++ = ((*p >> 0) & 0x0F) + '0';
|
|
|
|
p++;
|
|
|
|
} else {
|
|
|
|
*calling++ = ((*p >> 4) & 0x0F) + '0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*called = *calling = '\0';
|
|
|
|
|
|
|
|
return 1 + (called_len + calling_len + 1) / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x25_addr_aton(unsigned char *p, struct x25_address *called_addr,
|
|
|
|
struct x25_address *calling_addr)
|
|
|
|
{
|
|
|
|
unsigned int called_len, calling_len;
|
|
|
|
char *called, *calling;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
called = called_addr->x25_addr;
|
|
|
|
calling = calling_addr->x25_addr;
|
|
|
|
|
|
|
|
called_len = strlen(called);
|
|
|
|
calling_len = strlen(calling);
|
|
|
|
|
|
|
|
*p++ = (calling_len << 4) | (called_len << 0);
|
|
|
|
|
|
|
|
for (i = 0; i < (called_len + calling_len); i++) {
|
|
|
|
if (i < called_len) {
|
|
|
|
if (i % 2 != 0) {
|
|
|
|
*p |= (*called++ - '0') << 0;
|
|
|
|
p++;
|
|
|
|
} else {
|
|
|
|
*p = 0x00;
|
|
|
|
*p |= (*called++ - '0') << 4;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (i % 2 != 0) {
|
|
|
|
*p |= (*calling++ - '0') << 0;
|
|
|
|
p++;
|
|
|
|
} else {
|
|
|
|
*p = 0x00;
|
|
|
|
*p |= (*calling++ - '0') << 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1 + (called_len + calling_len + 1) / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Socket removal during an interrupt is now safe.
|
|
|
|
*/
|
|
|
|
static void x25_remove_socket(struct sock *sk)
|
|
|
|
{
|
|
|
|
write_lock_bh(&x25_list_lock);
|
|
|
|
sk_del_node_init(sk);
|
|
|
|
write_unlock_bh(&x25_list_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle device status changes.
|
|
|
|
*/
|
|
|
|
static int x25_device_event(struct notifier_block *this, unsigned long event,
|
|
|
|
void *ptr)
|
|
|
|
{
|
2013-05-28 09:30:21 +08:00
|
|
|
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
2005-04-17 06:20:36 +08:00
|
|
|
struct x25_neigh *nb;
|
|
|
|
|
2008-07-20 13:34:43 +08:00
|
|
|
if (!net_eq(dev_net(dev), &init_net))
|
2007-09-12 19:02:17 +08:00
|
|
|
return NOTIFY_DONE;
|
|
|
|
|
2020-12-09 11:33:46 +08:00
|
|
|
if (dev->type == ARPHRD_X25) {
|
2005-04-17 06:20:36 +08:00
|
|
|
switch (event) {
|
2020-11-26 14:35:53 +08:00
|
|
|
case NETDEV_REGISTER:
|
|
|
|
case NETDEV_POST_TYPE_CHANGE:
|
2011-07-01 17:43:13 +08:00
|
|
|
x25_link_device_up(dev);
|
|
|
|
break;
|
2020-11-26 14:35:53 +08:00
|
|
|
case NETDEV_DOWN:
|
2011-07-01 17:43:13 +08:00
|
|
|
nb = x25_get_neigh(dev);
|
|
|
|
if (nb) {
|
2020-11-26 14:35:53 +08:00
|
|
|
x25_link_terminated(nb);
|
2011-07-01 17:43:13 +08:00
|
|
|
x25_neigh_put(nb);
|
|
|
|
}
|
|
|
|
x25_route_device_down(dev);
|
2020-11-26 14:35:53 +08:00
|
|
|
break;
|
|
|
|
case NETDEV_PRE_TYPE_CHANGE:
|
|
|
|
case NETDEV_UNREGISTER:
|
2011-07-01 17:43:13 +08:00
|
|
|
x25_link_device_down(dev);
|
|
|
|
break;
|
2020-11-26 14:35:53 +08:00
|
|
|
case NETDEV_CHANGE:
|
|
|
|
if (!netif_carrier_ok(dev)) {
|
|
|
|
nb = x25_get_neigh(dev);
|
|
|
|
if (nb) {
|
|
|
|
x25_link_terminated(nb);
|
|
|
|
x25_neigh_put(nb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NOTIFY_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add a socket to the bound sockets list.
|
|
|
|
*/
|
|
|
|
static void x25_insert_socket(struct sock *sk)
|
|
|
|
{
|
|
|
|
write_lock_bh(&x25_list_lock);
|
|
|
|
sk_add_node(sk, &x25_list);
|
|
|
|
write_unlock_bh(&x25_list_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find a socket that wants to accept the Call Request we just
|
|
|
|
* received. Check the full list for an address/cud match.
|
|
|
|
* If no cuds match return the next_best thing, an address match.
|
|
|
|
* Note: if a listening socket has cud set it must only get calls
|
|
|
|
* with matching cud.
|
|
|
|
*/
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
static struct sock *x25_find_listener(struct x25_address *addr,
|
|
|
|
struct sk_buff *skb)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sock *s;
|
|
|
|
struct sock *next_best;
|
|
|
|
|
|
|
|
read_lock_bh(&x25_list_lock);
|
|
|
|
next_best = NULL;
|
|
|
|
|
hlist: drop the node parameter from iterators
I'm not sure why, but the hlist for each entry iterators were conceived
list_for_each_entry(pos, head, member)
The hlist ones were greedy and wanted an extra parameter:
hlist_for_each_entry(tpos, pos, head, member)
Why did they need an extra pos parameter? I'm not quite sure. Not only
they don't really need it, it also prevents the iterator from looking
exactly like the list iterator, which is unfortunate.
Besides the semantic patch, there was some manual work required:
- Fix up the actual hlist iterators in linux/list.h
- Fix up the declaration of other iterators based on the hlist ones.
- A very small amount of places were using the 'node' parameter, this
was modified to use 'obj->member' instead.
- Coccinelle didn't handle the hlist_for_each_entry_safe iterator
properly, so those had to be fixed up manually.
The semantic patch which is mostly the work of Peter Senna Tschudin is here:
@@
iterator name hlist_for_each_entry, hlist_for_each_entry_continue, hlist_for_each_entry_from, hlist_for_each_entry_rcu, hlist_for_each_entry_rcu_bh, hlist_for_each_entry_continue_rcu_bh, for_each_busy_worker, ax25_uid_for_each, ax25_for_each, inet_bind_bucket_for_each, sctp_for_each_hentry, sk_for_each, sk_for_each_rcu, sk_for_each_from, sk_for_each_safe, sk_for_each_bound, hlist_for_each_entry_safe, hlist_for_each_entry_continue_rcu, nr_neigh_for_each, nr_neigh_for_each_safe, nr_node_for_each, nr_node_for_each_safe, for_each_gfn_indirect_valid_sp, for_each_gfn_sp, for_each_host;
type T;
expression a,c,d,e;
identifier b;
statement S;
@@
-T b;
<+... when != b
(
hlist_for_each_entry(a,
- b,
c, d) S
|
hlist_for_each_entry_continue(a,
- b,
c) S
|
hlist_for_each_entry_from(a,
- b,
c) S
|
hlist_for_each_entry_rcu(a,
- b,
c, d) S
|
hlist_for_each_entry_rcu_bh(a,
- b,
c, d) S
|
hlist_for_each_entry_continue_rcu_bh(a,
- b,
c) S
|
for_each_busy_worker(a, c,
- b,
d) S
|
ax25_uid_for_each(a,
- b,
c) S
|
ax25_for_each(a,
- b,
c) S
|
inet_bind_bucket_for_each(a,
- b,
c) S
|
sctp_for_each_hentry(a,
- b,
c) S
|
sk_for_each(a,
- b,
c) S
|
sk_for_each_rcu(a,
- b,
c) S
|
sk_for_each_from
-(a, b)
+(a)
S
+ sk_for_each_from(a) S
|
sk_for_each_safe(a,
- b,
c, d) S
|
sk_for_each_bound(a,
- b,
c) S
|
hlist_for_each_entry_safe(a,
- b,
c, d, e) S
|
hlist_for_each_entry_continue_rcu(a,
- b,
c) S
|
nr_neigh_for_each(a,
- b,
c) S
|
nr_neigh_for_each_safe(a,
- b,
c, d) S
|
nr_node_for_each(a,
- b,
c) S
|
nr_node_for_each_safe(a,
- b,
c, d) S
|
- for_each_gfn_sp(a, c, d, b) S
+ for_each_gfn_sp(a, c, d) S
|
- for_each_gfn_indirect_valid_sp(a, c, d, b) S
+ for_each_gfn_indirect_valid_sp(a, c, d) S
|
for_each_host(a,
- b,
c) S
|
for_each_host_safe(a,
- b,
c, d) S
|
for_each_mesh_entry(a,
- b,
c, d) S
)
...+>
[akpm@linux-foundation.org: drop bogus change from net/ipv4/raw.c]
[akpm@linux-foundation.org: drop bogus hunk from net/ipv6/raw.c]
[akpm@linux-foundation.org: checkpatch fixes]
[akpm@linux-foundation.org: fix warnings]
[akpm@linux-foudnation.org: redo intrusive kvm changes]
Tested-by: Peter Senna Tschudin <peter.senna@gmail.com>
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-02-28 09:06:00 +08:00
|
|
|
sk_for_each(s, &x25_list)
|
2005-04-17 06:20:36 +08:00
|
|
|
if ((!strcmp(addr->x25_addr,
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
x25_sk(s)->source_addr.x25_addr) ||
|
2018-11-27 16:50:28 +08:00
|
|
|
!strcmp(x25_sk(s)->source_addr.x25_addr,
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
null_x25_address.x25_addr)) &&
|
|
|
|
s->sk_state == TCP_LISTEN) {
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Found a listening socket, now check the incoming
|
|
|
|
* call user data vs this sockets call user data
|
|
|
|
*/
|
2011-10-15 02:45:05 +08:00
|
|
|
if (x25_sk(s)->cudmatchlength > 0 &&
|
|
|
|
skb->len >= x25_sk(s)->cudmatchlength) {
|
2007-02-09 22:25:27 +08:00
|
|
|
if((memcmp(x25_sk(s)->calluserdata.cuddata,
|
|
|
|
skb->data,
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
x25_sk(s)->cudmatchlength)) == 0) {
|
|
|
|
sock_hold(s);
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
} else
|
2005-04-17 06:20:36 +08:00
|
|
|
next_best = s;
|
|
|
|
}
|
|
|
|
if (next_best) {
|
|
|
|
s = next_best;
|
|
|
|
sock_hold(s);
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
s = NULL;
|
|
|
|
found:
|
|
|
|
read_unlock_bh(&x25_list_lock);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find a connected X.25 socket given my LCI and neighbour.
|
|
|
|
*/
|
|
|
|
static struct sock *__x25_find_socket(unsigned int lci, struct x25_neigh *nb)
|
|
|
|
{
|
|
|
|
struct sock *s;
|
|
|
|
|
hlist: drop the node parameter from iterators
I'm not sure why, but the hlist for each entry iterators were conceived
list_for_each_entry(pos, head, member)
The hlist ones were greedy and wanted an extra parameter:
hlist_for_each_entry(tpos, pos, head, member)
Why did they need an extra pos parameter? I'm not quite sure. Not only
they don't really need it, it also prevents the iterator from looking
exactly like the list iterator, which is unfortunate.
Besides the semantic patch, there was some manual work required:
- Fix up the actual hlist iterators in linux/list.h
- Fix up the declaration of other iterators based on the hlist ones.
- A very small amount of places were using the 'node' parameter, this
was modified to use 'obj->member' instead.
- Coccinelle didn't handle the hlist_for_each_entry_safe iterator
properly, so those had to be fixed up manually.
The semantic patch which is mostly the work of Peter Senna Tschudin is here:
@@
iterator name hlist_for_each_entry, hlist_for_each_entry_continue, hlist_for_each_entry_from, hlist_for_each_entry_rcu, hlist_for_each_entry_rcu_bh, hlist_for_each_entry_continue_rcu_bh, for_each_busy_worker, ax25_uid_for_each, ax25_for_each, inet_bind_bucket_for_each, sctp_for_each_hentry, sk_for_each, sk_for_each_rcu, sk_for_each_from, sk_for_each_safe, sk_for_each_bound, hlist_for_each_entry_safe, hlist_for_each_entry_continue_rcu, nr_neigh_for_each, nr_neigh_for_each_safe, nr_node_for_each, nr_node_for_each_safe, for_each_gfn_indirect_valid_sp, for_each_gfn_sp, for_each_host;
type T;
expression a,c,d,e;
identifier b;
statement S;
@@
-T b;
<+... when != b
(
hlist_for_each_entry(a,
- b,
c, d) S
|
hlist_for_each_entry_continue(a,
- b,
c) S
|
hlist_for_each_entry_from(a,
- b,
c) S
|
hlist_for_each_entry_rcu(a,
- b,
c, d) S
|
hlist_for_each_entry_rcu_bh(a,
- b,
c, d) S
|
hlist_for_each_entry_continue_rcu_bh(a,
- b,
c) S
|
for_each_busy_worker(a, c,
- b,
d) S
|
ax25_uid_for_each(a,
- b,
c) S
|
ax25_for_each(a,
- b,
c) S
|
inet_bind_bucket_for_each(a,
- b,
c) S
|
sctp_for_each_hentry(a,
- b,
c) S
|
sk_for_each(a,
- b,
c) S
|
sk_for_each_rcu(a,
- b,
c) S
|
sk_for_each_from
-(a, b)
+(a)
S
+ sk_for_each_from(a) S
|
sk_for_each_safe(a,
- b,
c, d) S
|
sk_for_each_bound(a,
- b,
c) S
|
hlist_for_each_entry_safe(a,
- b,
c, d, e) S
|
hlist_for_each_entry_continue_rcu(a,
- b,
c) S
|
nr_neigh_for_each(a,
- b,
c) S
|
nr_neigh_for_each_safe(a,
- b,
c, d) S
|
nr_node_for_each(a,
- b,
c) S
|
nr_node_for_each_safe(a,
- b,
c, d) S
|
- for_each_gfn_sp(a, c, d, b) S
+ for_each_gfn_sp(a, c, d) S
|
- for_each_gfn_indirect_valid_sp(a, c, d, b) S
+ for_each_gfn_indirect_valid_sp(a, c, d) S
|
for_each_host(a,
- b,
c) S
|
for_each_host_safe(a,
- b,
c, d) S
|
for_each_mesh_entry(a,
- b,
c, d) S
)
...+>
[akpm@linux-foundation.org: drop bogus change from net/ipv4/raw.c]
[akpm@linux-foundation.org: drop bogus hunk from net/ipv6/raw.c]
[akpm@linux-foundation.org: checkpatch fixes]
[akpm@linux-foundation.org: fix warnings]
[akpm@linux-foudnation.org: redo intrusive kvm changes]
Tested-by: Peter Senna Tschudin <peter.senna@gmail.com>
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-02-28 09:06:00 +08:00
|
|
|
sk_for_each(s, &x25_list)
|
2005-04-17 06:20:36 +08:00
|
|
|
if (x25_sk(s)->lci == lci && x25_sk(s)->neighbour == nb) {
|
|
|
|
sock_hold(s);
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
s = NULL;
|
|
|
|
found:
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *nb)
|
|
|
|
{
|
|
|
|
struct sock *s;
|
|
|
|
|
|
|
|
read_lock_bh(&x25_list_lock);
|
|
|
|
s = __x25_find_socket(lci, nb);
|
|
|
|
read_unlock_bh(&x25_list_lock);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find a unique LCI for a given device.
|
|
|
|
*/
|
|
|
|
static unsigned int x25_new_lci(struct x25_neigh *nb)
|
|
|
|
{
|
|
|
|
unsigned int lci = 1;
|
|
|
|
struct sock *sk;
|
|
|
|
|
2019-02-09 04:41:05 +08:00
|
|
|
while ((sk = x25_find_socket(lci, nb)) != NULL) {
|
2005-04-17 06:20:36 +08:00
|
|
|
sock_put(sk);
|
|
|
|
if (++lci == 4096) {
|
|
|
|
lci = 0;
|
|
|
|
break;
|
|
|
|
}
|
2019-02-09 04:41:05 +08:00
|
|
|
cond_resched();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return lci;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deferred destroy.
|
|
|
|
*/
|
2009-06-16 20:40:30 +08:00
|
|
|
static void __x25_destroy_socket(struct sock *);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* handler for deferred kills.
|
|
|
|
*/
|
2017-10-17 08:29:36 +08:00
|
|
|
static void x25_destroy_timer(struct timer_list *t)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2017-10-17 08:29:36 +08:00
|
|
|
struct sock *sk = from_timer(sk, t, sk_timer);
|
|
|
|
|
|
|
|
x25_destroy_socket_from_timer(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is called from user mode and the timers. Thus it protects itself
|
2021-06-09 11:03:17 +08:00
|
|
|
* against interrupting users but doesn't worry about being called during
|
2005-04-17 06:20:36 +08:00
|
|
|
* work. Once it is removed from the queue no interrupt or bottom half
|
|
|
|
* will touch it and we are (fairly 8-) ) safe.
|
|
|
|
* Not static as it's used by the timer
|
|
|
|
*/
|
2009-06-16 20:40:30 +08:00
|
|
|
static void __x25_destroy_socket(struct sock *sk)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
x25_stop_heartbeat(sk);
|
|
|
|
x25_stop_timer(sk);
|
|
|
|
|
|
|
|
x25_remove_socket(sk);
|
|
|
|
x25_clear_queues(sk); /* Flush the queues */
|
|
|
|
|
|
|
|
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
|
|
|
|
if (skb->sk != sk) { /* A pending connection */
|
|
|
|
/*
|
|
|
|
* Queue the unaccepted socket for death
|
|
|
|
*/
|
2010-04-17 22:17:32 +08:00
|
|
|
skb->sk->sk_state = TCP_LISTEN;
|
2005-04-17 06:20:36 +08:00
|
|
|
sock_set_flag(skb->sk, SOCK_DEAD);
|
|
|
|
x25_start_heartbeat(skb->sk);
|
|
|
|
x25_sk(skb->sk)->state = X25_STATE_0;
|
|
|
|
}
|
|
|
|
|
|
|
|
kfree_skb(skb);
|
|
|
|
}
|
|
|
|
|
2009-06-16 18:12:03 +08:00
|
|
|
if (sk_has_allocations(sk)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
/* Defer: outstanding buffers */
|
|
|
|
sk->sk_timer.expires = jiffies + 10 * HZ;
|
2017-10-23 15:40:42 +08:00
|
|
|
sk->sk_timer.function = x25_destroy_timer;
|
2005-04-17 06:20:36 +08:00
|
|
|
add_timer(&sk->sk_timer);
|
|
|
|
} else {
|
|
|
|
/* drop last reference so sock_put will free */
|
|
|
|
__sock_put(sk);
|
|
|
|
}
|
2009-06-16 20:40:30 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-06-16 20:40:30 +08:00
|
|
|
void x25_destroy_socket_from_timer(struct sock *sk)
|
|
|
|
{
|
|
|
|
sock_hold(sk);
|
|
|
|
bh_lock_sock(sk);
|
|
|
|
__x25_destroy_socket(sk);
|
|
|
|
bh_unlock_sock(sk);
|
|
|
|
sock_put(sk);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Handling for system calls applied via the various interfaces to a
|
|
|
|
* X.25 socket object.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int x25_setsockopt(struct socket *sock, int level, int optname,
|
2020-07-23 14:09:07 +08:00
|
|
|
sockptr_t optval, unsigned int optlen)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int opt;
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
int rc = -ENOPROTOOPT;
|
|
|
|
|
|
|
|
if (level != SOL_X25 || optname != X25_QBITINCL)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (optlen < sizeof(int))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -EFAULT;
|
2020-07-23 14:09:07 +08:00
|
|
|
if (copy_from_sockptr(&opt, optval, sizeof(int)))
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
2010-05-17 06:59:41 +08:00
|
|
|
if (opt)
|
|
|
|
set_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
|
|
|
|
else
|
|
|
|
clear_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
|
2005-04-17 06:20:36 +08:00
|
|
|
rc = 0;
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int x25_getsockopt(struct socket *sock, int level, int optname,
|
|
|
|
char __user *optval, int __user *optlen)
|
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
int val, len, rc = -ENOPROTOOPT;
|
2007-02-09 22:25:27 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (level != SOL_X25 || optname != X25_QBITINCL)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -EFAULT;
|
|
|
|
if (get_user(len, optlen))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
len = min_t(unsigned int, len, sizeof(int));
|
|
|
|
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (len < 0)
|
|
|
|
goto out;
|
2007-02-09 22:25:27 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
rc = -EFAULT;
|
|
|
|
if (put_user(len, optlen))
|
|
|
|
goto out;
|
|
|
|
|
2010-05-17 06:59:41 +08:00
|
|
|
val = test_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
|
2005-04-17 06:20:36 +08:00
|
|
|
rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int x25_listen(struct socket *sock, int backlog)
|
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
int rc = -EOPNOTSUPP;
|
|
|
|
|
2010-09-14 21:31:16 +08:00
|
|
|
lock_sock(sk);
|
2023-01-24 03:43:23 +08:00
|
|
|
if (sock->state != SS_UNCONNECTED) {
|
|
|
|
rc = -EINVAL;
|
|
|
|
release_sock(sk);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (sk->sk_state != TCP_LISTEN) {
|
|
|
|
memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
|
|
|
|
sk->sk_max_ack_backlog = backlog;
|
|
|
|
sk->sk_state = TCP_LISTEN;
|
|
|
|
rc = 0;
|
|
|
|
}
|
2010-09-14 21:31:16 +08:00
|
|
|
release_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct proto x25_proto = {
|
|
|
|
.name = "X25",
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.obj_size = sizeof(struct x25_sock),
|
|
|
|
};
|
|
|
|
|
2015-05-09 10:09:13 +08:00
|
|
|
static struct sock *x25_alloc_socket(struct net *net, int kern)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct x25_sock *x25;
|
2015-05-09 10:09:13 +08:00
|
|
|
struct sock *sk = sk_alloc(net, AF_X25, GFP_ATOMIC, &x25_proto, kern);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (!sk)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
sock_init_data(NULL, sk);
|
|
|
|
|
|
|
|
x25 = x25_sk(sk);
|
|
|
|
skb_queue_head_init(&x25->ack_queue);
|
|
|
|
skb_queue_head_init(&x25->fragment_queue);
|
|
|
|
skb_queue_head_init(&x25->interrupt_in_queue);
|
|
|
|
skb_queue_head_init(&x25->interrupt_out_queue);
|
|
|
|
out:
|
|
|
|
return sk;
|
|
|
|
}
|
|
|
|
|
2009-11-06 14:18:14 +08:00
|
|
|
static int x25_create(struct net *net, struct socket *sock, int protocol,
|
|
|
|
int kern)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sock *sk;
|
|
|
|
struct x25_sock *x25;
|
2010-02-14 10:00:11 +08:00
|
|
|
int rc = -EAFNOSUPPORT;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-11-26 07:14:13 +08:00
|
|
|
if (!net_eq(net, &init_net))
|
2010-02-14 10:00:11 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -ESOCKTNOSUPPORT;
|
|
|
|
if (sock->type != SOCK_SEQPACKET)
|
|
|
|
goto out;
|
2007-10-09 14:24:22 +08:00
|
|
|
|
2010-02-14 10:00:11 +08:00
|
|
|
rc = -EINVAL;
|
|
|
|
if (protocol)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
2021-06-02 22:06:30 +08:00
|
|
|
rc = -ENOMEM;
|
2015-05-09 10:09:13 +08:00
|
|
|
if ((sk = x25_alloc_socket(net, kern)) == NULL)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
x25 = x25_sk(sk);
|
|
|
|
|
|
|
|
sock_init_data(sock, sk);
|
|
|
|
|
|
|
|
x25_init_timers(sk);
|
|
|
|
|
|
|
|
sock->ops = &x25_proto_ops;
|
|
|
|
sk->sk_protocol = protocol;
|
|
|
|
sk->sk_backlog_rcv = x25_backlog_rcv;
|
|
|
|
|
|
|
|
x25->t21 = sysctl_x25_call_request_timeout;
|
|
|
|
x25->t22 = sysctl_x25_reset_request_timeout;
|
|
|
|
x25->t23 = sysctl_x25_clear_request_timeout;
|
|
|
|
x25->t2 = sysctl_x25_ack_holdback_timeout;
|
|
|
|
x25->state = X25_STATE_0;
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
x25->cudmatchlength = 0;
|
2010-05-17 07:00:27 +08:00
|
|
|
set_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); /* normally no cud */
|
[X25]: Fast select with no restriction on response
This patch is a follow up to patch 1 regarding "Selective Sub Address
matching with call user data". It allows use of the Fast-Select-Acceptance
optional user facility for X.25.
This patch just implements fast select with no restriction on response
(NRR). What this means (according to ITU-T Recomendation 10/96 section
6.16) is that if in an incoming call packet, the relevant facility bits are
set for fast-select-NRR, then the called DTE can issue a direct response to
the incoming packet using a call-accepted packet that contains
call-user-data. This patch allows such a response.
The called DTE can also respond with a clear-request packet that contains
call-user-data. However, this feature is currently not implemented by the
patch.
How is Fast Select Acceptance used?
By default, the system does not allow fast select acceptance (as before).
To enable a response to fast select acceptance,
After a listen socket in created and bound as follows
socket(AF_X25, SOCK_SEQPACKET, 0);
bind(call_soc, (struct sockaddr *)&locl_addr, sizeof(locl_addr));
but before a listen system call is made, the following ioctl should be used.
ioctl(call_soc,SIOCX25CALLACCPTAPPRV);
Now the listen system call can be made
listen(call_soc, 4);
After this, an incoming-call packet will be accepted, but no call-accepted
packet will be sent back until the following system call is made on the socket
that accepts the call
ioctl(vc_soc,SIOCX25SENDCALLACCPT);
The network (or cisco xot router used for testing here) will allow the
application server's call-user-data in the call-accepted packet,
provided the call-request was made with Fast-select NRR.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:16:17 +08:00
|
|
|
/* on call accept */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE;
|
|
|
|
x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
|
|
|
|
x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE;
|
|
|
|
x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
|
2010-04-04 14:48:10 +08:00
|
|
|
x25->facilities.throughput = 0; /* by default don't negotiate
|
|
|
|
throughput */
|
2005-04-17 06:20:36 +08:00
|
|
|
x25->facilities.reverse = X25_DEFAULT_REVERSE;
|
2007-02-09 22:25:27 +08:00
|
|
|
x25->dte_facilities.calling_len = 0;
|
|
|
|
x25->dte_facilities.called_len = 0;
|
|
|
|
memset(x25->dte_facilities.called_ae, '\0',
|
|
|
|
sizeof(x25->dte_facilities.called_ae));
|
|
|
|
memset(x25->dte_facilities.calling_ae, '\0',
|
|
|
|
sizeof(x25->dte_facilities.calling_ae));
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
rc = 0;
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct sock *x25_make_new(struct sock *osk)
|
|
|
|
{
|
|
|
|
struct sock *sk = NULL;
|
|
|
|
struct x25_sock *x25, *ox25;
|
|
|
|
|
|
|
|
if (osk->sk_type != SOCK_SEQPACKET)
|
|
|
|
goto out;
|
|
|
|
|
2015-05-09 10:09:13 +08:00
|
|
|
if ((sk = x25_alloc_socket(sock_net(osk), 0)) == NULL)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
x25 = x25_sk(sk);
|
|
|
|
|
|
|
|
sk->sk_type = osk->sk_type;
|
|
|
|
sk->sk_priority = osk->sk_priority;
|
|
|
|
sk->sk_protocol = osk->sk_protocol;
|
|
|
|
sk->sk_rcvbuf = osk->sk_rcvbuf;
|
|
|
|
sk->sk_sndbuf = osk->sk_sndbuf;
|
|
|
|
sk->sk_state = TCP_ESTABLISHED;
|
|
|
|
sk->sk_backlog_rcv = osk->sk_backlog_rcv;
|
2006-01-07 05:11:35 +08:00
|
|
|
sock_copy_flags(sk, osk);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
ox25 = x25_sk(osk);
|
|
|
|
x25->t21 = ox25->t21;
|
|
|
|
x25->t22 = ox25->t22;
|
|
|
|
x25->t23 = ox25->t23;
|
|
|
|
x25->t2 = ox25->t2;
|
2010-05-17 06:59:41 +08:00
|
|
|
x25->flags = ox25->flags;
|
2005-04-17 06:20:36 +08:00
|
|
|
x25->facilities = ox25->facilities;
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
x25->dte_facilities = ox25->dte_facilities;
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
x25->cudmatchlength = ox25->cudmatchlength;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-05-17 07:00:02 +08:00
|
|
|
clear_bit(X25_INTERRUPT_FLAG, &x25->flags);
|
2005-04-17 06:20:36 +08:00
|
|
|
x25_init_timers(sk);
|
|
|
|
out:
|
|
|
|
return sk;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int x25_release(struct socket *sock)
|
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct x25_sock *x25;
|
|
|
|
|
|
|
|
if (!sk)
|
2011-01-23 06:44:59 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
x25 = x25_sk(sk);
|
|
|
|
|
2011-01-23 06:44:59 +08:00
|
|
|
sock_hold(sk);
|
|
|
|
lock_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
switch (x25->state) {
|
|
|
|
|
|
|
|
case X25_STATE_0:
|
|
|
|
case X25_STATE_2:
|
|
|
|
x25_disconnect(sk, 0, 0, 0);
|
2011-01-23 06:44:59 +08:00
|
|
|
__x25_destroy_socket(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
case X25_STATE_1:
|
|
|
|
case X25_STATE_3:
|
|
|
|
case X25_STATE_4:
|
|
|
|
x25_clear_queues(sk);
|
|
|
|
x25_write_internal(sk, X25_CLEAR_REQUEST);
|
|
|
|
x25_start_t23timer(sk);
|
|
|
|
x25->state = X25_STATE_2;
|
|
|
|
sk->sk_state = TCP_CLOSE;
|
|
|
|
sk->sk_shutdown |= SEND_SHUTDOWN;
|
|
|
|
sk->sk_state_change(sk);
|
|
|
|
sock_set_flag(sk, SOCK_DEAD);
|
|
|
|
sock_set_flag(sk, SOCK_DESTROY);
|
|
|
|
break;
|
2019-12-09 15:21:34 +08:00
|
|
|
|
|
|
|
case X25_STATE_5:
|
|
|
|
x25_write_internal(sk, X25_CLEAR_REQUEST);
|
|
|
|
x25_disconnect(sk, 0, 0, 0);
|
|
|
|
__x25_destroy_socket(sk);
|
|
|
|
goto out;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2008-06-17 18:05:13 +08:00
|
|
|
sock_orphan(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
out:
|
2011-01-23 06:44:59 +08:00
|
|
|
release_sock(sk);
|
|
|
|
sock_put(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
|
2010-02-14 10:00:45 +08:00
|
|
|
int len, i, rc = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2019-02-24 05:24:59 +08:00
|
|
|
if (addr_len != sizeof(struct sockaddr_x25) ||
|
2020-12-01 23:15:12 +08:00
|
|
|
addr->sx25_family != AF_X25 ||
|
|
|
|
strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN) {
|
2009-11-05 12:37:29 +08:00
|
|
|
rc = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2018-11-27 16:50:28 +08:00
|
|
|
/* check for the null_x25_address */
|
|
|
|
if (strcmp(addr->sx25_addr.x25_addr, null_x25_address.x25_addr)) {
|
|
|
|
|
|
|
|
len = strlen(addr->sx25_addr.x25_addr);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (!isdigit(addr->sx25_addr.x25_addr[i])) {
|
|
|
|
rc = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2010-02-14 10:00:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-14 21:31:38 +08:00
|
|
|
lock_sock(sk);
|
2019-02-24 05:24:59 +08:00
|
|
|
if (sock_flag(sk, SOCK_ZAPPED)) {
|
|
|
|
x25_sk(sk)->source_addr = addr->sx25_addr;
|
|
|
|
x25_insert_socket(sk);
|
|
|
|
sock_reset_flag(sk, SOCK_ZAPPED);
|
|
|
|
} else {
|
|
|
|
rc = -EINVAL;
|
|
|
|
}
|
2010-09-14 21:31:38 +08:00
|
|
|
release_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
|
2009-11-05 12:37:29 +08:00
|
|
|
out:
|
|
|
|
return rc;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int x25_wait_for_connection_establishment(struct sock *sk)
|
|
|
|
{
|
|
|
|
DECLARE_WAITQUEUE(wait, current);
|
2007-02-09 22:25:27 +08:00
|
|
|
int rc;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-04-20 21:03:51 +08:00
|
|
|
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
2005-04-17 06:20:36 +08:00
|
|
|
for (;;) {
|
|
|
|
__set_current_state(TASK_INTERRUPTIBLE);
|
|
|
|
rc = -ERESTARTSYS;
|
|
|
|
if (signal_pending(current))
|
|
|
|
break;
|
|
|
|
rc = sock_error(sk);
|
|
|
|
if (rc) {
|
|
|
|
sk->sk_socket->state = SS_UNCONNECTED;
|
|
|
|
break;
|
|
|
|
}
|
net/x25: fix call timeouts in blocking connects
When a userspace application starts a blocking connect(), a CALL REQUEST
is sent, the t21 timer is started and the connect is waiting in
x25_wait_for_connection_establishment(). If then for some reason the t21
timer expires before any reaction on the assigned logical channel (e.g.
CALL ACCEPT, CLEAR REQUEST), there is sent a CLEAR REQUEST and timer
t23 is started waiting for a CLEAR confirmation. If we now receive a
CLEAR CONFIRMATION from the peer, x25_disconnect() is called in
x25_state2_machine() with reason "0", which means "normal" call
clearing. This is ok, but the parameter "reason" is used as sk->sk_err
in x25_disconnect() and sock_error(sk) is evaluated in
x25_wait_for_connection_establishment() to check if the call is still
pending. As "0" is not rated as an error, the connect will stuck here
forever.
To fix this situation, also check if the sk->sk_state changed form
TCP_SYN_SENT to TCP_CLOSE in the meantime, which is also done by
x25_disconnect().
Signed-off-by: Martin Schiller <ms@dev.tdt.de>
Link: https://lore.kernel.org/r/20220805061810.10824-1-ms@dev.tdt.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-08-05 14:18:10 +08:00
|
|
|
rc = -ENOTCONN;
|
|
|
|
if (sk->sk_state == TCP_CLOSE) {
|
|
|
|
sk->sk_socket->state = SS_UNCONNECTED;
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
rc = 0;
|
|
|
|
if (sk->sk_state != TCP_ESTABLISHED) {
|
|
|
|
release_sock(sk);
|
|
|
|
schedule();
|
|
|
|
lock_sock(sk);
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
__set_current_state(TASK_RUNNING);
|
2010-04-20 21:03:51 +08:00
|
|
|
remove_wait_queue(sk_sleep(sk), &wait);
|
2005-04-17 06:20:36 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
|
|
|
|
int addr_len, int flags)
|
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct x25_sock *x25 = x25_sk(sk);
|
|
|
|
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
|
|
|
|
struct x25_route *rt;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
|
|
|
|
sock->state = SS_CONNECTED;
|
|
|
|
goto out; /* Connect completed during a ERESTARTSYS event */
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = -ECONNREFUSED;
|
|
|
|
if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
|
|
|
|
sock->state = SS_UNCONNECTED;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = -EISCONN; /* No reconnect on a seqpacket socket */
|
|
|
|
if (sk->sk_state == TCP_ESTABLISHED)
|
|
|
|
goto out;
|
|
|
|
|
2020-01-09 14:31:14 +08:00
|
|
|
rc = -EALREADY; /* Do nothing if call is already in progress */
|
|
|
|
if (sk->sk_state == TCP_SYN_SENT)
|
|
|
|
goto out;
|
|
|
|
|
2007-02-09 22:25:27 +08:00
|
|
|
sk->sk_state = TCP_CLOSE;
|
2005-04-17 06:20:36 +08:00
|
|
|
sock->state = SS_UNCONNECTED;
|
|
|
|
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (addr_len != sizeof(struct sockaddr_x25) ||
|
2020-12-01 23:15:12 +08:00
|
|
|
addr->sx25_family != AF_X25 ||
|
|
|
|
strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -ENETUNREACH;
|
|
|
|
rt = x25_get_route(&addr->sx25_addr);
|
|
|
|
if (!rt)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
x25->neighbour = x25_get_neigh(rt->dev);
|
|
|
|
if (!x25->neighbour)
|
|
|
|
goto out_put_route;
|
|
|
|
|
|
|
|
x25_limit_facilities(&x25->facilities, x25->neighbour);
|
|
|
|
|
|
|
|
x25->lci = x25_new_lci(x25->neighbour);
|
|
|
|
if (!x25->lci)
|
|
|
|
goto out_put_neigh;
|
|
|
|
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
|
|
|
|
goto out_put_neigh;
|
|
|
|
|
|
|
|
if (!strcmp(x25->source_addr.x25_addr, null_x25_address.x25_addr))
|
|
|
|
memset(&x25->source_addr, '\0', X25_ADDR_LEN);
|
|
|
|
|
|
|
|
x25->dest_addr = addr->sx25_addr;
|
|
|
|
|
|
|
|
/* Move to connecting socket, start sending Connect Requests */
|
|
|
|
sock->state = SS_CONNECTING;
|
|
|
|
sk->sk_state = TCP_SYN_SENT;
|
|
|
|
|
|
|
|
x25->state = X25_STATE_1;
|
|
|
|
|
|
|
|
x25_write_internal(sk, X25_CALL_REQUEST);
|
|
|
|
|
|
|
|
x25_start_heartbeat(sk);
|
|
|
|
x25_start_t21timer(sk);
|
|
|
|
|
|
|
|
/* Now the loop */
|
|
|
|
rc = -EINPROGRESS;
|
|
|
|
if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
|
2020-01-09 14:31:14 +08:00
|
|
|
goto out;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
rc = x25_wait_for_connection_establishment(sk);
|
|
|
|
if (rc)
|
|
|
|
goto out_put_neigh;
|
|
|
|
|
|
|
|
sock->state = SS_CONNECTED;
|
|
|
|
rc = 0;
|
|
|
|
out_put_neigh:
|
2020-11-09 14:54:49 +08:00
|
|
|
if (rc && x25->neighbour) {
|
2019-03-11 00:07:14 +08:00
|
|
|
read_lock_bh(&x25_list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
x25_neigh_put(x25->neighbour);
|
2019-03-11 00:07:14 +08:00
|
|
|
x25->neighbour = NULL;
|
|
|
|
read_unlock_bh(&x25_list_lock);
|
2019-03-12 04:48:44 +08:00
|
|
|
x25->state = X25_STATE_0;
|
2019-03-11 00:07:14 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
out_put_route:
|
|
|
|
x25_route_put(rt);
|
|
|
|
out:
|
|
|
|
release_sock(sk);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2006-03-22 16:00:40 +08:00
|
|
|
static int x25_wait_for_data(struct sock *sk, long timeout)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
DECLARE_WAITQUEUE(wait, current);
|
|
|
|
int rc = 0;
|
|
|
|
|
2010-04-20 21:03:51 +08:00
|
|
|
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
2005-04-17 06:20:36 +08:00
|
|
|
for (;;) {
|
|
|
|
__set_current_state(TASK_INTERRUPTIBLE);
|
|
|
|
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
|
|
|
break;
|
|
|
|
rc = -ERESTARTSYS;
|
|
|
|
if (signal_pending(current))
|
|
|
|
break;
|
|
|
|
rc = -EAGAIN;
|
|
|
|
if (!timeout)
|
|
|
|
break;
|
|
|
|
rc = 0;
|
|
|
|
if (skb_queue_empty(&sk->sk_receive_queue)) {
|
|
|
|
release_sock(sk);
|
|
|
|
timeout = schedule_timeout(timeout);
|
|
|
|
lock_sock(sk);
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
__set_current_state(TASK_RUNNING);
|
2010-04-20 21:03:51 +08:00
|
|
|
remove_wait_queue(sk_sleep(sk), &wait);
|
2005-04-17 06:20:36 +08:00
|
|
|
return rc;
|
|
|
|
}
|
2007-02-09 22:25:27 +08:00
|
|
|
|
2017-03-09 16:09:05 +08:00
|
|
|
static int x25_accept(struct socket *sock, struct socket *newsock, int flags,
|
|
|
|
bool kern)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct sock *newsk;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc = -EINVAL;
|
|
|
|
|
2010-09-15 11:38:54 +08:00
|
|
|
if (!sk)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -EOPNOTSUPP;
|
|
|
|
if (sk->sk_type != SOCK_SEQPACKET)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
lock_sock(sk);
|
2010-09-15 11:38:54 +08:00
|
|
|
rc = -EINVAL;
|
|
|
|
if (sk->sk_state != TCP_LISTEN)
|
|
|
|
goto out2;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
rc = x25_wait_for_data(sk, sk->sk_rcvtimeo);
|
|
|
|
if (rc)
|
|
|
|
goto out2;
|
|
|
|
skb = skb_dequeue(&sk->sk_receive_queue);
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (!skb->sk)
|
|
|
|
goto out2;
|
|
|
|
newsk = skb->sk;
|
2008-06-17 17:44:35 +08:00
|
|
|
sock_graft(newsk, newsock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* Now attach up the new socket */
|
|
|
|
skb->sk = NULL;
|
|
|
|
kfree_skb(skb);
|
2019-11-06 06:11:52 +08:00
|
|
|
sk_acceptq_removed(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
newsock->state = SS_CONNECTED;
|
|
|
|
rc = 0;
|
|
|
|
out2:
|
|
|
|
release_sock(sk);
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
|
2018-02-13 03:00:20 +08:00
|
|
|
int peer)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct x25_sock *x25 = x25_sk(sk);
|
2009-11-05 12:37:29 +08:00
|
|
|
int rc = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (peer) {
|
2009-11-05 12:37:29 +08:00
|
|
|
if (sk->sk_state != TCP_ESTABLISHED) {
|
|
|
|
rc = -ENOTCONN;
|
|
|
|
goto out;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
sx25->sx25_addr = x25->dest_addr;
|
|
|
|
} else
|
|
|
|
sx25->sx25_addr = x25->source_addr;
|
|
|
|
|
|
|
|
sx25->sx25_family = AF_X25;
|
2018-02-13 03:00:20 +08:00
|
|
|
rc = sizeof(*sx25);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-11-05 12:37:29 +08:00
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
|
|
|
|
unsigned int lci)
|
|
|
|
{
|
|
|
|
struct sock *sk;
|
|
|
|
struct sock *make;
|
|
|
|
struct x25_sock *makex25;
|
|
|
|
struct x25_address source_addr, dest_addr;
|
|
|
|
struct x25_facilities facilities;
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
struct x25_dte_facilities dte_facilities;
|
2007-02-09 05:34:02 +08:00
|
|
|
int len, addr_len, rc;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove the LCI and frame type.
|
|
|
|
*/
|
|
|
|
skb_pull(skb, X25_STD_MIN_LEN);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Extract the X.25 addresses and convert them to ASCII strings,
|
|
|
|
* and remove them.
|
2010-04-08 12:29:25 +08:00
|
|
|
*
|
|
|
|
* Address block is mandatory in call request packets
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2010-04-08 12:29:25 +08:00
|
|
|
addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr);
|
|
|
|
if (addr_len <= 0)
|
|
|
|
goto out_clear_request;
|
2007-02-09 05:34:02 +08:00
|
|
|
skb_pull(skb, addr_len);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the length of the facilities, skip past them for the moment
|
|
|
|
* get the call user data because this is needed to determine
|
|
|
|
* the correct listener
|
2010-04-08 12:29:25 +08:00
|
|
|
*
|
|
|
|
* Facilities length is mandatory in call request packets
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2011-10-15 02:45:04 +08:00
|
|
|
if (!pskb_may_pull(skb, 1))
|
2010-04-08 12:29:25 +08:00
|
|
|
goto out_clear_request;
|
2005-04-17 06:20:36 +08:00
|
|
|
len = skb->data[0] + 1;
|
2011-10-15 02:45:04 +08:00
|
|
|
if (!pskb_may_pull(skb, len))
|
2010-04-08 12:29:25 +08:00
|
|
|
goto out_clear_request;
|
2005-04-17 06:20:36 +08:00
|
|
|
skb_pull(skb,len);
|
|
|
|
|
2011-10-15 02:45:03 +08:00
|
|
|
/*
|
|
|
|
* Ensure that the amount of call user data is valid.
|
|
|
|
*/
|
|
|
|
if (skb->len > X25_MAX_CUD_LEN)
|
|
|
|
goto out_clear_request;
|
|
|
|
|
2011-10-15 02:45:04 +08:00
|
|
|
/*
|
|
|
|
* Get all the call user data so it can be used in
|
|
|
|
* x25_find_listener and skb_copy_from_linear_data up ahead.
|
|
|
|
*/
|
|
|
|
if (!pskb_may_pull(skb, skb->len))
|
|
|
|
goto out_clear_request;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Find a listener for the particular address/cud pair.
|
|
|
|
*/
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
sk = x25_find_listener(&source_addr,skb);
|
|
|
|
skb_push(skb,len);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-02-09 05:34:02 +08:00
|
|
|
if (sk != NULL && sk_acceptq_is_full(sk)) {
|
|
|
|
goto out_sock_put;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2007-02-09 05:34:02 +08:00
|
|
|
* We dont have any listeners for this incoming call.
|
|
|
|
* Try forwarding it.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2007-02-09 05:34:02 +08:00
|
|
|
if (sk == NULL) {
|
|
|
|
skb_push(skb, addr_len + X25_STD_MIN_LEN);
|
2007-02-09 05:34:36 +08:00
|
|
|
if (sysctl_x25_forward &&
|
|
|
|
x25_forward_call(&dest_addr, nb, skb, lci) > 0)
|
2007-02-09 05:34:02 +08:00
|
|
|
{
|
|
|
|
/* Call was forwarded, dont process it any more */
|
|
|
|
kfree_skb(skb);
|
|
|
|
rc = 1;
|
|
|
|
goto out;
|
|
|
|
} else {
|
|
|
|
/* No listeners, can't forward, clear the call */
|
|
|
|
goto out_clear_request;
|
|
|
|
}
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to reach a compromise on the requested facilities.
|
|
|
|
*/
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities);
|
|
|
|
if (len == -1)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out_sock_put;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* current neighbour/link might impose additional limits
|
2021-03-27 07:12:36 +08:00
|
|
|
* on certain facilities
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
x25_limit_facilities(&facilities, nb);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to create a new socket.
|
|
|
|
*/
|
|
|
|
make = x25_make_new(sk);
|
|
|
|
if (!make)
|
|
|
|
goto out_sock_put;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove the facilities
|
|
|
|
*/
|
|
|
|
skb_pull(skb, len);
|
|
|
|
|
|
|
|
skb->sk = make;
|
|
|
|
make->sk_state = TCP_ESTABLISHED;
|
|
|
|
|
|
|
|
makex25 = x25_sk(make);
|
|
|
|
makex25->lci = lci;
|
|
|
|
makex25->dest_addr = dest_addr;
|
|
|
|
makex25->source_addr = source_addr;
|
2020-11-12 18:35:06 +08:00
|
|
|
x25_neigh_hold(nb);
|
2005-04-17 06:20:36 +08:00
|
|
|
makex25->neighbour = nb;
|
|
|
|
makex25->facilities = facilities;
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
makex25->dte_facilities= dte_facilities;
|
2005-04-17 06:20:36 +08:00
|
|
|
makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
/* ensure no reverse facil on accept */
|
|
|
|
makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
/* ensure no calling address extension on accept */
|
|
|
|
makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE;
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-05-17 07:00:27 +08:00
|
|
|
/* Normally all calls are accepted immediately */
|
|
|
|
if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) {
|
[X25]: Fast select with no restriction on response
This patch is a follow up to patch 1 regarding "Selective Sub Address
matching with call user data". It allows use of the Fast-Select-Acceptance
optional user facility for X.25.
This patch just implements fast select with no restriction on response
(NRR). What this means (according to ITU-T Recomendation 10/96 section
6.16) is that if in an incoming call packet, the relevant facility bits are
set for fast-select-NRR, then the called DTE can issue a direct response to
the incoming packet using a call-accepted packet that contains
call-user-data. This patch allows such a response.
The called DTE can also respond with a clear-request packet that contains
call-user-data. However, this feature is currently not implemented by the
patch.
How is Fast Select Acceptance used?
By default, the system does not allow fast select acceptance (as before).
To enable a response to fast select acceptance,
After a listen socket in created and bound as follows
socket(AF_X25, SOCK_SEQPACKET, 0);
bind(call_soc, (struct sockaddr *)&locl_addr, sizeof(locl_addr));
but before a listen system call is made, the following ioctl should be used.
ioctl(call_soc,SIOCX25CALLACCPTAPPRV);
Now the listen system call can be made
listen(call_soc, 4);
After this, an incoming-call packet will be accepted, but no call-accepted
packet will be sent back until the following system call is made on the socket
that accepts the call
ioctl(vc_soc,SIOCX25SENDCALLACCPT);
The network (or cisco xot router used for testing here) will allow the
application server's call-user-data in the call-accepted packet,
provided the call-request was made with Fast-select NRR.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:16:17 +08:00
|
|
|
x25_write_internal(make, X25_CALL_ACCEPTED);
|
|
|
|
makex25->state = X25_STATE_3;
|
2019-12-09 15:21:34 +08:00
|
|
|
} else {
|
|
|
|
makex25->state = X25_STATE_5;
|
[X25]: Fast select with no restriction on response
This patch is a follow up to patch 1 regarding "Selective Sub Address
matching with call user data". It allows use of the Fast-Select-Acceptance
optional user facility for X.25.
This patch just implements fast select with no restriction on response
(NRR). What this means (according to ITU-T Recomendation 10/96 section
6.16) is that if in an incoming call packet, the relevant facility bits are
set for fast-select-NRR, then the called DTE can issue a direct response to
the incoming packet using a call-accepted packet that contains
call-user-data. This patch allows such a response.
The called DTE can also respond with a clear-request packet that contains
call-user-data. However, this feature is currently not implemented by the
patch.
How is Fast Select Acceptance used?
By default, the system does not allow fast select acceptance (as before).
To enable a response to fast select acceptance,
After a listen socket in created and bound as follows
socket(AF_X25, SOCK_SEQPACKET, 0);
bind(call_soc, (struct sockaddr *)&locl_addr, sizeof(locl_addr));
but before a listen system call is made, the following ioctl should be used.
ioctl(call_soc,SIOCX25CALLACCPTAPPRV);
Now the listen system call can be made
listen(call_soc, 4);
After this, an incoming-call packet will be accepted, but no call-accepted
packet will be sent back until the following system call is made on the socket
that accepts the call
ioctl(vc_soc,SIOCX25SENDCALLACCPT);
The network (or cisco xot router used for testing here) will allow the
application server's call-user-data in the call-accepted packet,
provided the call-request was made with Fast-select NRR.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:16:17 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
/*
|
|
|
|
* Incoming Call User Data.
|
|
|
|
*/
|
2009-03-14 07:04:12 +08:00
|
|
|
skb_copy_from_linear_data(skb, makex25->calluserdata.cuddata, skb->len);
|
|
|
|
makex25->calluserdata.cudlength = skb->len;
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
|
2019-11-06 06:11:52 +08:00
|
|
|
sk_acceptq_added(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
x25_insert_socket(make);
|
|
|
|
|
|
|
|
skb_queue_head(&sk->sk_receive_queue, skb);
|
|
|
|
|
|
|
|
x25_start_heartbeat(make);
|
|
|
|
|
|
|
|
if (!sock_flag(sk, SOCK_DEAD))
|
2014-04-12 04:15:36 +08:00
|
|
|
sk->sk_data_ready(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
rc = 1;
|
|
|
|
sock_put(sk);
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
out_sock_put:
|
|
|
|
sock_put(sk);
|
|
|
|
out_clear_request:
|
|
|
|
rc = 0;
|
|
|
|
x25_transmit_clear_request(nb, lci, 0x01);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2015-03-02 15:37:48 +08:00
|
|
|
static int x25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct x25_sock *x25 = x25_sk(sk);
|
2014-01-18 05:53:15 +08:00
|
|
|
DECLARE_SOCKADDR(struct sockaddr_x25 *, usx25, msg->msg_name);
|
2005-04-17 06:20:36 +08:00
|
|
|
struct sockaddr_x25 sx25;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
unsigned char *asmptr;
|
|
|
|
int noblock = msg->msg_flags & MSG_DONTWAIT;
|
|
|
|
size_t size;
|
|
|
|
int qbit = 0, rc = -EINVAL;
|
|
|
|
|
2011-01-23 06:44:59 +08:00
|
|
|
lock_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* we currently don't support segmented records at the user interface */
|
|
|
|
if (!(msg->msg_flags & (MSG_EOR|MSG_OOB)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -EADDRNOTAVAIL;
|
|
|
|
if (sock_flag(sk, SOCK_ZAPPED))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -EPIPE;
|
|
|
|
if (sk->sk_shutdown & SEND_SHUTDOWN) {
|
|
|
|
send_sig(SIGPIPE, current, 0);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = -ENETUNREACH;
|
|
|
|
if (!x25->neighbour)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (usx25) {
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (msg->msg_namelen < sizeof(sx25))
|
|
|
|
goto out;
|
|
|
|
memcpy(&sx25, usx25, sizeof(sx25));
|
|
|
|
rc = -EISCONN;
|
|
|
|
if (strcmp(x25->dest_addr.x25_addr, sx25.sx25_addr.x25_addr))
|
|
|
|
goto out;
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (sx25.sx25_family != AF_X25)
|
|
|
|
goto out;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* FIXME 1003.1g - if the socket is like this because
|
|
|
|
* it has become closed (not started closed) we ought
|
|
|
|
* to SIGPIPE, EPIPE;
|
|
|
|
*/
|
|
|
|
rc = -ENOTCONN;
|
|
|
|
if (sk->sk_state != TCP_ESTABLISHED)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
sx25.sx25_family = AF_X25;
|
|
|
|
sx25.sx25_addr = x25->dest_addr;
|
|
|
|
}
|
|
|
|
|
2009-03-27 15:28:21 +08:00
|
|
|
/* Sanity check the packet size */
|
|
|
|
if (len > 65535) {
|
|
|
|
rc = -EMSGSIZE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");
|
|
|
|
|
|
|
|
/* Build a packet */
|
|
|
|
SOCK_DEBUG(sk, "x25_sendmsg: sendto: building packet.\n");
|
|
|
|
|
|
|
|
if ((msg->msg_flags & MSG_OOB) && len > 32)
|
|
|
|
len = 32;
|
|
|
|
|
|
|
|
size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN;
|
|
|
|
|
2011-01-23 06:44:59 +08:00
|
|
|
release_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
skb = sock_alloc_send_skb(sk, size, noblock, &rc);
|
2011-01-23 06:44:59 +08:00
|
|
|
lock_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!skb)
|
|
|
|
goto out;
|
|
|
|
X25_SKB_CB(skb)->flags = msg->msg_flags;
|
|
|
|
|
|
|
|
skb_reserve(skb, X25_MAX_L2_LEN + X25_EXT_MIN_LEN);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the data on the end
|
|
|
|
*/
|
|
|
|
SOCK_DEBUG(sk, "x25_sendmsg: Copying user data\n");
|
|
|
|
|
2007-03-15 08:04:34 +08:00
|
|
|
skb_reset_transport_header(skb);
|
|
|
|
skb_put(skb, len);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2014-04-07 09:25:44 +08:00
|
|
|
rc = memcpy_from_msg(skb_transport_header(skb), msg, len);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (rc)
|
|
|
|
goto out_kfree_skb;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the Q BIT Include socket option is in force, the first
|
|
|
|
* byte of the user data is the logical value of the Q Bit.
|
|
|
|
*/
|
2010-05-17 06:59:41 +08:00
|
|
|
if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
|
2011-10-15 02:45:04 +08:00
|
|
|
if (!pskb_may_pull(skb, 1))
|
|
|
|
goto out_kfree_skb;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
qbit = skb->data[0];
|
|
|
|
skb_pull(skb, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Push down the X.25 header
|
|
|
|
*/
|
|
|
|
SOCK_DEBUG(sk, "x25_sendmsg: Building X.25 Header.\n");
|
|
|
|
|
|
|
|
if (msg->msg_flags & MSG_OOB) {
|
|
|
|
if (x25->neighbour->extended) {
|
|
|
|
asmptr = skb_push(skb, X25_STD_MIN_LEN);
|
|
|
|
*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;
|
|
|
|
*asmptr++ = (x25->lci >> 0) & 0xFF;
|
|
|
|
*asmptr++ = X25_INTERRUPT;
|
|
|
|
} else {
|
|
|
|
asmptr = skb_push(skb, X25_STD_MIN_LEN);
|
|
|
|
*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;
|
|
|
|
*asmptr++ = (x25->lci >> 0) & 0xFF;
|
|
|
|
*asmptr++ = X25_INTERRUPT;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (x25->neighbour->extended) {
|
|
|
|
/* Build an Extended X.25 header */
|
|
|
|
asmptr = skb_push(skb, X25_EXT_MIN_LEN);
|
|
|
|
*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;
|
|
|
|
*asmptr++ = (x25->lci >> 0) & 0xFF;
|
|
|
|
*asmptr++ = X25_DATA;
|
|
|
|
*asmptr++ = X25_DATA;
|
|
|
|
} else {
|
|
|
|
/* Build an Standard X.25 header */
|
|
|
|
asmptr = skb_push(skb, X25_STD_MIN_LEN);
|
|
|
|
*asmptr++ = ((x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;
|
|
|
|
*asmptr++ = (x25->lci >> 0) & 0xFF;
|
|
|
|
*asmptr++ = X25_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qbit)
|
|
|
|
skb->data[0] |= X25_Q_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
SOCK_DEBUG(sk, "x25_sendmsg: Built header.\n");
|
|
|
|
SOCK_DEBUG(sk, "x25_sendmsg: Transmitting buffer\n");
|
|
|
|
|
|
|
|
rc = -ENOTCONN;
|
|
|
|
if (sk->sk_state != TCP_ESTABLISHED)
|
|
|
|
goto out_kfree_skb;
|
|
|
|
|
|
|
|
if (msg->msg_flags & MSG_OOB)
|
|
|
|
skb_queue_tail(&x25->interrupt_out_queue, skb);
|
|
|
|
else {
|
2009-03-14 07:04:12 +08:00
|
|
|
rc = x25_output(sk, skb);
|
|
|
|
len = rc;
|
|
|
|
if (rc < 0)
|
2005-04-17 06:20:36 +08:00
|
|
|
kfree_skb(skb);
|
2010-05-17 06:59:41 +08:00
|
|
|
else if (test_bit(X25_Q_BIT_FLAG, &x25->flags))
|
2005-04-17 06:20:36 +08:00
|
|
|
len++;
|
|
|
|
}
|
|
|
|
|
|
|
|
x25_kick(sk);
|
|
|
|
rc = len;
|
|
|
|
out:
|
2011-01-23 06:44:59 +08:00
|
|
|
release_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
return rc;
|
|
|
|
out_kfree_skb:
|
|
|
|
kfree_skb(skb);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-02 15:37:48 +08:00
|
|
|
static int x25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
|
2005-04-17 06:20:36 +08:00
|
|
|
int flags)
|
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct x25_sock *x25 = x25_sk(sk);
|
2014-01-18 05:53:15 +08:00
|
|
|
DECLARE_SOCKADDR(struct sockaddr_x25 *, sx25, msg->msg_name);
|
2005-04-17 06:20:36 +08:00
|
|
|
size_t copied;
|
2011-11-02 00:26:44 +08:00
|
|
|
int qbit, header_len;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct sk_buff *skb;
|
|
|
|
unsigned char *asmptr;
|
|
|
|
int rc = -ENOTCONN;
|
|
|
|
|
2011-01-23 06:44:59 +08:00
|
|
|
lock_sock(sk);
|
2011-11-02 00:26:44 +08:00
|
|
|
|
|
|
|
if (x25->neighbour == NULL)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
header_len = x25->neighbour->extended ?
|
|
|
|
X25_EXT_MIN_LEN : X25_STD_MIN_LEN;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* This works for seqpacket too. The receiver has ordered the queue for
|
|
|
|
* us! We do one quick check first though
|
|
|
|
*/
|
|
|
|
if (sk->sk_state != TCP_ESTABLISHED)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (flags & MSG_OOB) {
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (sock_flag(sk, SOCK_URGINLINE) ||
|
|
|
|
!skb_peek(&x25->interrupt_in_queue))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
skb = skb_dequeue(&x25->interrupt_in_queue);
|
|
|
|
|
2011-10-15 02:45:04 +08:00
|
|
|
if (!pskb_may_pull(skb, X25_STD_MIN_LEN))
|
|
|
|
goto out_free_dgram;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
skb_pull(skb, X25_STD_MIN_LEN);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No Q bit information on Interrupt data.
|
|
|
|
*/
|
2010-05-17 06:59:41 +08:00
|
|
|
if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
asmptr = skb_push(skb, 1);
|
|
|
|
*asmptr = 0x00;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg->msg_flags |= MSG_OOB;
|
|
|
|
} else {
|
|
|
|
/* Now we can treat all alike */
|
2011-01-23 06:44:59 +08:00
|
|
|
release_sock(sk);
|
2022-04-05 00:30:22 +08:00
|
|
|
skb = skb_recv_datagram(sk, flags, &rc);
|
2011-01-23 06:44:59 +08:00
|
|
|
lock_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!skb)
|
|
|
|
goto out;
|
|
|
|
|
2011-10-15 02:45:04 +08:00
|
|
|
if (!pskb_may_pull(skb, header_len))
|
|
|
|
goto out_free_dgram;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT;
|
|
|
|
|
2011-10-15 02:45:04 +08:00
|
|
|
skb_pull(skb, header_len);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-05-17 06:59:41 +08:00
|
|
|
if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
asmptr = skb_push(skb, 1);
|
|
|
|
*asmptr = qbit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-14 00:06:52 +08:00
|
|
|
skb_reset_transport_header(skb);
|
2005-04-17 06:20:36 +08:00
|
|
|
copied = skb->len;
|
|
|
|
|
|
|
|
if (copied > size) {
|
|
|
|
copied = size;
|
|
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
|
|
}
|
|
|
|
|
2007-02-09 22:25:27 +08:00
|
|
|
/* Currently, each datagram always contains a complete record */
|
2005-04-17 06:20:36 +08:00
|
|
|
msg->msg_flags |= MSG_EOR;
|
|
|
|
|
2014-11-06 05:46:40 +08:00
|
|
|
rc = skb_copy_datagram_msg(skb, 0, msg, copied);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (rc)
|
|
|
|
goto out_free_dgram;
|
|
|
|
|
|
|
|
if (sx25) {
|
|
|
|
sx25->sx25_family = AF_X25;
|
|
|
|
sx25->sx25_addr = x25->dest_addr;
|
2013-11-21 10:14:22 +08:00
|
|
|
msg->msg_namelen = sizeof(*sx25);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
x25_check_rbuf(sk);
|
|
|
|
rc = copied;
|
|
|
|
out_free_dgram:
|
|
|
|
skb_free_datagram(sk, skb);
|
|
|
|
out:
|
2011-01-23 06:44:59 +08:00
|
|
|
release_sock(sk);
|
2005-04-17 06:20:36 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|
|
|
{
|
|
|
|
struct sock *sk = sock->sk;
|
|
|
|
struct x25_sock *x25 = x25_sk(sk);
|
|
|
|
void __user *argp = (void __user *)arg;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
switch (cmd) {
|
2011-07-01 17:43:13 +08:00
|
|
|
case TIOCOUTQ: {
|
|
|
|
int amount;
|
|
|
|
|
|
|
|
amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
|
|
|
|
if (amount < 0)
|
|
|
|
amount = 0;
|
|
|
|
rc = put_user(amount, (unsigned int __user *)argp);
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case TIOCINQ: {
|
|
|
|
struct sk_buff *skb;
|
|
|
|
int amount = 0;
|
|
|
|
/*
|
|
|
|
* These two are safe on a single CPU system as
|
|
|
|
* only user tasks fiddle here
|
|
|
|
*/
|
|
|
|
lock_sock(sk);
|
|
|
|
if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
|
|
|
|
amount = skb->len;
|
|
|
|
release_sock(sk);
|
|
|
|
rc = put_user(amount, (unsigned int __user *)argp);
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCGIFADDR:
|
|
|
|
case SIOCSIFADDR:
|
|
|
|
case SIOCGIFDSTADDR:
|
|
|
|
case SIOCSIFDSTADDR:
|
|
|
|
case SIOCGIFBRDADDR:
|
|
|
|
case SIOCSIFBRDADDR:
|
|
|
|
case SIOCGIFNETMASK:
|
|
|
|
case SIOCSIFNETMASK:
|
|
|
|
case SIOCGIFMETRIC:
|
|
|
|
case SIOCSIFMETRIC:
|
|
|
|
rc = -EINVAL;
|
|
|
|
break;
|
|
|
|
case SIOCADDRT:
|
|
|
|
case SIOCDELRT:
|
|
|
|
rc = -EPERM;
|
|
|
|
if (!capable(CAP_NET_ADMIN))
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
2011-07-01 17:43:13 +08:00
|
|
|
rc = x25_route_ioctl(cmd, argp);
|
|
|
|
break;
|
|
|
|
case SIOCX25GSUBSCRIP:
|
|
|
|
rc = x25_subscr_ioctl(cmd, argp);
|
|
|
|
break;
|
|
|
|
case SIOCX25SSUBSCRIP:
|
|
|
|
rc = -EPERM;
|
|
|
|
if (!capable(CAP_NET_ADMIN))
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
2011-07-01 17:43:13 +08:00
|
|
|
rc = x25_subscr_ioctl(cmd, argp);
|
|
|
|
break;
|
|
|
|
case SIOCX25GFACILITIES: {
|
|
|
|
lock_sock(sk);
|
|
|
|
rc = copy_to_user(argp, &x25->facilities,
|
|
|
|
sizeof(x25->facilities))
|
|
|
|
? -EFAULT : 0;
|
|
|
|
release_sock(sk);
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25SFACILITIES: {
|
|
|
|
struct x25_facilities facilities;
|
|
|
|
rc = -EFAULT;
|
|
|
|
if (copy_from_user(&facilities, argp, sizeof(facilities)))
|
|
|
|
break;
|
|
|
|
rc = -EINVAL;
|
|
|
|
lock_sock(sk);
|
|
|
|
if (sk->sk_state != TCP_LISTEN &&
|
|
|
|
sk->sk_state != TCP_CLOSE)
|
|
|
|
goto out_fac_release;
|
|
|
|
if (facilities.pacsize_in < X25_PS16 ||
|
|
|
|
facilities.pacsize_in > X25_PS4096)
|
|
|
|
goto out_fac_release;
|
|
|
|
if (facilities.pacsize_out < X25_PS16 ||
|
|
|
|
facilities.pacsize_out > X25_PS4096)
|
|
|
|
goto out_fac_release;
|
|
|
|
if (facilities.winsize_in < 1 ||
|
|
|
|
facilities.winsize_in > 127)
|
|
|
|
goto out_fac_release;
|
|
|
|
if (facilities.throughput) {
|
|
|
|
int out = facilities.throughput & 0xf0;
|
|
|
|
int in = facilities.throughput & 0x0f;
|
|
|
|
if (!out)
|
|
|
|
facilities.throughput |=
|
|
|
|
X25_DEFAULT_THROUGHPUT << 4;
|
|
|
|
else if (out < 0x30 || out > 0xD0)
|
2010-11-25 10:18:35 +08:00
|
|
|
goto out_fac_release;
|
2011-07-01 17:43:13 +08:00
|
|
|
if (!in)
|
|
|
|
facilities.throughput |=
|
|
|
|
X25_DEFAULT_THROUGHPUT;
|
|
|
|
else if (in < 0x03 || in > 0x0D)
|
2010-11-25 10:18:35 +08:00
|
|
|
goto out_fac_release;
|
2007-02-09 22:25:27 +08:00
|
|
|
}
|
2011-07-01 17:43:13 +08:00
|
|
|
if (facilities.reverse &&
|
|
|
|
(facilities.reverse & 0x81) != 0x81)
|
|
|
|
goto out_fac_release;
|
|
|
|
x25->facilities = facilities;
|
|
|
|
rc = 0;
|
|
|
|
out_fac_release:
|
|
|
|
release_sock(sk);
|
|
|
|
break;
|
|
|
|
}
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25GDTEFACILITIES: {
|
|
|
|
lock_sock(sk);
|
|
|
|
rc = copy_to_user(argp, &x25->dte_facilities,
|
|
|
|
sizeof(x25->dte_facilities));
|
|
|
|
release_sock(sk);
|
|
|
|
if (rc)
|
2007-02-09 22:25:27 +08:00
|
|
|
rc = -EFAULT;
|
2011-07-01 17:43:13 +08:00
|
|
|
break;
|
|
|
|
}
|
[X25]: allow ITU-T DTE facilities for x25
Allows use of the optional user facility to insert ITU-T
(http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25
packets. This feature is optional; no facilities will be added if the ioctl
is not used, and call setup packet remains the same as before.
If the ioctls provided by the patch are used, then a facility marker will be
added to the x25 packet header so that the called dte address extension
facility can be differentiated from other types of facilities (as described in
the ITU-T X.25 recommendation) that are also allowed in the x25 packet header.
Facility markers are made up of two octets, and may be present in the x25
packet headers of call-request, incoming call, call accepted, clear request,
and clear indication packets. The first of the two octets represents the
facility code field and is set to zero by this patch. The second octet of the
marker represents the facility parameter field and is set to 0x0F because the
marker will be inserted before ITU-T type DTE facilities.
Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks
will support the facility markers with a facility parameter field set to all
ones or to 00001111", therefore this patch should work with all x.25 networks.
While there are many ITU-T DTE facilities, this patch implements only the
called and calling address extension, with placeholders in the
x25_dte_facilities structure for the rest of the facilities.
Testing:
This patch was tested using a cisco xot router connected on its serial ports
to an X.25 network, and on its lan ports to a host running an xotd daemon.
It is also possible to test this patch using an xotd daemon and an x25tap
patch, where the xotd daemons work back-to-back without actually using an x.25
network. See www.fyonne.net for details on how to do this.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Andrew Hendry <ahendry@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-03-22 16:01:31 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25SDTEFACILITIES: {
|
|
|
|
struct x25_dte_facilities dtefacs;
|
|
|
|
rc = -EFAULT;
|
|
|
|
if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
2011-07-01 17:43:13 +08:00
|
|
|
rc = -EINVAL;
|
|
|
|
lock_sock(sk);
|
|
|
|
if (sk->sk_state != TCP_LISTEN &&
|
|
|
|
sk->sk_state != TCP_CLOSE)
|
|
|
|
goto out_dtefac_release;
|
|
|
|
if (dtefacs.calling_len > X25_MAX_AE_LEN)
|
|
|
|
goto out_dtefac_release;
|
|
|
|
if (dtefacs.called_len > X25_MAX_AE_LEN)
|
|
|
|
goto out_dtefac_release;
|
|
|
|
x25->dte_facilities = dtefacs;
|
|
|
|
rc = 0;
|
|
|
|
out_dtefac_release:
|
|
|
|
release_sock(sk);
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25GCALLUSERDATA: {
|
|
|
|
lock_sock(sk);
|
|
|
|
rc = copy_to_user(argp, &x25->calluserdata,
|
|
|
|
sizeof(x25->calluserdata))
|
|
|
|
? -EFAULT : 0;
|
|
|
|
release_sock(sk);
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25SCALLUSERDATA: {
|
|
|
|
struct x25_calluserdata calluserdata;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
rc = -EFAULT;
|
|
|
|
if (copy_from_user(&calluserdata, argp, sizeof(calluserdata)))
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
2011-07-01 17:43:13 +08:00
|
|
|
rc = -EINVAL;
|
|
|
|
if (calluserdata.cudlength > X25_MAX_CUD_LEN)
|
|
|
|
break;
|
|
|
|
lock_sock(sk);
|
|
|
|
x25->calluserdata = calluserdata;
|
|
|
|
release_sock(sk);
|
|
|
|
rc = 0;
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25GCAUSEDIAG: {
|
|
|
|
lock_sock(sk);
|
|
|
|
rc = copy_to_user(argp, &x25->causediag, sizeof(x25->causediag))
|
|
|
|
? -EFAULT : 0;
|
|
|
|
release_sock(sk);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SIOCX25SCAUSEDIAG: {
|
|
|
|
struct x25_causediag causediag;
|
|
|
|
rc = -EFAULT;
|
|
|
|
if (copy_from_user(&causediag, argp, sizeof(causediag)))
|
2009-11-19 15:30:41 +08:00
|
|
|
break;
|
2011-07-01 17:43:13 +08:00
|
|
|
lock_sock(sk);
|
|
|
|
x25->causediag = causediag;
|
|
|
|
release_sock(sk);
|
|
|
|
rc = 0;
|
|
|
|
break;
|
2009-11-19 15:30:41 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
}
|
2009-11-19 15:30:41 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25SCUDMATCHLEN: {
|
|
|
|
struct x25_subaddr sub_addr;
|
|
|
|
rc = -EINVAL;
|
|
|
|
lock_sock(sk);
|
|
|
|
if(sk->sk_state != TCP_CLOSE)
|
|
|
|
goto out_cud_release;
|
|
|
|
rc = -EFAULT;
|
|
|
|
if (copy_from_user(&sub_addr, argp,
|
|
|
|
sizeof(sub_addr)))
|
|
|
|
goto out_cud_release;
|
|
|
|
rc = -EINVAL;
|
|
|
|
if (sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
|
|
|
|
goto out_cud_release;
|
|
|
|
x25->cudmatchlength = sub_addr.cudmatchlength;
|
|
|
|
rc = 0;
|
2010-11-25 10:18:45 +08:00
|
|
|
out_cud_release:
|
2011-07-01 17:43:13 +08:00
|
|
|
release_sock(sk);
|
|
|
|
break;
|
|
|
|
}
|
[X25]: Selective sub-address matching with call user data.
From: Shaun Pereira <spereira@tusc.com.au>
This is the first (independent of the second) patch of two that I am
working on with x25 on linux (tested with xot on a cisco router). Details
are as follows.
Current state of module:
A server using the current implementation (2.6.11.7) of the x25 module will
accept a call request/ incoming call packet at the listening x.25 address,
from all callers to that address, as long as NO call user data is present
in the packet header.
If the server needs to choose to accept a particular call request/ incoming
call packet arriving at its listening x25 address, then the kernel has to
allow a match of call user data present in the call request packet with its
own. This is required when multiple servers listen at the same x25 address
and device interface. The kernel currently matches ALL call user data, if
present.
Current Changes:
This patch is a follow up to the patch submitted previously by Andrew
Hendry, and allows the user to selectively control the number of octets of
call user data in the call request packet, that the kernel will match. By
default no call user data is matched, even if call user data is present.
To allow call user data matching, a cudmatchlength > 0 has to be passed
into the kernel after which the passed number of octets will be matched.
Otherwise the kernel behavior is exactly as the original implementation.
This patch also ensures that as is normally the case, no call user data
will be present in the Call accepted / call connected packet sent back to
the caller
Future Changes on next patch:
There are cases however when call user data may be present in the call
accepted packet. According to the X.25 recommendation (ITU-T 10/96)
section 5.2.3.2 call user data may be present in the call accepted packet
provided the fast select facility is used. My next patch will include this
fast select utility and the ability to send up to 128 octets call user data
in the call accepted packet provided the fast select facility is used. I
am currently testing this, again with xot on linux and cisco.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
(With a fix from Alexey Dobriyan <adobriyan@gmail.com>)
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:15:01 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25CALLACCPTAPPRV: {
|
|
|
|
rc = -EINVAL;
|
|
|
|
lock_sock(sk);
|
2013-06-29 00:13:52 +08:00
|
|
|
if (sk->sk_state == TCP_CLOSE) {
|
|
|
|
clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
|
|
|
|
rc = 0;
|
|
|
|
}
|
2011-07-01 17:43:13 +08:00
|
|
|
release_sock(sk);
|
|
|
|
break;
|
|
|
|
}
|
[X25]: Fast select with no restriction on response
This patch is a follow up to patch 1 regarding "Selective Sub Address
matching with call user data". It allows use of the Fast-Select-Acceptance
optional user facility for X.25.
This patch just implements fast select with no restriction on response
(NRR). What this means (according to ITU-T Recomendation 10/96 section
6.16) is that if in an incoming call packet, the relevant facility bits are
set for fast-select-NRR, then the called DTE can issue a direct response to
the incoming packet using a call-accepted packet that contains
call-user-data. This patch allows such a response.
The called DTE can also respond with a clear-request packet that contains
call-user-data. However, this feature is currently not implemented by the
patch.
How is Fast Select Acceptance used?
By default, the system does not allow fast select acceptance (as before).
To enable a response to fast select acceptance,
After a listen socket in created and bound as follows
socket(AF_X25, SOCK_SEQPACKET, 0);
bind(call_soc, (struct sockaddr *)&locl_addr, sizeof(locl_addr));
but before a listen system call is made, the following ioctl should be used.
ioctl(call_soc,SIOCX25CALLACCPTAPPRV);
Now the listen system call can be made
listen(call_soc, 4);
After this, an incoming-call packet will be accepted, but no call-accepted
packet will be sent back until the following system call is made on the socket
that accepts the call
ioctl(vc_soc,SIOCX25SENDCALLACCPT);
The network (or cisco xot router used for testing here) will allow the
application server's call-user-data in the call-accepted packet,
provided the call-request was made with Fast-select NRR.
Signed-off-by: Shaun Pereira <spereira@tusc.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-23 13:16:17 +08:00
|
|
|
|
2011-07-01 17:43:13 +08:00
|
|
|
case SIOCX25SENDCALLACCPT: {
|
|
|
|
rc = -EINVAL;
|
|
|
|
lock_sock(sk);
|
|
|
|
if (sk->sk_state != TCP_ESTABLISHED)
|
2013-06-29 00:13:52 +08:00
|
|
|
goto out_sendcallaccpt_release;
|
2011-07-01 17:43:13 +08:00
|
|
|
/* must call accptapprv above */
|
|
|
|
if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
|
2013-06-29 00:13:52 +08:00
|
|
|
goto out_sendcallaccpt_release;
|
2011-07-01 17:43:13 +08:00
|
|
|
x25_write_internal(sk, X25_CALL_ACCEPTED);
|
|
|
|
x25->state = X25_STATE_3;
|
|
|
|
rc = 0;
|
2013-06-29 00:13:52 +08:00
|
|
|
out_sendcallaccpt_release:
|
|
|
|
release_sock(sk);
|
2011-07-01 17:43:13 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
rc = -ENOIOCTLCMD;
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2009-10-05 13:58:39 +08:00
|
|
|
static const struct net_proto_family x25_family_ops = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.family = AF_X25,
|
|
|
|
.create = x25_create,
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
};
|
|
|
|
|
2006-03-22 16:00:12 +08:00
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
static int compat_x25_subscr_ioctl(unsigned int cmd,
|
|
|
|
struct compat_x25_subscrip_struct __user *x25_subscr32)
|
|
|
|
{
|
|
|
|
struct compat_x25_subscrip_struct x25_subscr;
|
|
|
|
struct x25_neigh *nb;
|
|
|
|
struct net_device *dev;
|
|
|
|
int rc = -EINVAL;
|
|
|
|
|
|
|
|
rc = -EFAULT;
|
|
|
|
if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
rc = -EINVAL;
|
|
|
|
dev = x25_dev_get(x25_subscr.device);
|
|
|
|
if (dev == NULL)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
nb = x25_get_neigh(dev);
|
|
|
|
if (nb == NULL)
|
|
|
|
goto out_dev_put;
|
|
|
|
|
|
|
|
dev_put(dev);
|
|
|
|
|
|
|
|
if (cmd == SIOCX25GSUBSCRIP) {
|
2010-11-25 10:18:15 +08:00
|
|
|
read_lock_bh(&x25_neigh_list_lock);
|
2006-03-22 16:00:12 +08:00
|
|
|
x25_subscr.extended = nb->extended;
|
|
|
|
x25_subscr.global_facil_mask = nb->global_facil_mask;
|
2010-11-25 10:18:15 +08:00
|
|
|
read_unlock_bh(&x25_neigh_list_lock);
|
2006-03-22 16:00:12 +08:00
|
|
|
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;
|
2010-11-25 10:18:15 +08:00
|
|
|
write_lock_bh(&x25_neigh_list_lock);
|
2006-03-22 16:00:12 +08:00
|
|
|
nb->extended = x25_subscr.extended;
|
|
|
|
nb->global_facil_mask = x25_subscr.global_facil_mask;
|
2010-11-25 10:18:15 +08:00
|
|
|
write_unlock_bh(&x25_neigh_list_lock);
|
2006-03-22 16:00:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
x25_neigh_put(nb);
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
out_dev_put:
|
|
|
|
dev_put(dev);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
void __user *argp = compat_ptr(arg);
|
|
|
|
int rc = -ENOIOCTLCMD;
|
|
|
|
|
|
|
|
switch(cmd) {
|
|
|
|
case TIOCOUTQ:
|
|
|
|
case TIOCINQ:
|
|
|
|
rc = x25_ioctl(sock, cmd, (unsigned long)argp);
|
|
|
|
break;
|
|
|
|
case SIOCGIFADDR:
|
|
|
|
case SIOCSIFADDR:
|
|
|
|
case SIOCGIFDSTADDR:
|
|
|
|
case SIOCSIFDSTADDR:
|
|
|
|
case SIOCGIFBRDADDR:
|
|
|
|
case SIOCSIFBRDADDR:
|
|
|
|
case SIOCGIFNETMASK:
|
|
|
|
case SIOCSIFNETMASK:
|
|
|
|
case SIOCGIFMETRIC:
|
|
|
|
case SIOCSIFMETRIC:
|
|
|
|
rc = -EINVAL;
|
|
|
|
break;
|
|
|
|
case SIOCADDRT:
|
|
|
|
case SIOCDELRT:
|
|
|
|
rc = -EPERM;
|
|
|
|
if (!capable(CAP_NET_ADMIN))
|
|
|
|
break;
|
|
|
|
rc = x25_route_ioctl(cmd, argp);
|
|
|
|
break;
|
|
|
|
case SIOCX25GSUBSCRIP:
|
|
|
|
rc = compat_x25_subscr_ioctl(cmd, argp);
|
|
|
|
break;
|
|
|
|
case SIOCX25SSUBSCRIP:
|
|
|
|
rc = -EPERM;
|
|
|
|
if (!capable(CAP_NET_ADMIN))
|
|
|
|
break;
|
|
|
|
rc = compat_x25_subscr_ioctl(cmd, argp);
|
|
|
|
break;
|
|
|
|
case SIOCX25GFACILITIES:
|
|
|
|
case SIOCX25SFACILITIES:
|
2006-03-22 16:02:00 +08:00
|
|
|
case SIOCX25GDTEFACILITIES:
|
|
|
|
case SIOCX25SDTEFACILITIES:
|
2006-03-22 16:00:12 +08:00
|
|
|
case SIOCX25GCALLUSERDATA:
|
|
|
|
case SIOCX25SCALLUSERDATA:
|
|
|
|
case SIOCX25GCAUSEDIAG:
|
2009-11-19 15:30:41 +08:00
|
|
|
case SIOCX25SCAUSEDIAG:
|
2006-03-22 16:00:12 +08:00
|
|
|
case SIOCX25SCUDMATCHLEN:
|
|
|
|
case SIOCX25CALLACCPTAPPRV:
|
|
|
|
case SIOCX25SENDCALLACCPT:
|
|
|
|
rc = x25_ioctl(sock, cmd, (unsigned long)argp);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rc = -ENOIOCTLCMD;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-11-05 12:37:29 +08:00
|
|
|
static const struct proto_ops x25_proto_ops = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.family = AF_X25,
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.release = x25_release,
|
|
|
|
.bind = x25_bind,
|
|
|
|
.connect = x25_connect,
|
|
|
|
.socketpair = sock_no_socketpair,
|
|
|
|
.accept = x25_accept,
|
|
|
|
.getname = x25_getname,
|
2018-06-29 00:43:44 +08:00
|
|
|
.poll = datagram_poll,
|
2005-04-17 06:20:36 +08:00
|
|
|
.ioctl = x25_ioctl,
|
2006-03-22 16:00:12 +08:00
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
.compat_ioctl = compat_x25_ioctl,
|
|
|
|
#endif
|
2019-04-18 04:51:48 +08:00
|
|
|
.gettstamp = sock_gettstamp,
|
2005-04-17 06:20:36 +08:00
|
|
|
.listen = x25_listen,
|
|
|
|
.shutdown = sock_no_shutdown,
|
|
|
|
.setsockopt = x25_setsockopt,
|
|
|
|
.getsockopt = x25_getsockopt,
|
|
|
|
.sendmsg = x25_sendmsg,
|
|
|
|
.recvmsg = x25_recvmsg,
|
|
|
|
.mmap = sock_no_mmap,
|
|
|
|
};
|
|
|
|
|
2009-03-09 16:18:29 +08:00
|
|
|
static struct packet_type x25_packet_type __read_mostly = {
|
2009-02-01 16:45:17 +08:00
|
|
|
.type = cpu_to_be16(ETH_P_X25),
|
2005-04-17 06:20:36 +08:00
|
|
|
.func = x25_lapb_receive_frame,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct notifier_block x25_dev_notifier = {
|
|
|
|
.notifier_call = x25_device_event,
|
|
|
|
};
|
|
|
|
|
|
|
|
void x25_kill_by_neigh(struct x25_neigh *nb)
|
|
|
|
{
|
|
|
|
struct sock *s;
|
|
|
|
|
|
|
|
write_lock_bh(&x25_list_lock);
|
|
|
|
|
2022-03-26 18:43:46 +08:00
|
|
|
sk_for_each(s, &x25_list) {
|
|
|
|
if (x25_sk(s)->neighbour == nb) {
|
|
|
|
write_unlock_bh(&x25_list_lock);
|
|
|
|
lock_sock(s);
|
2005-04-17 06:20:36 +08:00
|
|
|
x25_disconnect(s, ENETUNREACH, 0, 0);
|
2022-03-26 18:43:46 +08:00
|
|
|
release_sock(s);
|
|
|
|
write_lock_bh(&x25_list_lock);
|
|
|
|
}
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
write_unlock_bh(&x25_list_lock);
|
2007-02-09 05:34:02 +08:00
|
|
|
|
|
|
|
/* Remove any related forwards */
|
|
|
|
x25_clear_forward_by_dev(nb->dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int __init x25_init(void)
|
|
|
|
{
|
2017-05-17 12:05:07 +08:00
|
|
|
int rc;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-05-17 12:05:07 +08:00
|
|
|
rc = proto_register(&x25_proto, 0);
|
|
|
|
if (rc)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
2009-11-24 23:15:42 +08:00
|
|
|
rc = sock_register(&x25_family_ops);
|
2017-05-17 12:05:07 +08:00
|
|
|
if (rc)
|
2009-11-24 23:15:42 +08:00
|
|
|
goto out_proto;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
dev_add_pack(&x25_packet_type);
|
|
|
|
|
2009-11-24 23:15:42 +08:00
|
|
|
rc = register_netdevice_notifier(&x25_dev_notifier);
|
2017-05-17 12:05:07 +08:00
|
|
|
if (rc)
|
2009-11-24 23:15:42 +08:00
|
|
|
goto out_sock;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-05-17 12:05:07 +08:00
|
|
|
rc = x25_register_sysctl();
|
|
|
|
if (rc)
|
|
|
|
goto out_dev;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-11-24 23:15:42 +08:00
|
|
|
rc = x25_proc_init();
|
2017-05-17 12:05:07 +08:00
|
|
|
if (rc)
|
|
|
|
goto out_sysctl;
|
|
|
|
|
|
|
|
pr_info("Linux Version 0.2\n");
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
out:
|
|
|
|
return rc;
|
2017-05-17 12:05:07 +08:00
|
|
|
out_sysctl:
|
|
|
|
x25_unregister_sysctl();
|
2009-11-24 23:15:42 +08:00
|
|
|
out_dev:
|
|
|
|
unregister_netdevice_notifier(&x25_dev_notifier);
|
|
|
|
out_sock:
|
2017-05-17 12:05:07 +08:00
|
|
|
dev_remove_pack(&x25_packet_type);
|
2009-11-24 23:15:42 +08:00
|
|
|
sock_unregister(AF_X25);
|
|
|
|
out_proto:
|
|
|
|
proto_unregister(&x25_proto);
|
|
|
|
goto out;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
module_init(x25_init);
|
|
|
|
|
|
|
|
static void __exit x25_exit(void)
|
|
|
|
{
|
|
|
|
x25_proc_exit();
|
|
|
|
x25_link_free();
|
|
|
|
x25_route_free();
|
|
|
|
|
|
|
|
x25_unregister_sysctl();
|
|
|
|
|
|
|
|
unregister_netdevice_notifier(&x25_dev_notifier);
|
|
|
|
|
|
|
|
dev_remove_pack(&x25_packet_type);
|
|
|
|
|
|
|
|
sock_unregister(AF_X25);
|
|
|
|
proto_unregister(&x25_proto);
|
|
|
|
}
|
|
|
|
module_exit(x25_exit);
|
|
|
|
|
|
|
|
MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
|
|
|
|
MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol");
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_ALIAS_NETPROTO(PF_X25);
|