X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fnetrom%2Faf_netrom.c;h=3669cb953e6e7d49c05eb82c39ba1d43e80f9e3d;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=6774669bb212c924748b41ea417caae26abfff3b;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 6774669bb..3669cb953 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -39,11 +40,11 @@ #include #include #include -#include +#include #include #include -int nr_ndevs = 4; +static int nr_ndevs = 4; int sysctl_netrom_default_path_quality = NR_DEFAULT_QUAL; int sysctl_netrom_obsolescence_count_initialiser = NR_DEFAULT_OBS; @@ -56,36 +57,14 @@ int sysctl_netrom_transport_requested_window_size = NR_DEFAULT_WINDOW; int sysctl_netrom_transport_no_activity_timeout = NR_DEFAULT_IDLE; int sysctl_netrom_routing_control = NR_DEFAULT_ROUTING; int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS; +int sysctl_netrom_reset_circuit = NR_DEFAULT_RESET; static unsigned short circuit = 0x101; static HLIST_HEAD(nr_list); -static spinlock_t nr_list_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(nr_list_lock); -static struct proto_ops nr_proto_ops; -void nr_init_timers(struct sock *sk); - -static struct sock *nr_alloc_sock(void) -{ - nr_cb *nr; - struct sock *sk = sk_alloc(PF_NETROM, GFP_ATOMIC, 1, NULL); - - if (!sk) - goto out; - - nr = sk->sk_protinfo = kmalloc(sizeof(*nr), GFP_ATOMIC); - if (!nr) - goto frees; - - memset(nr, 0x00, sizeof(*nr)); - nr->sk = sk; -out: - return sk; -frees: - sk_free(sk); - sk = NULL; - goto out; -} +static const struct proto_ops nr_proto_ops; /* * Socket removal during an interrupt is now safe. @@ -170,7 +149,7 @@ static struct sock *nr_find_socket(unsigned char index, unsigned char id) spin_lock_bh(&nr_list_lock); sk_for_each(s, node, &nr_list) { - nr_cb *nr = nr_sk(s); + struct nr_sock *nr = nr_sk(s); if (nr->my_index == index && nr->my_id == id) { bh_lock_sock(s); @@ -194,7 +173,7 @@ static struct sock *nr_find_peer(unsigned char index, unsigned char id, spin_lock_bh(&nr_list_lock); sk_for_each(s, node, &nr_list) { - nr_cb *nr = nr_sk(s); + struct nr_sock *nr = nr_sk(s); if (nr->your_index == index && nr->your_id == id && !ax25cmp(&nr->dest_addr, dest)) { @@ -301,7 +280,7 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) { struct sock *sk = sock->sk; - nr_cb *nr = nr_sk(sk); + struct nr_sock *nr = nr_sk(sk); int opt; if (level != SOL_NETROM) @@ -353,7 +332,7 @@ static int nr_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; - nr_cb *nr = nr_sk(sk); + struct nr_sock *nr = nr_sk(sk); int val = 0; int len; @@ -416,21 +395,26 @@ static int nr_listen(struct socket *sock, int backlog) return -EOPNOTSUPP; } +static struct proto nr_proto = { + .name = "NETROM", + .owner = THIS_MODULE, + .obj_size = sizeof(struct nr_sock), +}; + static int nr_create(struct socket *sock, int protocol) { struct sock *sk; - nr_cb *nr; + struct nr_sock *nr; if (sock->type != SOCK_SEQPACKET || protocol != 0) return -ESOCKTNOSUPPORT; - if ((sk = nr_alloc_sock()) == NULL) + if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL) return -ENOMEM; nr = nr_sk(sk); sock_init_data(sock, sk); - sk_set_owner(sk, THIS_MODULE); sock->ops = &nr_proto_ops; sk->sk_protocol = protocol; @@ -441,11 +425,16 @@ static int nr_create(struct socket *sock, int protocol) nr_init_timers(sk); - nr->t1 = sysctl_netrom_transport_timeout; - nr->t2 = sysctl_netrom_transport_acknowledge_delay; - nr->n2 = sysctl_netrom_transport_maximum_tries; - nr->t4 = sysctl_netrom_transport_busy_delay; - nr->idle = sysctl_netrom_transport_no_activity_timeout; + nr->t1 = + msecs_to_jiffies(sysctl_netrom_transport_timeout); + nr->t2 = + msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay); + nr->n2 = + msecs_to_jiffies(sysctl_netrom_transport_maximum_tries); + nr->t4 = + msecs_to_jiffies(sysctl_netrom_transport_busy_delay); + nr->idle = + msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout); nr->window = sysctl_netrom_transport_requested_window_size; nr->bpqext = 1; @@ -457,18 +446,17 @@ static int nr_create(struct socket *sock, int protocol) static struct sock *nr_make_new(struct sock *osk) { struct sock *sk; - nr_cb *nr, *onr; + struct nr_sock *nr, *onr; if (osk->sk_type != SOCK_SEQPACKET) return NULL; - if ((sk = nr_alloc_sock()) == NULL) + if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL) return NULL; nr = nr_sk(sk); sock_init_data(NULL, sk); - sk_set_owner(sk, THIS_MODULE); sk->sk_type = osk->sk_type; sk->sk_socket = osk->sk_socket; @@ -476,10 +464,9 @@ static struct sock *nr_make_new(struct sock *osk) sk->sk_protocol = osk->sk_protocol; sk->sk_rcvbuf = osk->sk_rcvbuf; sk->sk_sndbuf = osk->sk_sndbuf; - sk->sk_debug = osk->sk_debug; sk->sk_state = TCP_ESTABLISHED; sk->sk_sleep = osk->sk_sleep; - sk->sk_zapped = osk->sk_zapped; + sock_copy_flags(sk, osk); skb_queue_head_init(&nr->ack_queue); skb_queue_head_init(&nr->reseq_queue); @@ -505,7 +492,7 @@ static struct sock *nr_make_new(struct sock *osk) static int nr_release(struct socket *sock) { struct sock *sk = sock->sk; - nr_cb *nr; + struct nr_sock *nr; if (sk == NULL) return 0; @@ -553,13 +540,14 @@ static int nr_release(struct socket *sock) static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; - nr_cb *nr = nr_sk(sk); + struct nr_sock *nr = nr_sk(sk); struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; struct net_device *dev; - ax25_address *user, *source; + ax25_uid_assoc *user; + ax25_address *source; lock_sock(sk); - if (!sk->sk_zapped) { + if (!sock_flag(sk, SOCK_ZAPPED)) { release_sock(sk); return -EINVAL; } @@ -595,23 +583,26 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) } else { source = &addr->fsa_ax25.sax25_call; - if ((user = ax25_findbyuid(current->euid)) == NULL) { + user = ax25_findbyuid(current->euid); + if (user) { + nr->user_addr = user->call; + ax25_uid_put(user); + } else { if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) { release_sock(sk); dev_put(dev); return -EPERM; } - user = source; + nr->user_addr = *source; } - nr->user_addr = *user; nr->source_addr = *source; } nr->device = dev; nr_insert_socket(sk); - sk->sk_zapped = 0; + sock_reset_flag(sk, SOCK_ZAPPED); dev_put(dev); release_sock(sk); SOCK_DEBUG(sk, "NET/ROM: socket is bound\n"); @@ -622,9 +613,10 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { struct sock *sk = sock->sk; - nr_cb *nr = nr_sk(sk); + struct nr_sock *nr = nr_sk(sk); struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr; - ax25_address *user, *source = NULL; + ax25_address *source = NULL; + ax25_uid_assoc *user; struct net_device *dev; lock_sock(sk); @@ -656,8 +648,8 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, release_sock(sk); return -EINVAL; } - if (sk->sk_zapped) { /* Must bind first - autobinding in this may or may not work */ - sk->sk_zapped = 0; + if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */ + sock_reset_flag(sk, SOCK_ZAPPED); if ((dev = nr_dev_first()) == NULL) { release_sock(sk); @@ -665,16 +657,19 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, } source = (ax25_address *)dev->dev_addr; - if ((user = ax25_findbyuid(current->euid)) == NULL) { + user = ax25_findbyuid(current->euid); + if (user) { + nr->user_addr = user->call; + ax25_uid_put(user); + } else { if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) { dev_put(dev); release_sock(sk); return -EPERM; } - user = source; + nr->user_addr = *source; } - nr->user_addr = *user; nr->source_addr = *source; nr->device = dev; @@ -801,7 +796,6 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) remove_wait_queue(sk->sk_sleep, &wait); newsk = skb->sk; - newsk->sk_pair = NULL; newsk->sk_socket = newsock; newsk->sk_sleep = &newsock->wait; @@ -820,7 +814,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr, { struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr; struct sock *sk = sock->sk; - nr_cb *nr = nr_sk(sk); + struct nr_sock *nr = nr_sk(sk); lock_sock(sk); if (peer != 0) { @@ -848,7 +842,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) { struct sock *sk; struct sock *make; - nr_cb *nr_make; + struct nr_sock *nr_make; ax25_address *src, *dest, *user; unsigned short circuit_index, circuit_id; unsigned short peer_circuit_index, peer_circuit_id; @@ -871,17 +865,16 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) frametype = skb->data[19] & 0x0F; flags = skb->data[19] & 0xF0; -#ifdef CONFIG_INET /* * Check for an incoming IP over NET/ROM frame. */ - if (frametype == NR_PROTOEXT && circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) { + if (frametype == NR_PROTOEXT && + circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) { skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); skb->h.raw = skb->data; return nr_rx_ip(skb, dev); } -#endif /* * Find an existing socket connection, based on circuit ID, if it's @@ -922,17 +915,17 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) if (frametype != NR_CONNREQ) { /* * Here it would be nice to be able to send a reset but - * NET/ROM doesn't have one. The following hack would - * have been a way to extend the protocol but apparently - * it kills BPQ boxes... :-( - */ -#if 0 - /* - * Never reply to a CONNACK/CHOKE. + * NET/ROM doesn't have one. We've tried to extend the protocol + * by sending NR_CONNACK | NR_CHOKE_FLAGS replies but that + * apparently kills BPQ boxes... :-( + * So now we try to follow the established behaviour of + * G8PZT's Xrouter which is sending packets with command type 7 + * as an extension of the protocol. */ - if (frametype != NR_CONNACK || flags != NR_CHOKE_FLAG) - nr_transmit_refusal(skb, 1); -#endif + if (sysctl_netrom_reset_circuit && + (frametype != NR_RESET || flags != 0)) + nr_transmit_reset(skb, 1); + return 0; } @@ -940,7 +933,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) user = (ax25_address *)(skb->data + 21); - if (!sk || sk->sk_ack_backlog == sk->sk_max_ack_backlog || + if (sk == NULL || sk_acceptq_is_full(sk) || (make = nr_make_new(sk)) == NULL) { nr_transmit_refusal(skb, 0); if (sk) @@ -994,7 +987,6 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) nr_make->vl = 0; nr_make->state = NR_STATE_3; sk->sk_ack_backlog++; - make->sk_pair = sk; nr_insert_socket(make); @@ -1014,7 +1006,7 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - nr_cb *nr = nr_sk(sk); + struct nr_sock *nr = nr_sk(sk); struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; int err; struct sockaddr_ax25 sax; @@ -1026,7 +1018,7 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, return -EINVAL; lock_sock(sk); - if (sk->sk_zapped) { + if (sock_flag(sk, SOCK_ZAPPED)) { err = -EADDRNOTAVAIL; goto out; } @@ -1180,10 +1172,11 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int ret; - lock_sock(sk); switch (cmd) { case TIOCOUTQ: { long amount; + + lock_sock(sk); amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); if (amount < 0) amount = 0; @@ -1194,6 +1187,8 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case TIOCINQ: { struct sk_buff *skb; long amount = 0L; + + lock_sock(sk); /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) amount = skb->len; @@ -1202,9 +1197,8 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } case SIOCGSTAMP: - ret = -EINVAL; - if (sk != NULL) - ret = sock_get_timestamp(sk, argp); + lock_sock(sk); + ret = sock_get_timestamp(sk, argp); release_sock(sk); return ret; @@ -1218,21 +1212,17 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCSIFNETMASK: case SIOCGIFMETRIC: case SIOCSIFMETRIC: - release_sock(sk); return -EINVAL; case SIOCADDRT: case SIOCDELRT: case SIOCNRDECOBS: - release_sock(sk); if (!capable(CAP_NET_ADMIN)) return -EPERM; return nr_rt_ioctl(cmd, argp); default: - release_sock(sk); - return dev_ioctl(cmd, argp); + return -ENOIOCTLCMD; } - release_sock(sk); return 0; } @@ -1274,8 +1264,9 @@ static int nr_info_show(struct seq_file *seq, void *v) { struct sock *s = v; struct net_device *dev; - nr_cb *nr; + struct nr_sock *nr; const char *devname; + char buf[11]; if (v == SEQ_START_TOKEN) seq_puts(seq, @@ -1291,11 +1282,11 @@ static int nr_info_show(struct seq_file *seq, void *v) else devname = dev->name; - seq_printf(seq, "%-9s ", ax2asc(&nr->user_addr)); - seq_printf(seq, "%-9s ", ax2asc(&nr->dest_addr)); + seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr)); + seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr)); seq_printf(seq, "%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %ld\n", - ax2asc(&nr->source_addr), + ax2asc(buf, &nr->source_addr), devname, nr->my_index, nr->my_id, @@ -1352,7 +1343,7 @@ static struct net_proto_family nr_family_ops = { .owner = THIS_MODULE, }; -static struct proto_ops nr_proto_ops = { +static const struct proto_ops nr_proto_ops = { .family = PF_NETROM, .owner = THIS_MODULE, .release = nr_release, @@ -1379,11 +1370,13 @@ static struct notifier_block nr_dev_notifier = { static struct net_device **dev_nr; -static char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n"; - static int __init nr_proto_init(void) { int i; + int rc = proto_register(&nr_proto, 0); + + if (rc != 0) + goto out; if (nr_ndevs > 0x7fffffff/sizeof(struct net_device *)) { printk(KERN_ERR "NET/ROM: nr_proto_init - nr_ndevs parameter to large\n"); @@ -1403,8 +1396,7 @@ static int __init nr_proto_init(void) struct net_device *dev; sprintf(name, "nr%d", i); - dev = alloc_netdev(sizeof(struct net_device_stats), name, - nr_setup); + dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup); if (!dev) { printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); goto fail; @@ -1425,7 +1417,6 @@ static int __init nr_proto_init(void) } register_netdevice_notifier(&nr_dev_notifier); - printk(banner); ax25_protocol_register(AX25_P_NETROM, nr_route_frame); ax25_linkfail_register(nr_link_failed); @@ -1439,15 +1430,17 @@ static int __init nr_proto_init(void) proc_net_fops_create("nr", S_IRUGO, &nr_info_fops); proc_net_fops_create("nr_neigh", S_IRUGO, &nr_neigh_fops); proc_net_fops_create("nr_nodes", S_IRUGO, &nr_nodes_fops); - return 0; - - fail: +out: + return rc; +fail: while (--i >= 0) { unregister_netdev(dev_nr[i]); free_netdev(dev_nr[i]); } kfree(dev_nr); - return -1; + proto_unregister(&nr_proto); + rc = -1; + goto out; } module_init(nr_proto_init); @@ -1491,5 +1484,6 @@ static void __exit nr_exit(void) } kfree(dev_nr); + proto_unregister(&nr_proto); } module_exit(nr_exit);