summaryrefslogtreecommitdiffstats
path: root/net/rose/rose_route.c
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/rose_route.c
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/rose_route.c')
-rw-r--r--net/rose/rose_route.c163
1 files changed, 128 insertions, 35 deletions
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();