summaryrefslogtreecommitdiffstats
path: root/net/x25
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-11-28 03:58:46 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-11-28 03:58:46 +0000
commitb63ad0882a16a5d28003e57f2b0b81dee3fb322b (patch)
tree0a343ce219e2b8b38a5d702d66032c57b83d9720 /net/x25
parenta9d7bff9a84dba79609a0002e5321b74c4d64c64 (diff)
Merge with 2.4.0-test11.
Diffstat (limited to 'net/x25')
-rw-r--r--net/x25/af_x25.c41
-rw-r--r--net/x25/x25_dev.c11
-rw-r--r--net/x25/x25_in.c17
-rw-r--r--net/x25/x25_out.c30
4 files changed, 81 insertions, 18 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 320722c40..0242b12e5 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -16,13 +16,16 @@
* X.25 001 Jonathan Naylor Started coding.
* X.25 002 Jonathan Naylor Centralised disconnect handling.
* New timer architecture.
- * 2000-11-03 Henner Eisen MSG_EOR handling more POSIX compliant.
- * 2000-22-03 Daniela Squassoni Allowed disabling/enabling of
+ * 2000-03-11 Henner Eisen MSG_EOR handling more POSIX compliant.
+ * 2000-03-22 Daniela Squassoni Allowed disabling/enabling of
* facilities negotiation and increased
* the throughput upper limit.
- * 2000-27-08 Arnaldo C. Melo s/suser/capable/ + micro cleanups
- * 2000-04-09 Henner Eisen Set sock->state in x25_accept().
+ * 2000-08-27 Arnaldo C. Melo s/suser/capable/ + micro cleanups
+ * 2000-09-04 Henner Eisen Set sock->state in x25_accept().
* 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
*/
#include <linux/config.h>
@@ -191,6 +194,7 @@ static void x25_kill_by_device(struct net_device *dev)
static int x25_device_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct net_device *dev = (struct net_device *)ptr;
+ struct x25_neigh *neigh;
if (dev->type == ARPHRD_X25
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
@@ -201,6 +205,10 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, vo
case NETDEV_UP:
x25_link_device_up(dev);
break;
+ case NETDEV_GOING_DOWN:
+ if ((neigh = x25_get_neigh(dev)))
+ x25_terminate_link(neigh);
+ break;
case NETDEV_DOWN:
x25_kill_by_device(dev);
x25_route_device_down(dev);
@@ -471,6 +479,7 @@ static int x25_create(struct socket *sock, int protocol)
sock->ops = &x25_proto_ops;
sk->protocol = protocol;
+ sk->backlog_rcv = x25_backlog_rcv;
x25->t21 = sysctl_x25_call_request_timeout;
x25->t22 = sysctl_x25_reset_request_timeout;
@@ -905,6 +914,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
return err;
+ X25_SKB_CB(skb)->flags = msg->msg_flags;
skb_reserve(skb, X25_MAX_L2_LEN + X25_EXT_MIN_LEN);
@@ -974,14 +984,31 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
if (msg->msg_flags & MSG_OOB) {
skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb);
} else {
- err = x25_output(sk, skb);
- if(err){
- len = err;
+ len = x25_output(sk, skb);
+ if(len<0){
kfree_skb(skb);
+ } else {
+ if(sk->protinfo.x25->qbitincl) len++;
}
}
+ /*
+ * lock_sock() is currently only used to serialize this x25_kick()
+ * against input-driven x25_kick() calls. It currently only blocks
+ * incoming packets for this socket and does not protect against
+ * any other socket state changes and is not called from anywhere
+ * else. As x25_kick() cannot block and as long as all socket
+ * operations are BKL-wrapped, we don't need take to care about
+ * purging the backlog queue in x25_release().
+ *
+ * Using lock_sock() to protect all socket operations entirely
+ * (and making the whole x25 stack SMP aware) unfortunately would
+ * require major changes to {send,recv}msg and skb allocation methods.
+ * -> 2.5 ;)
+ */
+ lock_sock(sk);
x25_kick(sk);
+ release_sock(sk);
return len;
}
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index d986022fb..fbc781dce 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -68,8 +68,17 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
* Find an existing socket.
*/
if ((sk = x25_find_socket(lci, neigh)) != NULL) {
+ int queued = 1;
+
skb->h.raw = skb->data;
- return x25_process_rx_frame(sk, skb);
+ bh_lock_sock(sk);
+ if (!sk->lock.users) {
+ queued = x25_process_rx_frame(sk, skb);
+ } else {
+ sk_add_backlog(sk, skb);
+ }
+ bh_unlock_sock(sk);
+ return queued;
}
/*
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 5110d327a..bcb5f1cf4 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -16,8 +16,10 @@
* X.25 001 Jonathan Naylor Started coding.
* X.25 002 Jonathan Naylor Centralised disconnection code.
* New timer architecture.
- * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * 2000-03-20 Daniela Squassoni Disabling/enabling of facilities
* negotiation.
+ * 2000-11-10 Henner Eisen Check and reset for out-of-sequence
+ * i-frames.
*/
#include <linux/config.h>
@@ -216,7 +218,8 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp
case X25_DATA: /* XXX */
sk->protinfo.x25->condition &= ~X25_COND_PEER_RX_BUSY;
- if (!x25_validate_nr(sk, nr)) {
+ if ((ns!=sk->protinfo.x25->vr) ||
+ !x25_validate_nr(sk, nr)) {
x25_clear_queues(sk);
x25_write_internal(sk, X25_RESET_REQUEST);
x25_start_t22timer(sk);
@@ -357,4 +360,14 @@ int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
return queued;
}
+int x25_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ int queued;
+
+ queued = x25_process_rx_frame(sk,skb);
+ if(!queued) kfree_skb(skb);
+
+ return 0;
+}
+
#endif
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index 077f2c0b4..b3ce30477 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -15,7 +15,10 @@
* History
* X.25 001 Jonathan Naylor Started coding.
* X.25 002 Jonathan Naylor New timer architecture.
- * 2000-09-04 Henner Eisen Prevented x25_output() skb leakage.
+ * 2000-09-04 Henner Eisen Prevented x25_output() skb leakage.
+ * 2000-10-27 Henner Eisen MSG_DONTWAIT for fragment allocation.
+ * 2000-11-10 Henner Eisen x25_send_iframe(): re-queued frames
+ * needed cleaned seq-number fields.
*/
#include <linux/config.h>
@@ -55,13 +58,17 @@ static int x25_pacsize_to_bytes(unsigned int pacsize)
}
/*
- * This is where all X.25 information frames pass;
+ * This is where all X.25 information frames pass.
+ *
+ * Returns the amount of user data bytes sent on success
+ * or a negative error code on failure.
*/
int x25_output(struct sock *sk, struct sk_buff *skb)
{
struct sk_buff *skbn;
unsigned char header[X25_EXT_MIN_LEN];
int err, frontlen, len, header_len, max_len;
+ int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT;
header_len = (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN;
max_len = x25_pacsize_to_bytes(sk->protinfo.x25->facilities.pacsize_out);
@@ -74,11 +81,14 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
frontlen = skb_headroom(skb);
while (skb->len > 0) {
- if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL){
- int unsent = skb->len - header_len;
- SOCK_DEBUG(sk, "x25_output: framgent allocation failed, err=%d, %d bytes unsent\n", err, unsent);
- return err;
+ if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, noblock, &err)) == NULL){
+ if(err == -EWOULDBLOCK && noblock){
+ kfree_skb(skb);
+ return sent;
}
+ SOCK_DEBUG(sk, "x25_output: fragment allocation failed, err=%d, %d bytes sent\n", err, sent);
+ return err;
+ }
skb_reserve(skbn, frontlen);
@@ -100,13 +110,15 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
}
skb_queue_tail(&sk->write_queue, skbn);
+ sent += len;
}
kfree_skb(skb);
} else {
skb_queue_tail(&sk->write_queue, skb);
+ sent = skb->len - header_len;
}
- return 0;
+ return sent;
}
/*
@@ -119,9 +131,11 @@ static void x25_send_iframe(struct sock *sk, struct sk_buff *skb)
return;
if (sk->protinfo.x25->neighbour->extended) {
- skb->data[2] |= (sk->protinfo.x25->vs << 1) & 0xFE;
+ skb->data[2] = (sk->protinfo.x25->vs << 1) & 0xFE;
+ skb->data[3] &= X25_EXT_M_BIT;
skb->data[3] |= (sk->protinfo.x25->vr << 1) & 0xFE;
} else {
+ skb->data[2] &= X25_STD_M_BIT;
skb->data[2] |= (sk->protinfo.x25->vs << 1) & 0x0E;
skb->data[2] |= (sk->protinfo.x25->vr << 5) & 0xE0;
}