/* * Find which interface to use. */ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) { ax25_route *ax25_rt; ax25_address *call; if ((ax25_rt = ax25_find_route(addr, NULL)) == NULL) return -EHOSTUNREACH; if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) return -EHOSTUNREACH; if ((call = ax25_findbyuid(current->euid)) == NULL) { if (ax25_uid_policy && !suser()) return -EPERM; call = (ax25_address *)ax25->ax25_dev->dev->dev_addr; } ax25->source_addr = *call; if (ax25_rt->digipeat != NULL) { if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) return -ENOMEM; *ax25->digipeat = *ax25_rt->digipeat; ax25_adjust_path(addr, ax25->digipeat); } if (ax25->sk != NULL) ax25->sk->zapped = 0; return 0; }
/* * Find which interface to use. */ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) { ax25_uid_assoc *user; ax25_route *ax25_rt; int err = 0; ax25_route_lock_use(); ax25_rt = ax25_get_route(addr, NULL); if (!ax25_rt) { ax25_route_lock_unuse(); return -EHOSTUNREACH; } if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) { err = -EHOSTUNREACH; goto put; } user = ax25_findbyuid(current_euid()); if (user) { ax25->source_addr = user->call; ax25_uid_put(user); } else { if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) { err = -EPERM; goto put; } ax25->source_addr = *(ax25_address *)ax25->ax25_dev->dev->dev_addr; } if (ax25_rt->digipeat != NULL) { ax25->digipeat = kmemdup(ax25_rt->digipeat, sizeof(ax25_digi), GFP_ATOMIC); if (ax25->digipeat == NULL) { err = -ENOMEM; goto put; } ax25_adjust_path(addr, ax25->digipeat); } if (ax25->sk != NULL) { bh_lock_sock(ax25->sk); sock_reset_flag(ax25->sk, SOCK_ZAPPED); bh_unlock_sock(ax25->sk); } put: ax25_route_lock_unuse(); return err; }
/* * Find which interface to use. */ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) { ax25_route *ax25_rt; ax25_address *call; int err; if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL) return -EHOSTUNREACH; if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) { err = -EHOSTUNREACH; goto put; } if ((call = ax25_findbyuid(current->euid)) == NULL) { if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) { err = -EPERM; goto put; } call = (ax25_address *)ax25->ax25_dev->dev->dev_addr; } ax25->source_addr = *call; if (ax25_rt->digipeat != NULL) { if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { err = -ENOMEM; goto put; } memcpy(ax25->digipeat, ax25_rt->digipeat, sizeof(ax25_digi)); ax25_adjust_path(addr, ax25->digipeat); } if (ax25->sk != NULL) { bh_lock_sock(ax25->sk); ax25->sk->sk_zapped = 0; bh_unlock_sock(ax25->sk); } put: ax25_put_route(ax25_rt); return 0; }
int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) { ax25_uid_assoc *s, *ax25_uid; unsigned long flags; switch (cmd) { case SIOCAX25GETUID: for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) { if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) return ax25_uid->uid; } return -ENOENT; case SIOCAX25ADDUID: if (!capable(CAP_NET_ADMIN)) return -EPERM; if (ax25_findbyuid(sax->sax25_uid)) return -EEXIST; if (sax->sax25_uid == 0) return -EINVAL; if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL) return -ENOMEM; ax25_uid->uid = sax->sax25_uid; ax25_uid->call = sax->sax25_call; save_flags(flags); cli(); ax25_uid->next = ax25_uid_list; ax25_uid_list = ax25_uid; restore_flags(flags); return 0; case SIOCAX25DELUID: if (!capable(CAP_NET_ADMIN)) return -EPERM; for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) { if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) break; } if (ax25_uid == NULL) return -ENOENT; save_flags(flags); cli(); if ((s = ax25_uid_list) == ax25_uid) { ax25_uid_list = s->next; restore_flags(flags); kfree(ax25_uid); return 0; } while (s != NULL && s->next != NULL) { if (s->next == ax25_uid) { s->next = ax25_uid->next; restore_flags(flags); kfree(ax25_uid); return 0; } s = s->next; } restore_flags(flags); return -ENOENT; default: return -EINVAL; } return -EINVAL; /*NOTREACHED */ }