summaryrefslogtreecommitdiffstats
path: root/net/rose
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
commitdcec8a13bf565e47942a1751a9cec21bec5648fe (patch)
tree548b69625b18cc2e88c3e68d0923be546c9ebb03 /net/rose
parent2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (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/Makefile3
-rw-r--r--net/rose/af_rose.c12
-rw-r--r--net/rose/rose_dev.c8
-rw-r--r--net/rose/rose_in.c27
-rw-r--r--net/rose/rose_link.c7
-rw-r--r--net/rose/rose_loopback.c126
-rw-r--r--net/rose/rose_route.c163
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();