diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /net/x25 | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (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.c | 37 | ||||
-rw-r--r-- | net/x25/x25_dev.c | 14 | ||||
-rw-r--r-- | net/x25/x25_facilities.c | 22 | ||||
-rw-r--r-- | net/x25/x25_in.c | 18 | ||||
-rw-r--r-- | net/x25/x25_link.c | 5 |
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); } /* |