diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
commit | dcec8a13bf565e47942a1751a9cec21bec5648fe (patch) | |
tree | 548b69625b18cc2e88c3e68d0923be546c9ebb03 /net/rose | |
parent | 2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff) |
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash.
o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'net/rose')
-rw-r--r-- | net/rose/Makefile | 3 | ||||
-rw-r--r-- | net/rose/af_rose.c | 12 | ||||
-rw-r--r-- | net/rose/rose_dev.c | 8 | ||||
-rw-r--r-- | net/rose/rose_in.c | 27 | ||||
-rw-r--r-- | net/rose/rose_link.c | 7 | ||||
-rw-r--r-- | net/rose/rose_loopback.c | 126 | ||||
-rw-r--r-- | net/rose/rose_route.c | 163 |
7 files changed, 293 insertions, 53 deletions
diff --git a/net/rose/Makefile b/net/rose/Makefile index 7eb55881e..de3f1b257 100644 --- a/net/rose/Makefile +++ b/net/rose/Makefile @@ -8,7 +8,8 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := rose.o -O_OBJS := af_rose.o rose_dev.o rose_in.o rose_link.o rose_out.o rose_route.o rose_subr.o rose_timer.o +O_OBJS := af_rose.o rose_dev.o rose_in.o rose_link.o rose_loopback.o \ + rose_out.o rose_route.o rose_subr.o rose_timer.o M_OBJS := $(O_TARGET) ifeq ($(CONFIG_SYSCTL),y) diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index a575402c7..286a2aa68 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1261,7 +1261,7 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i cli(); - len += sprintf(buffer, "dest_addr dest_call src_addr src_call dev lci st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q\n"); + len += sprintf(buffer, "dest_addr dest_call src_addr src_call dev lci st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); for (s = rose_list; s != NULL; s = s->next) { if ((dev = s->protinfo.rose->device) == NULL) @@ -1278,7 +1278,7 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i else callsign = ax2asc(&s->protinfo.rose->source_call); - len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d\n", + len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n", rose2asc(&s->protinfo.rose->source_addr), callsign, devname, @@ -1295,7 +1295,8 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i ax25_display_timer(&s->protinfo.rose->idletimer) / (60 * HZ), s->protinfo.rose->idle / (60 * HZ), atomic_read(&s->wmem_alloc), - atomic_read(&s->rmem_alloc)); + atomic_read(&s->rmem_alloc), + s->socket != NULL ? s->socket->inode->i_ino : 0L); pos = begin + len; @@ -1408,6 +1409,9 @@ __initfunc(void rose_proto_init(struct net_proto *pro)) #ifdef CONFIG_SYSCTL rose_register_sysctl(); #endif + rose_loopback_init(); + + rose_add_loopback_neigh(); #ifdef CONFIG_PROC_FS proc_net_register(&proc_net_rose); @@ -1443,6 +1447,8 @@ void cleanup_module(void) proc_net_unregister(PROC_NET_RS_NODES); proc_net_unregister(PROC_NET_RS_ROUTES); #endif + rose_loopback_clear(); + rose_rt_free(); ax25_protocol_release(AX25_P_ROSE); diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 0cc81c464..702a55931 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -134,11 +134,11 @@ static int rose_set_mac_address(struct device *dev, void *addr) { struct sockaddr *sa = addr; - ax25_listen_release((ax25_address *)dev->dev_addr, NULL); + rose_del_loopback_node((rose_address *)dev->dev_addr); memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); - ax25_listen_register((ax25_address *)dev->dev_addr, NULL); + rose_add_loopback_node((rose_address *)dev->dev_addr); return 0; } @@ -150,7 +150,7 @@ static int rose_open(struct device *dev) MOD_INC_USE_COUNT; - ax25_listen_register((ax25_address *)dev->dev_addr, NULL); + rose_add_loopback_node((rose_address *)dev->dev_addr); return 0; } @@ -162,7 +162,7 @@ static int rose_close(struct device *dev) MOD_DEC_USE_COUNT; - ax25_listen_release((ax25_address *)dev->dev_addr, NULL); + rose_del_loopback_node((rose_address *)dev->dev_addr); return 0; } diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c index de412d3c4..be86c9e16 100644 --- a/net/rose/rose_in.c +++ b/net/rose/rose_in.c @@ -141,10 +141,6 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety case ROSE_RR: case ROSE_RNR: - if (frametype == ROSE_RNR) - sk->protinfo.rose->condition |= ROSE_COND_PEER_RX_BUSY; - else - sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; if (!rose_validate_nr(sk, nr)) { rose_write_internal(sk, ROSE_RESET_REQUEST); sk->protinfo.rose->condition = 0x00; @@ -157,8 +153,11 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety rose_stop_idletimer(sk); } else { rose_frames_acked(sk, nr); - if (frametype == ROSE_RNR) - rose_requeue_frames(sk); + if (frametype == ROSE_RNR) { + sk->protinfo.rose->condition |= ROSE_COND_PEER_RX_BUSY; + } else { + sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; + } } break; @@ -177,16 +176,26 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety break; } rose_frames_acked(sk, nr); - if (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY) - break; if (ns == sk->protinfo.rose->vr) { rose_start_idletimer(sk); if (sock_queue_rcv_skb(sk, skb) == 0) { sk->protinfo.rose->vr = (sk->protinfo.rose->vr + 1) % ROSE_MODULUS; queued = 1; } else { - sk->protinfo.rose->condition |= ROSE_COND_OWN_RX_BUSY; + /* Should never happen ! */ + rose_write_internal(sk, ROSE_RESET_REQUEST); + sk->protinfo.rose->condition = 0x00; + sk->protinfo.rose->vs = 0; + sk->protinfo.rose->vr = 0; + sk->protinfo.rose->va = 0; + sk->protinfo.rose->vl = 0; + sk->protinfo.rose->state = ROSE_STATE_4; + rose_start_t2timer(sk); + rose_stop_idletimer(sk); + break; } + if (atomic_read(&sk->rmem_alloc) > (sk->rcvbuf / 2)) + sk->protinfo.rose->condition |= ROSE_COND_OWN_RX_BUSY; } /* * If the window is full, ack the frame, else start the diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index c462fa696..33cc2f990 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -113,7 +113,7 @@ static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) else rose_call = &rose_callsign; - neigh->ax25 = ax25_send_frame(skb, 0, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); + neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); return (neigh->ax25 != NULL); } @@ -296,6 +296,11 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh) return; } + if (neigh->loopback) { + rose_loopback_queue(skb, neigh); + return; + } + if (!rose_link_up(neigh)) neigh->restarted = 0; diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c new file mode 100644 index 000000000..ce66a9911 --- /dev/null +++ b/net/rose/rose_loopback.c @@ -0,0 +1,126 @@ +/* + * ROSE release 003 + * + * This code REQUIRES 2.1.15 or higher/ NET3.038 + * + * This module: + * This module is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * History + * ROSE 003 Jonathan(G4KLX) Created this file from nr_loopback.c. + * + */ + +#include <linux/config.h> +#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) +#include <linux/types.h> +#include <linux/socket.h> +#include <linux/timer.h> +#include <net/ax25.h> +#include <linux/skbuff.h> +#include <net/rose.h> + +static struct sk_buff_head loopback_queue; +static struct timer_list loopback_timer; + +static void rose_set_loopback_timer(void); + +void rose_loopback_init(void) +{ + skb_queue_head_init(&loopback_queue); + + init_timer(&loopback_timer); +} + +static int rose_loopback_running(void) +{ + return (loopback_timer.prev != NULL || loopback_timer.next != NULL); +} + +int rose_loopback_queue(struct sk_buff *skb, struct rose_neigh *neigh) +{ + struct sk_buff *skbn; + + skbn = skb_clone(skb, GFP_ATOMIC); + + kfree_skb(skb); + + if (skbn != NULL) { + skb_queue_tail(&loopback_queue, skbn); + + if (!rose_loopback_running()) + rose_set_loopback_timer(); + } + + return 1; +} + +static void rose_loopback_timer(unsigned long); + +static void rose_set_loopback_timer(void) +{ + del_timer(&loopback_timer); + + loopback_timer.data = 0; + loopback_timer.function = &rose_loopback_timer; + loopback_timer.expires = jiffies + 10; + + add_timer(&loopback_timer); +} + +static void rose_loopback_timer(unsigned long param) +{ + struct sk_buff *skb; + struct device *dev; + rose_address *dest; + struct sock *sk; + unsigned short frametype; + unsigned int lci_i, lci_o; + + while ((skb = skb_dequeue(&loopback_queue)) != NULL) { + lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); + frametype = skb->data[2]; + dest = (rose_address *)(skb->data + 4); + lci_o = sysctl_rose_maximum_vcs - lci_i + 1; + + skb->h.raw = skb->data; + + if ((sk = rose_find_socket(lci_o, rose_loopback_neigh)) != NULL) { + if (rose_process_rx_frame(sk, skb) == 0) + kfree_skb(skb); + continue; + } + + if (frametype == ROSE_CALL_REQUEST) { + if ((dev = rose_dev_get(dest)) != NULL) { + if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) + kfree_skb(skb); + } else { + kfree_skb(skb); + } + } else { + kfree_skb(skb); + } + } +} + +#ifdef MODULE + +void rose_loopback_clear(void) +{ + struct sk_buff *skb; + + del_timer(&loopback_timer); + + while ((skb = skb_dequeue(&loopback_queue)) != NULL) { + skb->sk = NULL; + kfree_skb(skb); + } +} + +#endif + +#endif diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 917846bf7..2d6d23230 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -55,6 +55,8 @@ static struct rose_node *rose_node_list = NULL; static struct rose_neigh *rose_neigh_list = NULL; static struct rose_route *rose_route_list = NULL; +struct rose_neigh *rose_loopback_neigh = NULL; + static void rose_remove_neigh(struct rose_neigh *); /* @@ -72,6 +74,9 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0)) break; + if (rose_node != NULL && rose_node->loopback) + return -EINVAL; + for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0 && rose_neigh->dev == dev) break; @@ -87,6 +92,7 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de rose_neigh->count = 0; rose_neigh->use = 0; rose_neigh->dce_mode = 0; + rose_neigh->loopback = 0; rose_neigh->number = rose_neigh_no++; rose_neigh->restarted = 0; @@ -123,6 +129,7 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de rose_node->address = rose_route->address; rose_node->mask = rose_route->mask; rose_node->count = 1; + rose_node->loopback = 0; rose_node->neighbour[0] = rose_neigh; save_flags(flags); cli(); @@ -263,6 +270,8 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct device *de if (rose_node == NULL) return -EINVAL; + if (rose_node->loopback) return -EINVAL; + for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0 && rose_neigh->dev == dev) break; @@ -299,6 +308,86 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct device *de } /* + * Add the loopback neighbour. + */ +int rose_add_loopback_neigh(void) +{ + unsigned long flags; + + if ((rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_ATOMIC)) == NULL) + return -ENOMEM; + + rose_loopback_neigh->callsign = null_ax25_address; + rose_loopback_neigh->digipeat = NULL; + rose_loopback_neigh->ax25 = NULL; + rose_loopback_neigh->dev = NULL; + rose_loopback_neigh->count = 0; + rose_loopback_neigh->use = 0; + rose_loopback_neigh->dce_mode = 1; + rose_loopback_neigh->loopback = 1; + rose_loopback_neigh->number = rose_neigh_no++; + rose_loopback_neigh->restarted = 1; + + save_flags(flags); cli(); + rose_loopback_neigh->next = rose_neigh_list; + rose_neigh_list = rose_loopback_neigh; + restore_flags(flags); + + return 0; +} + +/* + * Add a loopback node. + */ +int rose_add_loopback_node(rose_address *address) +{ + struct rose_node *rose_node; + unsigned long flags; + + for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) + if ((rose_node->mask == 10) && (rosecmpm(address, &rose_node->address, 10) == 0) && rose_node->loopback) + break; + + if (rose_node != NULL) return 0; + + if ((rose_node = kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL) + return -ENOMEM; + + rose_node->address = *address; + rose_node->mask = 10; + rose_node->count = 1; + rose_node->loopback = 1; + rose_node->neighbour[0] = rose_loopback_neigh; + + save_flags(flags); cli(); + rose_node->next = rose_node_list; + rose_node_list = rose_node; + restore_flags(flags); + + rose_loopback_neigh->count++; + + return 0; +} + +/* + * Delete a loopback node. + */ +void rose_del_loopback_node(rose_address *address) +{ + struct rose_node *rose_node; + + for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) + if ((rose_node->mask == 10) && (rosecmpm(address, &rose_node->address, 10) == 0) && rose_node->loopback) + break; + + if (rose_node == NULL) return; + + rose_remove_node(rose_node); + + rose_loopback_neigh->count--; +} + +/* * A device has been removed. Remove its routes and neighbours. */ void rose_rt_device_down(struct device *dev) @@ -723,16 +812,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) rosecmp(src_addr, &rose_route->src_addr) == 0 && ax25cmp(&facilities.dest_call, &rose_route->src_call) == 0 && ax25cmp(&facilities.source_call, &rose_route->dest_call) == 0) { - printk(KERN_DEBUG "ROSE: routing loop from %s\n", rose2asc(src_addr)); - printk(KERN_DEBUG "ROSE: to %s\n", rose2asc(dest_addr)); rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 120); return 0; } } if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic)) == NULL) { - if (cause == ROSE_NOT_OBTAINABLE) - printk(KERN_DEBUG "ROSE: no route to %s\n", rose2asc(dest_addr)); rose_transmit_clear_request(rose_neigh, lci, cause, diagnostic); return 0; } @@ -788,16 +873,22 @@ int rose_nodes_get_info(char *buffer, char **start, off_t offset, len += sprintf(buffer, "address mask n neigh neigh neigh\n"); for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) { - len += sprintf(buffer + len, "%-10s %04d %d", - rose2asc(&rose_node->address), - rose_node->mask, - rose_node->count); + if (rose_node->loopback) { + len += sprintf(buffer + len, "%-10s %04d 1 loopback\n", + rose2asc(&rose_node->address), + rose_node->mask); + } else { + len += sprintf(buffer + len, "%-10s %04d %d", + rose2asc(&rose_node->address), + rose_node->mask, + rose_node->count); - for (i = 0; i < rose_node->count; i++) - len += sprintf(buffer + len, " %05d", - rose_node->neighbour[i]->number); + for (i = 0; i < rose_node->count; i++) + len += sprintf(buffer + len, " %05d", + rose_node->neighbour[i]->number); - len += sprintf(buffer + len, "\n"); + len += sprintf(buffer + len, "\n"); + } pos = begin + len; @@ -834,33 +925,35 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset, len += sprintf(buffer, "addr callsign dev count use mode restart t0 tf digipeaters\n"); for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) { - len += sprintf(buffer + len, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu", - rose_neigh->number, - ax2asc(&rose_neigh->callsign), - rose_neigh->dev ? rose_neigh->dev->name : "???", - rose_neigh->count, - rose_neigh->use, - (rose_neigh->dce_mode) ? "DCE" : "DTE", - (rose_neigh->restarted) ? "yes" : "no", - ax25_display_timer(&rose_neigh->t0timer) / HZ, - ax25_display_timer(&rose_neigh->ftimer) / HZ); - - if (rose_neigh->digipeat != NULL) { - for (i = 0; i < rose_neigh->digipeat->ndigi; i++) - len += sprintf(buffer + len, " %s", ax2asc(&rose_neigh->digipeat->calls[i])); - } + if (!rose_neigh->loopback) { + len += sprintf(buffer + len, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu", + rose_neigh->number, + ax2asc(&rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, + rose_neigh->use, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, + ax25_display_timer(&rose_neigh->ftimer) / HZ); + + if (rose_neigh->digipeat != NULL) { + for (i = 0; i < rose_neigh->digipeat->ndigi; i++) + len += sprintf(buffer + len, " %s", ax2asc(&rose_neigh->digipeat->calls[i])); + } - len += sprintf(buffer + len, "\n"); + len += sprintf(buffer + len, "\n"); - pos = begin + len; + pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } + if (pos < offset) { + len = 0; + begin = pos; + } - if (pos > offset + length) - break; + if (pos > offset + length) + break; + } } sti(); |