summaryrefslogtreecommitdiffstats
path: root/net/x25
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /net/x25
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff)
o Merge with Linux 2.1.116.
o New Newport console code. o New G364 console code.
Diffstat (limited to 'net/x25')
-rw-r--r--net/x25/af_x25.c37
-rw-r--r--net/x25/x25_dev.c14
-rw-r--r--net/x25/x25_facilities.c22
-rw-r--r--net/x25/x25_in.c18
-rw-r--r--net/x25/x25_link.c5
5 files changed, 76 insertions, 20 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 514f64e1b..60a3581e5 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -174,7 +174,8 @@ static void x25_kill_by_device(struct device *dev)
struct sock *s;
for (s = x25_list; s != NULL; s = s->next)
- if (s->protinfo.x25->neighbour->dev == dev)
+ if (s->protinfo.x25->neighbour &&
+ s->protinfo.x25->neighbour->dev == dev)
x25_disconnect(s, ENETUNREACH, 0, 0);
}
@@ -621,6 +622,9 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
if ((sk->protinfo.x25->neighbour = x25_get_neigh(dev)) == NULL)
return -ENETUNREACH;
+ x25_limit_facilities(&sk->protinfo.x25->facilities,
+ sk->protinfo.x25->neighbour);
+
if ((sk->protinfo.x25->lci = x25_new_lci(sk->protinfo.x25->neighbour)) == 0)
return -ENETUNREACH;
@@ -787,6 +791,13 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
}
/*
+ * current neighbour/link might impose additional limits
+ * on certain facilties
+ */
+
+ x25_limit_facilities(&facilities,neigh);
+
+ /*
* Try to create a new socket.
*/
if ((make = x25_make_new(sk)) == NULL) {
@@ -1124,18 +1135,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return -EINVAL;
if (facilities.pacsize_out < X25_PS16 || facilities.pacsize_out > X25_PS4096)
return -EINVAL;
- if (sk->state == TCP_CLOSE || sk->protinfo.x25->neighbour->extended)
- {
- if (facilities.winsize_in < 1 || facilities.winsize_in > 127)
- return -EINVAL;
- if (facilities.winsize_out < 1 || facilities.winsize_out > 127)
- return -EINVAL;
- } else {
- if (facilities.winsize_in < 1 || facilities.winsize_in > 7)
- return -EINVAL;
- if (facilities.winsize_out < 1 || facilities.winsize_out > 7)
- return -EINVAL;
- }
+ if (facilities.winsize_in < 1 || facilities.winsize_in > 127)
+ return -EINVAL;
if (facilities.throughput < 0x03 || facilities.throughput > 0x2C)
return -EINVAL;
if (facilities.reverse != 0 && facilities.reverse != 1)
@@ -1276,6 +1277,16 @@ struct notifier_block x25_dev_notifier = {
0
};
+void x25_kill_by_neigh(struct x25_neigh *neigh)
+{
+ struct sock *s;
+
+ for( s=x25_list; s != NULL; s=s->next){
+ if( s->protinfo.x25->neighbour == neigh )
+ x25_disconnect(s, ENETUNREACH, 0, 0);
+ }
+}
+
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry proc_net_x25 = {
PROC_NET_X25, 3, "x25",
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 16fc3677d..bcbf31b0d 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -98,6 +98,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
int x25_lapb_receive_frame(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
{
struct x25_neigh *neigh;
+ int queued;
skb->sk = NULL;
@@ -113,7 +114,13 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct device *dev, struct packe
switch (skb->data[0]) {
case 0x00:
skb_pull(skb, 1);
- return x25_receive_data(skb, neigh);
+ queued = x25_receive_data(skb, neigh);
+ if( ! queued )
+ /* We need to free the skb ourselves because
+ * net_bh() won't care about our return code.
+ */
+ kfree_skb(skb);
+ return 0;
case 0x01:
x25_link_established(neigh);
@@ -215,6 +222,8 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *neigh)
{
unsigned char *dptr;
+ skb->nh.raw = skb->data;
+
switch (neigh->dev->type) {
case ARPHRD_X25:
dptr = skb_push(skb, 1);
@@ -238,3 +247,6 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *neigh)
}
#endif
+
+
+
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index af072ce22..18de2da1a 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -200,4 +200,26 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_fa
return len;
}
+/*
+ * Limit values of certain facilities according to the capability of the
+ * currently attached x25 link.
+ */
+void x25_limit_facilities(struct x25_facilities *facilities,
+ struct x25_neigh *neighbour)
+{
+
+ if( ! neighbour->extended ){
+ if( facilities->winsize_in > 7 ){
+ printk(KERN_DEBUG "X.25: incoming winsize limited to 7\n");
+ facilities->winsize_in = 7;
+ }
+ if( facilities->winsize_out > 7 ){
+ facilities->winsize_out = 7;
+ printk( KERN_DEBUG "X.25: outgoing winsize limited to 7\n");
+ }
+ }
+}
+
#endif
+
+
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index ae98e95ec..ad7adb7ea 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -49,17 +49,20 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
if (more) {
sk->protinfo.x25->fraglen += skb->len;
skb_queue_tail(&sk->protinfo.x25->fragment_queue, skb);
+ skb_set_owner_r(skb, sk);
return 0;
}
if (!more && sk->protinfo.x25->fraglen > 0) { /* End of fragment */
- sk->protinfo.x25->fraglen += skb->len;
- skb_queue_tail(&sk->protinfo.x25->fragment_queue, skb);
+ int len = sk->protinfo.x25->fraglen + skb->len;
- if ((skbn = alloc_skb(sk->protinfo.x25->fraglen, GFP_ATOMIC)) == NULL)
+ if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL){
+ kfree_skb(skb);
return 1;
+ }
+
+ skb_queue_tail(&sk->protinfo.x25->fragment_queue, skb);
- skb_set_owner_r(skbn, sk);
skbn->h.raw = skbn->data;
skbo = skb_dequeue(&sk->protinfo.x25->fragment_queue);
@@ -75,7 +78,12 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
sk->protinfo.x25->fraglen = 0;
}
- return sock_queue_rcv_skb(sk, skbn);
+ skb_set_owner_r(skbn, sk);
+ skb_queue_tail(&sk->receive_queue, skbn);
+ if (!sk->dead)
+ sk->data_ready(sk,skbn->len);
+
+ return 0;
}
/*
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index f27fa4f4a..961682702 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -264,11 +264,14 @@ void x25_link_established(struct x25_neigh *neigh)
/*
* Called when the link layer has terminated, or an establishment
- * request has failed. XXX should tell sockets.
+ * request has failed.
*/
+
void x25_link_terminated(struct x25_neigh *neigh)
{
neigh->state = X25_LINK_STATE_0;
+ /* Out of order: clear existing virtual calls (X.25 03/93 4.6.3) */
+ x25_kill_by_neigh(neigh);
}
/*