Commit 058f4f76 authored by Ralf Bächle's avatar Ralf Bächle

Split ax25_rt_ioctl() into several functions.

parent e2021e76
...@@ -118,81 +118,88 @@ void ax25_rt_device_down(struct net_device *dev) ...@@ -118,81 +118,88 @@ void ax25_rt_device_down(struct net_device *dev)
write_unlock(&ax25_route_lock); write_unlock(&ax25_route_lock);
} }
int ax25_rt_ioctl(unsigned int cmd, void *arg) static int ax25_rt_add(struct ax25_routes_struct *route)
{ {
ax25_route *s, *t, *ax25_rt; ax25_route *ax25_rt;
struct ax25_routes_struct route;
struct ax25_route_opt_struct rt_option;
ax25_dev *ax25_dev; ax25_dev *ax25_dev;
int i; int i;
switch (cmd) { if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
case SIOCADDRT:
if (copy_from_user(&route, arg, sizeof(route)))
return -EFAULT;
if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL)
return -EINVAL; return -EINVAL;
if (route.digi_count > AX25_MAX_DIGIS) if (route->digi_count > AX25_MAX_DIGIS)
return -EINVAL; return -EINVAL;
write_lock(ax25_route_lock); write_lock(ax25_route_lock);
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) { ax25_rt = ax25_route_list;
while (ax25_rt != NULL) {
if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 &&
ax25_rt->dev == ax25_dev->dev) {
if (ax25_rt->digipeat != NULL) { if (ax25_rt->digipeat != NULL) {
kfree(ax25_rt->digipeat); kfree(ax25_rt->digipeat);
ax25_rt->digipeat = NULL; ax25_rt->digipeat = NULL;
} }
if (route.digi_count != 0) { if (route->digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock); write_unlock(ax25_route_lock);
return -ENOMEM; return -ENOMEM;
} }
ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->lastrepeat = -1;
ax25_rt->digipeat->ndigi = route.digi_count; ax25_rt->digipeat->ndigi = route->digi_count;
for (i = 0; i < route.digi_count; i++) { for (i = 0; i < route->digi_count; i++) {
ax25_rt->digipeat->repeated[i] = 0; ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->calls[i] = route.digi_addr[i]; ax25_rt->digipeat->calls[i] = route->digi_addr[i];
} }
} }
return 0; return 0;
} }
ax25_rt = ax25_rt->next;
} }
if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) { if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock); write_unlock(ax25_route_lock);
return -ENOMEM; return -ENOMEM;
} }
ax25_rt->callsign = route.dest_addr;
ax25_rt->callsign = route->dest_addr;
ax25_rt->dev = ax25_dev->dev; ax25_rt->dev = ax25_dev->dev;
ax25_rt->digipeat = NULL; ax25_rt->digipeat = NULL;
ax25_rt->ip_mode = ' '; ax25_rt->ip_mode = ' ';
if (route.digi_count != 0) { if (route->digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock); write_unlock(ax25_route_lock);
kfree(ax25_rt); kfree(ax25_rt);
return -ENOMEM; return -ENOMEM;
} }
ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->lastrepeat = -1;
ax25_rt->digipeat->ndigi = route.digi_count; ax25_rt->digipeat->ndigi = route->digi_count;
for (i = 0; i < route.digi_count; i++) { for (i = 0; i < route->digi_count; i++) {
ax25_rt->digipeat->repeated[i] = 0; ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->calls[i] = route.digi_addr[i]; ax25_rt->digipeat->calls[i] = route->digi_addr[i];
} }
} }
ax25_rt->next = ax25_route_list; ax25_rt->next = ax25_route_list;
ax25_route_list = ax25_rt; ax25_route_list = ax25_rt;
write_unlock(ax25_route_lock); write_unlock(ax25_route_lock);
break; return 0;
}
case SIOCDELRT: static int ax25_rt_del(struct ax25_routes_struct *route)
if (copy_from_user(&route, arg, sizeof(route))) {
return -EFAULT; ax25_route *s, *t, *ax25_rt;
if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL) ax25_dev *ax25_dev;
if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
return -EINVAL; return -EINVAL;
write_lock(ax25_route_lock);
ax25_rt = ax25_route_list; ax25_rt = ax25_route_list;
while (ax25_rt != NULL) { while (ax25_rt != NULL) {
s = ax25_rt; s = ax25_rt;
ax25_rt = ax25_rt->next; ax25_rt = ax25_rt->next;
if (s->dev == ax25_dev->dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) { if (s->dev == ax25_dev->dev && ax25cmp(&route->dest_addr, &s->callsign) == 0) {
if (ax25_route_list == s) { if (ax25_route_list == s) {
ax25_route_list = s->next; ax25_route_list = s->next;
if (s->digipeat != NULL) if (s->digipeat != NULL)
...@@ -211,41 +218,76 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) ...@@ -211,41 +218,76 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
} }
} }
} }
break; write_unlock(ax25_route_lock);
case SIOCAX25OPTRT: return 0;
if (copy_from_user(&rt_option, arg, sizeof(rt_option))) }
return -EFAULT;
if ((ax25_dev = ax25_addr_ax25dev(&rt_option.port_addr)) == NULL) static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
{
ax25_route *ax25_rt;
ax25_dev *ax25_dev;
int err = 0;
if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL)
return -EINVAL; return -EINVAL;
write_lock(ax25_route_lock); write_lock(ax25_route_lock);
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25_rt->dev == ax25_dev->dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) { ax25_rt = ax25_route_list;
switch (rt_option.cmd) { while (ax25_rt != NULL) {
if (ax25_rt->dev == ax25_dev->dev &&
ax25cmp(&rt_option->dest_addr, &ax25_rt->callsign) == 0) {
switch (rt_option->cmd) {
case AX25_SET_RT_IPMODE: case AX25_SET_RT_IPMODE:
switch (rt_option.arg) { switch (rt_option->arg) {
case ' ': case ' ':
case 'D': case 'D':
case 'V': case 'V':
ax25_rt->ip_mode = rt_option.arg; ax25_rt->ip_mode = rt_option->arg;
break; break;
default: default:
return -EINVAL; err = -EINVAL;
goto out;
} }
break; break;
default: default:
return -EINVAL; err = -EINVAL;
goto out;
} }
} }
ax25_rt = ax25_rt->next;
} }
out:
write_unlock(ax25_route_lock); write_unlock(ax25_route_lock);
break; return err;
}
int ax25_rt_ioctl(unsigned int cmd, void *arg)
{
struct ax25_route_opt_struct rt_option;
struct ax25_routes_struct route;
switch (cmd) {
case SIOCADDRT:
if (copy_from_user(&route, arg, sizeof(route)))
return -EFAULT;
return ax25_rt_add(&route);
case SIOCDELRT:
if (copy_from_user(&route, arg, sizeof(route)))
return -EFAULT;
return ax25_rt_del(&route);
case SIOCAX25OPTRT:
if (copy_from_user(&rt_option, arg, sizeof(rt_option)))
return -EFAULT;
return ax25_rt_opt(&rt_option);
default: default:
return -EINVAL; return -EINVAL;
} }
return 0;
} }
int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length) int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment