Ejemplo n.º 1
0
/*
 *	Handle the ioctls that control the routing functions.
 */
int rose_rt_ioctl(unsigned int cmd, void *arg)
{
	struct rose_route_struct rose_route;
	struct net_device *dev;
	int err;

	switch (cmd) {

		case SIOCADDRT:
			if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
				return -EFAULT;
			if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
				return -EINVAL;
			if (rose_dev_exists(&rose_route.address)) { /* Can't add routes to ourself */
				dev_put(dev);
				return -EINVAL;
			}
			if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
				return -EINVAL;
			if (rose_route.ndigis > AX25_MAX_DIGIS)
				return -EINVAL;

			err = rose_add_node(&rose_route, dev);
			dev_put(dev);
			return err;

		case SIOCDELRT:
			if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
				return -EFAULT;
			if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
				return -EINVAL;
			err = rose_del_node(&rose_route, dev);
			dev_put(dev);
			return err;
				

		case SIOCRSCLRRT:
			return rose_clear_routes();

		default:
			return -EINVAL;
	}

	return 0;
}
Ejemplo n.º 2
0
/*
 *	Handle the ioctls that control the routing functions.
 */
int rose_rt_ioctl(unsigned int cmd, void *arg)
{
	struct rose_route_struct rose_route;
	struct device *dev;
	int err;

	switch (cmd) {

		case SIOCADDRT:
			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct rose_route_struct))) != 0)
				return err;
			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_route.mask > 10) /* Mask can't be more than 10 digits */
				return -EINVAL;

			return rose_add_node(&rose_route, dev);

		case SIOCDELRT:
			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct rose_route_struct))) != 0)
				return err;
			memcpy_fromfs(&rose_route, arg, sizeof(struct rose_route_struct));
			if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
				return -EINVAL;
			return rose_del_node(&rose_route, dev);

		case SIOCRSCLRRT:
			return rose_clear_routes();

		default:
			return -EINVAL;
	}

	return 0;
}
Ejemplo n.º 3
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;
}