patch-2.0.36 linux/net/rose/rose_route.c
Next file: linux/net/rose/rose_subr.c
Previous file: linux/net/rose/rose_out.c
Back to the patch index
Back to the overall index
- Lines: 427
- Date:
Sun Nov 15 10:33:22 1998
- Orig file:
v2.0.35/linux/net/rose/rose_route.c
- Orig date:
Sun Nov 15 10:50:02 1998
diff -u --recursive --new-file v2.0.35/linux/net/rose/rose_route.c linux/net/rose/rose_route.c
@@ -54,6 +54,17 @@
static struct rose_route *rose_route_list = NULL;
static void rose_remove_neigh(struct rose_neigh *);
+static int rose_del_node(struct rose_route_struct *, struct device *);
+
+static int rose_is_null(rose_address *address)
+{
+ int i;
+
+ for (i = 0 ; i < sizeof(rose_address) ; i++)
+ if (address->rose_addr[i])
+ return 0;
+ return 1;
+}
/*
* Add a new route to a node, and in the process add the node and the
@@ -63,6 +74,7 @@
{
struct rose_node *rose_node, *rose_tmpn, *rose_tmpp;
struct rose_neigh *rose_neigh;
+ struct rose_route_struct dummy_route;
unsigned long flags;
int i;
@@ -166,16 +178,22 @@
rose_neigh->count++;
- return 0;
- }
-
- /* We have space, slot it in */
- if (rose_node->count < 3) {
+ } else if (rose_node->count < ROSE_MAX_ALTERNATE) {
+ /* We have space, slot it in */
rose_node->neighbour[rose_node->count] = rose_neigh;
rose_node->count++;
rose_neigh->count++;
}
+ if (!rose_is_null(&rose_route->address))
+ {
+ /* Delete this neighbourg from the dummy node 0000000000 */
+ dummy_route = *rose_route;
+ dummy_route.mask = 10;
+ memset(&dummy_route.address, 0, sizeof(rose_address));
+ rose_del_node(&dummy_route, dev);
+ }
+
return 0;
}
@@ -252,11 +270,11 @@
struct rose_route *s;
unsigned long flags;
- if (rose_route->neigh1 != NULL)
- rose_route->neigh1->use--;
+ if (rose_route->tr1.neigh != NULL)
+ rose_route->tr1.neigh->use--;
- if (rose_route->neigh2 != NULL)
- rose_route->neigh2->use--;
+ if (rose_route->tr2.neigh != NULL)
+ rose_route->tr2.neigh->use--;
save_flags(flags);
cli();
@@ -290,6 +308,7 @@
{
struct rose_node *rose_node;
struct rose_neigh *rose_neigh;
+ struct rose_route_struct dummy_route;
int i;
for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next)
@@ -308,8 +327,16 @@
if (rose_node->neighbour[i] == rose_neigh) {
rose_neigh->count--;
- if (rose_neigh->count == 0 && rose_neigh->use == 0)
+ if (rose_neigh->count == 0) {
+ /* Add a dummy node to keep the neighbourg still visible */
+ dummy_route = *rose_route;
+ dummy_route.mask = 10;
+ memset(&dummy_route.address, 0, sizeof(rose_address));
+ rose_add_node(&dummy_route, dev);
+ }
+ /* if (rose_neigh->count == 0 && rose_neigh->use == 0) {
rose_remove_neigh(rose_neigh);
+ } */
rose_node->count--;
@@ -388,7 +415,7 @@
s = rose_route;
rose_route = rose_route->next;
- if (s->neigh1->dev == dev || s->neigh2->dev == dev)
+ if (s->tr1.neigh->dev == dev || s->tr2.neigh->dev == dev)
rose_remove_route(s);
}
}
@@ -472,8 +499,8 @@
struct rose_route *rose_route;
for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next)
- if ((rose_route->neigh1 == neigh && rose_route->lci1 == lci) ||
- (rose_route->neigh2 == neigh && rose_route->lci2 == lci))
+ if ((rose_route->tr1.neigh == neigh && rose_route->tr1.lci == lci) ||
+ (rose_route->tr2.neigh == neigh && rose_route->tr2.lci == lci))
return rose_route;
return NULL;
@@ -496,7 +523,7 @@
else
failed = 1;
}
- /* F6FBB : All nodes for this route are out of order */
+ /* do not accept other node address */
break;
}
}
@@ -529,8 +556,8 @@
memcpy_fromfs(&rose_route, arg, sizeof(struct rose_route_struct));
if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
return -EINVAL;
- if (rose_dev_get(&rose_route.address) != NULL) /* Can't add routes to ourself */
- return -EINVAL;
+ /* if (rose_dev_get(&rose_route.address) != NULL) / Can't add routes to ourself /
+ return -EINVAL; */
if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
return -EINVAL;
@@ -571,25 +598,25 @@
rose_route = rose_route_list;
while (rose_route != NULL) {
- if ((rose_route->neigh1 == rose_neigh && rose_route->neigh2 == rose_neigh) ||
- (rose_route->neigh1 == rose_neigh && rose_route->neigh2 == NULL) ||
- (rose_route->neigh2 == rose_neigh && rose_route->neigh1 == NULL)) {
+ if ((rose_route->tr1.neigh == rose_neigh && rose_route->tr2.neigh == rose_neigh) ||
+ (rose_route->tr1.neigh == rose_neigh && rose_route->tr2.neigh == NULL) ||
+ (rose_route->tr2.neigh == rose_neigh && rose_route->tr1.neigh == NULL)) {
s = rose_route->next;
rose_remove_route(rose_route);
rose_route = s;
continue;
}
- if (rose_route->neigh1 == rose_neigh) {
- rose_route->neigh1->use--;
- rose_route->neigh1 = NULL;
- rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0);
+ if (rose_route->tr1.neigh == rose_neigh) {
+ rose_route->tr1.neigh->use--;
+ rose_route->tr1.neigh = NULL;
+ rose_transmit_clear_request(rose_route->tr2.neigh, rose_route->tr2.lci, ROSE_OUT_OF_ORDER, 0);
}
- if (rose_route->neigh2 == rose_neigh) {
- rose_route->neigh2->use--;
- rose_route->neigh2 = NULL;
- rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0);
+ if (rose_route->tr2.neigh == rose_neigh) {
+ rose_route->tr2.neigh->use--;
+ rose_route->tr2.neigh = NULL;
+ rose_transmit_clear_request(rose_route->tr1.neigh, rose_route->tr1.lci, ROSE_OUT_OF_ORDER, 0);
}
rose_route = rose_route->next;
@@ -634,13 +661,23 @@
}
/*
+ * A Restart has occured. Delete all existing routes to this neighbour
+ */
+void rose_clean_neighbour(struct rose_neigh *rose_neigh)
+{
+ rose_del_route_by_neigh(rose_neigh);
+ rose_kill_by_neigh(rose_neigh);
+}
+
+
+/*
* Route a frame to an appropriate AX.25 connection.
*/
int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
{
struct rose_neigh *rose_neigh, *new_neigh;
struct rose_route *rose_route;
- struct rose_facilities facilities;
+ struct rose_facilities_struct facilities;
rose_address *src_addr, *dest_addr;
struct sock *sk;
unsigned short frametype;
@@ -648,6 +685,8 @@
unsigned char cause, diagnostic;
struct device *dev;
unsigned long flags;
+ int len;
+ struct sk_buff *skbn;
#ifdef CONFIG_FIREWALL
if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL) != FW_ACCEPT)
@@ -663,8 +702,10 @@
if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 && ax25->device == rose_neigh->dev)
break;
- if (rose_neigh == NULL)
+ if (rose_neigh == NULL) {
+ printk("rose_route : unknown neighbour or device %s\n", ax2asc(&ax25->dest_addr));
return 0;
+ }
/*
* Obviously the link is working, halt the ftimer.
@@ -684,16 +725,36 @@
* Find an existing socket.
*/
if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) {
- skb->h.raw = skb->data;
- return rose_process_rx_frame(sk, skb);
+ if (frametype == ROSE_CALL_REQUEST)
+ {
+ /* F6FBB - Remove an existing unused socket */
+ rose_clear_queues(sk);
+ sk->protinfo.rose->cause = ROSE_NETWORK_CONGESTION;
+ sk->protinfo.rose->diagnostic = 0;
+ sk->protinfo.rose->neighbour->use--;
+ sk->protinfo.rose->neighbour = NULL;
+ sk->protinfo.rose->state = ROSE_STATE_0;
+ sk->state = TCP_CLOSE;
+ sk->err = 0;
+ sk->shutdown |= SEND_SHUTDOWN;
+ if (!sk->dead)
+ sk->state_change(sk);
+ sk->dead = 1;
+ }
+ else
+ {
+ skb->h.raw = skb->data;
+ return rose_process_rx_frame(sk, skb);
+ }
}
/*
- * Is is a Call Request and is it for us ?
+ * Is it a Call Request and is it for us ?
*/
if (frametype == ROSE_CALL_REQUEST)
- if ((dev = rose_dev_get(dest_addr)) != NULL)
+ if ((dev = rose_dev_get(dest_addr)) != NULL) {
return rose_rx_call_request(skb, dev, rose_neigh, lci);
+ }
if (!sysctl_rose_routing_control) {
rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 0);
@@ -704,12 +765,20 @@
* Route it to the next in line if we have an entry for it.
*/
for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
- if (rose_route->lci1 == lci && rose_route->neigh1 == rose_neigh) {
- if (rose_route->neigh2 != NULL) {
+ if (rose_route->tr1.lci == lci && rose_route->tr1.neigh == rose_neigh) {
+ if (frametype == ROSE_CALL_REQUEST) {
+ /* F6FBB - Remove an existing unused route */
+ rose_remove_route(rose_route);
+ break;
+ } else if (rose_route->tr2.neigh != NULL) {
+ if ((skbn = skb_copy(skb, GFP_ATOMIC)) != NULL) {
+ kfree_skb(skb, FREE_READ);
+ skb = skbn;
+ }
skb->data[0] &= 0xF0;
- skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;
- skb->data[1] = (rose_route->lci2 >> 0) & 0xFF;
- rose_transmit_link(skb, rose_route->neigh2);
+ skb->data[0] |= (rose_route->tr2.lci >> 8) & 0x0F;
+ skb->data[1] = (rose_route->tr2.lci >> 0) & 0xFF;
+ rose_transmit_link(skb, rose_route->tr2.neigh);
if (frametype == ROSE_CLEAR_CONFIRMATION)
rose_remove_route(rose_route);
return 1;
@@ -719,12 +788,20 @@
return 0;
}
}
- if (rose_route->lci2 == lci && rose_route->neigh2 == rose_neigh) {
- if (rose_route->neigh1 != NULL) {
+ if (rose_route->tr2.lci == lci && rose_route->tr2.neigh == rose_neigh) {
+ if (frametype == ROSE_CALL_REQUEST) {
+ /* F6FBB - Remove an existing unused route */
+ rose_remove_route(rose_route);
+ break;
+ } else if (rose_route->tr1.neigh != NULL) {
+ if ((skbn = skb_copy(skb, GFP_ATOMIC)) != NULL) {
+ kfree_skb(skb, FREE_READ);
+ skb = skbn;
+ }
skb->data[0] &= 0xF0;
- skb->data[0] |= (rose_route->lci1 >> 8) & 0x0F;
- skb->data[1] = (rose_route->lci1 >> 0) & 0xFF;
- rose_transmit_link(skb, rose_route->neigh1);
+ skb->data[0] |= (rose_route->tr1.lci >> 8) & 0x0F;
+ skb->data[1] = (rose_route->tr1.lci >> 0) & 0xFF;
+ rose_transmit_link(skb, rose_route->tr1.neigh);
if (frametype == ROSE_CLEAR_CONFIRMATION)
rose_remove_route(rose_route);
return 1;
@@ -741,10 +818,17 @@
* 1. The frame isn't for us,
* 2. It isn't "owned" by any existing route.
*/
- if (frametype != ROSE_CALL_REQUEST) /* XXX */
+ if (frametype != ROSE_CALL_REQUEST) { /* Trashed packet */
return 0;
+ }
- if (!rose_parse_facilities(skb, &facilities)) {
+ len = (((skb->data[3] >> 4) & 0x0F) + 1) / 2;
+ len += (((skb->data[3] >> 0) & 0x0F) + 1) / 2;
+
+ memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
+
+ if (!rose_parse_facilities(skb->data + len + 4, &facilities)) {
+ printk("CR : rose_parse_facilities error\n");
rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);
return 0;
}
@@ -757,16 +841,12 @@
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;
}
@@ -777,33 +857,38 @@
}
if ((rose_route = (struct rose_route *)kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) {
- rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120);
+ rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 121);
return 0;
}
- rose_route->lci1 = lci;
rose_route->src_addr = *src_addr;
rose_route->dest_addr = *dest_addr;
rose_route->src_call = facilities.dest_call;
rose_route->dest_call = facilities.source_call;
rose_route->rand = facilities.rand;
- rose_route->neigh1 = rose_neigh;
- rose_route->lci2 = new_lci;
- rose_route->neigh2 = new_neigh;
+ rose_route->tr1.lci = lci;
+ rose_route->tr1.neigh = rose_neigh;
+ rose_route->tr2.lci = new_lci;
+ rose_route->tr2.neigh = new_neigh;
- rose_route->neigh1->use++;
- rose_route->neigh2->use++;
+ rose_route->tr1.neigh->use++;
+ rose_route->tr2.neigh->use++;
save_flags(flags); cli();
rose_route->next = rose_route_list;
rose_route_list = rose_route;
restore_flags(flags);
+ if ((skbn = skb_copy(skb, GFP_ATOMIC)) != NULL) {
+ kfree_skb(skb, FREE_READ);
+ skb = skbn;
+ }
+
skb->data[0] &= 0xF0;
- skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;
- skb->data[1] = (rose_route->lci2 >> 0) & 0xFF;
+ skb->data[0] |= (rose_route->tr2.lci >> 8) & 0x0F;
+ skb->data[1] = (rose_route->tr2.lci >> 0) & 0xFF;
- rose_transmit_link(skb, rose_route->neigh2);
+ rose_transmit_link(skb, rose_route->tr2.neigh);
return 1;
}
@@ -920,22 +1005,22 @@
len += sprintf(buffer, "lci address callsign neigh <-> lci address callsign neigh\n");
for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) {
- if (rose_route->neigh1 != NULL) {
+ if (rose_route->tr1.neigh != NULL) {
len += sprintf(buffer + len, "%3.3X %-10s %-9s %05d ",
- rose_route->lci1,
+ rose_route->tr1.lci,
rose2asc(&rose_route->src_addr),
ax2asc(&rose_route->src_call),
- rose_route->neigh1->number);
+ rose_route->tr1.neigh->number);
} else {
len += sprintf(buffer + len, "000 * * 00000 ");
}
- if (rose_route->neigh2 != NULL) {
+ if (rose_route->tr2.neigh != NULL) {
len += sprintf(buffer + len, "%3.3X %-10s %-9s %05d\n",
- rose_route->lci2,
+ rose_route->tr2.lci,
rose2asc(&rose_route->dest_addr),
ax2asc(&rose_route->dest_call),
- rose_route->neigh2->number);
+ rose_route->tr2.neigh->number);
} else {
len += sprintf(buffer + len, "000 * * 00000\n");
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov