Example #1
0
/*
 *	Find a neighbour given a ROSE address.
 */
struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, unsigned char *diagnostic)
{
	struct rose_node *node;
	int failed = 0;
	int i;

	for (node = rose_node_list; node != NULL; node = node->next) {
		if (rosecmpm(addr, &node->address, node->mask) == 0) {
			for (i = 0; i < node->count; i++) {
				if (node->neighbour[i]->ftimer == 0)
					return node->neighbour[i];
				else
					failed = 1;
			}
			/* do not accept other node address */
			break;
		}
	}

	if (failed) {
		*cause      = ROSE_OUT_OF_ORDER;
		*diagnostic = 0;
	} else {
		*cause      = ROSE_NOT_OBTAINABLE;
		*diagnostic = 0;
	}

	return NULL;
}
Example #2
0
/*
 *	Find a neighbour given a ROSE address.
 */
struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
                                  unsigned char *diagnostic)
{
    struct rose_neigh *res = NULL;
    struct rose_node *node;
    int failed = 0;
    int i;

    spin_lock_bh(&rose_node_list_lock);
    for (node = rose_node_list; node != NULL; node = node->next) {
        if (rosecmpm(addr, &node->address, node->mask) == 0) {
            for (i = 0; i < node->count; i++) {
                if (!rose_ftimer_running(node->neighbour[i])) {
                    res = node->neighbour[i];
                    goto out;
                } else
                    failed = 1;
            }
            break;
        }
    }

    if (failed) {
        *cause      = ROSE_OUT_OF_ORDER;
        *diagnostic = 0;
    } else {
        *cause      = ROSE_NOT_OBTAINABLE;
        *diagnostic = 0;
    }

out:
    spin_unlock_bh(&rose_node_list_lock);

    return res;
}
Example #3
0
/*
 *	Delete a loopback node.
 */
void rose_del_loopback_node(rose_address *address)
{
    struct rose_node *rose_node;

    spin_lock_bh(&rose_node_list_lock);

    rose_node = rose_node_list;
    while (rose_node != NULL) {
        if ((rose_node->mask == 10) &&
                (rosecmpm(address, &rose_node->address, 10) == 0) &&
                rose_node->loopback)
            break;
        rose_node = rose_node->next;
    }

    if (rose_node == NULL)
        goto out;

    rose_remove_node(rose_node);

    rose_loopback_neigh->count--;

out:
    spin_unlock_bh(&rose_node_list_lock);
}
Example #4
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;

	/* Insert at the head of list. Address is always mask=10 */
	save_flags(flags); cli();
	rose_node->next = rose_node_list;
	rose_node_list  = rose_node;
	restore_flags(flags);

	rose_loopback_neigh->count++;

	return 0;
}
Example #5
0
/*
 *	"Delete" a node. Strictly speaking remove a route to a node. The node
 *	is only deleted if no routes are left to it.
 */
static int rose_del_node(struct rose_route_struct *rose_route, struct device *dev)
{
	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)
		if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0))
			break;

	if (rose_node == NULL) 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;

	if (rose_neigh == NULL) return -EINVAL;

	for (i = 0; i < rose_node->count; i++) {
		if (rose_node->neighbour[i] == rose_neigh) {
			rose_neigh->count--;

			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--;

			if (rose_node->count == 0) {
				rose_remove_node(rose_node);
			} else {
				switch (i) {
					case 0:
						rose_node->neighbour[0] = rose_node->neighbour[1];
					case 1:
						rose_node->neighbour[1] = rose_node->neighbour[2];
					case 2:
						break;
				}
			}

			return 0;
		}
	}

	return -EINVAL;
}
Example #6
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--;
}
Example #7
0
/*
 *	"Delete" a node. Strictly speaking remove a route to a node. The node
 *	is only deleted if no routes are left to it.
 */
static int rose_del_node(struct rose_route_struct *rose_route, struct net_device *dev)
{
	struct rose_node  *rose_node;
	struct rose_neigh *rose_neigh;
	int i;

	for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next)
		if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0))
			break;

	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;

	if (rose_neigh == NULL) return -EINVAL;

	for (i = 0; i < rose_node->count; i++) {
		if (rose_node->neighbour[i] == rose_neigh) {
			rose_neigh->count--;

			if (rose_neigh->count == 0 && rose_neigh->use == 0)
				rose_remove_neigh(rose_neigh);

			rose_node->count--;

			if (rose_node->count == 0) {
				rose_remove_node(rose_node);
			} else {
				switch (i) {
					case 0:
						rose_node->neighbour[0] = rose_node->neighbour[1];
					case 1:
						rose_node->neighbour[1] = rose_node->neighbour[2];
					case 2:
						break;
				}
			}

			return 0;
		}
	}

	return -EINVAL;
}
Example #8
0
/*
 *	Add a loopback node.
 */
int rose_add_loopback_node(rose_address *address)
{
    struct rose_node *rose_node;
    unsigned int err = 0;

    spin_lock_bh(&rose_node_list_lock);

    rose_node = rose_node_list;
    while (rose_node != NULL) {
        if ((rose_node->mask == 10) &&
                (rosecmpm(address, &rose_node->address, 10) == 0) &&
                rose_node->loopback)
            break;
        rose_node = rose_node->next;
    }

    if (rose_node != NULL)
        goto out;

    if ((rose_node = kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL) {
        err = -ENOMEM;
        goto out;
    }

    rose_node->address      = *address;
    rose_node->mask         = 10;
    rose_node->count        = 1;
    rose_node->loopback     = 1;
    rose_node->neighbour[0] = rose_loopback_neigh;

    /* Insert at the head of list. Address is always mask=10 */
    rose_node->next = rose_node_list;
    rose_node_list  = rose_node;

    rose_loopback_neigh->count++;

out:
    spin_unlock_bh(&rose_node_list_lock);

    return 0;
}
Example #9
0
/*
 *	Add a new route to a node, and in the process add the node and the
 *	neighbour if it is new.
 */
static int rose_add_node(struct rose_route_struct *rose_route,
                         struct net_device *dev)
{
    struct rose_node  *rose_node, *rose_tmpn, *rose_tmpp;
    struct rose_neigh *rose_neigh;
    int i, res = 0;

    spin_lock_bh(&rose_node_list_lock);
    spin_lock_bh(&rose_neigh_list_lock);

    rose_node = rose_node_list;
    while (rose_node != NULL) {
        if ((rose_node->mask == rose_route->mask) &&
                (rosecmpm(&rose_route->address, &rose_node->address,
                          rose_route->mask) == 0))
            break;
        rose_node = rose_node->next;
    }

    if (rose_node != NULL && rose_node->loopback) {
        res = -EINVAL;
        goto out;
    }

    rose_neigh = rose_neigh_list;
    while (rose_neigh != NULL) {
        if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0
                && rose_neigh->dev == dev)
            break;
        rose_neigh = rose_neigh->next;
    }

    if (rose_neigh == NULL) {
        rose_neigh = kmalloc(sizeof(*rose_neigh), GFP_ATOMIC);
        if (rose_neigh == NULL) {
            res = -ENOMEM;
            goto out;
        }

        rose_neigh->callsign  = rose_route->neighbour;
        rose_neigh->digipeat  = NULL;
        rose_neigh->ax25      = NULL;
        rose_neigh->dev       = dev;
        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;

        skb_queue_head_init(&rose_neigh->queue);

        init_timer(&rose_neigh->ftimer);
        init_timer(&rose_neigh->t0timer);

        if (rose_route->ndigis != 0) {
            if ((rose_neigh->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
                kfree(rose_neigh);
                res = -ENOMEM;
                goto out;
            }

            rose_neigh->digipeat->ndigi      = rose_route->ndigis;
            rose_neigh->digipeat->lastrepeat = -1;

            for (i = 0; i < rose_route->ndigis; i++) {
                rose_neigh->digipeat->calls[i]    =
                    rose_route->digipeaters[i];
                rose_neigh->digipeat->repeated[i] = 0;
            }
        }

        rose_neigh->next = rose_neigh_list;
        rose_neigh_list  = rose_neigh;
    }

    /*
     * This is a new node to be inserted into the list. Find where it needs
     * to be inserted into the list, and insert it. We want to be sure
     * to order the list in descending order of mask size to ensure that
     * later when we are searching this list the first match will be the
     * best match.
     */
    if (rose_node == NULL) {
        rose_tmpn = rose_node_list;
        rose_tmpp = NULL;

        while (rose_tmpn != NULL) {
            if (rose_tmpn->mask > rose_route->mask) {
                rose_tmpp = rose_tmpn;
                rose_tmpn = rose_tmpn->next;
            } else {
                break;
            }
        }

        /* create new node */
        rose_node = kmalloc(sizeof(*rose_node), GFP_ATOMIC);
        if (rose_node == NULL) {
            res = -ENOMEM;
            goto out;
        }

        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;

        if (rose_tmpn == NULL) {
            if (rose_tmpp == NULL) {	/* Empty list */
                rose_node_list  = rose_node;
                rose_node->next = NULL;
            } else {
                rose_tmpp->next = rose_node;
                rose_node->next = NULL;
            }
        } else {
            if (rose_tmpp == NULL) {	/* 1st node */
                rose_node->next = rose_node_list;
                rose_node_list  = rose_node;
            } else {
                rose_tmpp->next = rose_node;
                rose_node->next = rose_tmpn;
            }
        }
        rose_neigh->count++;

        goto out;
    }

    /* We have space, slot it in */
    if (rose_node->count < 3) {
        rose_node->neighbour[rose_node->count] = rose_neigh;
        rose_node->count++;
        rose_neigh->count++;
    }

out:
    spin_unlock_bh(&rose_neigh_list_lock);
    spin_unlock_bh(&rose_node_list_lock);

    return res;
}
Example #10
0
/*
 *	"Delete" a node. Strictly speaking remove a route to a node. The node
 *	is only deleted if no routes are left to it.
 */
static int rose_del_node(struct rose_route_struct *rose_route,
                         struct net_device *dev)
{
    struct rose_node  *rose_node;
    struct rose_neigh *rose_neigh;
    int i, err = 0;

    spin_lock_bh(&rose_node_list_lock);
    spin_lock_bh(&rose_neigh_list_lock);

    rose_node = rose_node_list;
    while (rose_node != NULL) {
        if ((rose_node->mask == rose_route->mask) &&
                (rosecmpm(&rose_route->address, &rose_node->address,
                          rose_route->mask) == 0))
            break;
        rose_node = rose_node->next;
    }

    if (rose_node == NULL || rose_node->loopback) {
        err = -EINVAL;
        goto out;
    }

    rose_neigh = rose_neigh_list;
    while (rose_neigh != NULL) {
        if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0
                && rose_neigh->dev == dev)
            break;
        rose_neigh = rose_neigh->next;
    }

    if (rose_neigh == NULL) {
        err = -EINVAL;
        goto out;
    }

    for (i = 0; i < rose_node->count; i++) {
        if (rose_node->neighbour[i] == rose_neigh) {
            rose_neigh->count--;

            if (rose_neigh->count == 0 && rose_neigh->use == 0)
                rose_remove_neigh(rose_neigh);

            rose_node->count--;

            if (rose_node->count == 0) {
                rose_remove_node(rose_node);
            } else {
                switch (i) {
                case 0:
                    rose_node->neighbour[0] =
                        rose_node->neighbour[1];
                case 1:
                    rose_node->neighbour[1] =
                        rose_node->neighbour[2];
                case 2:
                    break;
                }
            }
            goto out;
        }
    }
    err = -EINVAL;

out:
    spin_unlock_bh(&rose_neigh_list_lock);
    spin_unlock_bh(&rose_node_list_lock);

    return err;
}
Example #11
0
/*
 *	Add a new route to a node, and in the process add the node and the
 *	neighbour if it is new.
 */
static int rose_add_node(struct rose_route_struct *rose_route, struct device *dev)
{
	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;

	for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next)
		if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0))
			break;

	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;

	if (rose_neigh == NULL) {
		if ((rose_neigh = (struct rose_neigh *)kmalloc(sizeof(*rose_neigh), GFP_ATOMIC)) == NULL)
			return -ENOMEM;

		rose_neigh->callsign  = rose_route->neighbour;
		rose_neigh->digipeat  = NULL;
		rose_neigh->ax25      = NULL;
		rose_neigh->dev       = dev;
		rose_neigh->count     = 0;
		rose_neigh->use       = 0;
		rose_neigh->dce_mode  = 0;
		rose_neigh->number    = rose_neigh_no++;
		rose_neigh->restarted = 0;
		skb_queue_head_init(&rose_neigh->queue);
		rose_neigh->t0timer   = 0;
		rose_neigh->ftimer    = 0;
		init_timer(&rose_neigh->timer);

		if (rose_route->ndigis != 0) {
			if ((rose_neigh->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
				kfree_s(rose_neigh, sizeof(*rose_neigh));
				return -ENOMEM;
			}

			rose_neigh->digipeat->ndigi      = rose_route->ndigis;
			rose_neigh->digipeat->lastrepeat = -1;

			for (i = 0; i < rose_route->ndigis; i++) {
				rose_neigh->digipeat->calls[i]    = rose_route->digipeaters[i];
				rose_neigh->digipeat->repeated[i] = 0;
			}
		}

		save_flags(flags); cli();
		rose_neigh->next = rose_neigh_list;
		rose_neigh_list  = rose_neigh;
		restore_flags(flags);
	}

	/*
	 * This is a new node to be inserted into the list. Find where it needs
	 * to be inserted into the list, and insert it. We want to be sure
	 * to order the list in descending order of mask size to ensure that
	 * later when we are searching this list the first match will be the
	 * best match.
	 */
	if (rose_node == NULL) {
		rose_tmpn = rose_node_list;
		rose_tmpp = NULL;

		while (rose_tmpn != NULL) {
			if (rose_tmpn->mask > rose_route->mask) {
				rose_tmpp = rose_tmpn;
				rose_tmpn = rose_tmpn->next;
			} else {
				break;
			}
		}

		/* create new node */
		if ((rose_node = (struct rose_node *)kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL)
			return -ENOMEM;

		rose_node->address = rose_route->address;
		rose_node->mask    = rose_route->mask;
		rose_node->count   = 1;
		rose_node->neighbour[0] = rose_neigh;

		save_flags(flags); cli();

		if (rose_tmpn == NULL) {
			if (rose_tmpp == NULL) {	/* Empty list */
				rose_node_list  = rose_node;
				rose_node->next = NULL;
			} else {
				rose_tmpp->next = rose_node;
				rose_node->next = NULL;
			}
		} else {
			if (rose_tmpp == NULL) {	/* 1st node */
				rose_node->next = rose_node_list;
				rose_node_list  = rose_node;
			} else {
				rose_tmpp->next = rose_node;
				rose_node->next = rose_tmpn;
			}
		}

		restore_flags(flags);

		rose_neigh->count++;

	} 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;
}