X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fnetrom%2Faf_netrom.c;h=3be0e016ab7df1bd34576816c1ea97232c36c7e8;hb=9d2a3f31d6d7832cd441eeda08bc2266cdd5d972;hp=9ee672e19ec160e368829eee7121ff403f9e7a10;hpb=5ff7630e4aa6c3969094dc30ff1cdaa6f52b0ed0;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 9ee672e..3be0e01 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -8,9 +8,9 @@ * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk) * Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk) */ -#include #include #include +#include #include #include #include @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,28 @@ static DEFINE_SPINLOCK(nr_list_lock); static const struct proto_ops nr_proto_ops; /* + * NETROM network devices are virtual network devices encapsulating NETROM + * frames into AX.25 which will be sent through an AX.25 device, so form a + * special "super class" of normal net devices; split their locks off into a + * separate class since they always nest. + */ +static struct lock_class_key nr_netdev_xmit_lock_key; +static struct lock_class_key nr_netdev_addr_lock_key; + +static void nr_set_lockdep_one(struct net_device *dev, + struct netdev_queue *txq, + void *_unused) +{ + lockdep_set_class(&txq->_xmit_lock, &nr_netdev_xmit_lock_key); +} + +static void nr_set_lockdep_key(struct net_device *dev) +{ + lockdep_set_class(&dev->addr_list_lock, &nr_netdev_addr_lock_key); + netdev_for_each_tx_queue(dev, nr_set_lockdep_one, NULL); +} + +/* * Socket removal during an interrupt is now safe. */ static void nr_remove_socket(struct sock *sk) @@ -97,12 +120,15 @@ static int nr_device_event(struct notifier_block *this, unsigned long event, voi { struct net_device *dev = (struct net_device *)ptr; + if (!net_eq(dev_net(dev), &init_net)) + return NOTIFY_DONE; + if (event != NETDEV_DOWN) return NOTIFY_DONE; nr_kill_by_device(dev); nr_rt_device_down(dev); - + return NOTIFY_DONE; } @@ -129,7 +155,7 @@ static struct sock *nr_find_listener(ax25_address *addr) sk_for_each(s, node, &nr_list) if (!ax25cmp(&nr_sk(s)->source_addr, addr) && s->sk_state == TCP_LISTEN) { - bh_lock_sock(s); + bh_lock_sock(s); goto found; } s = NULL; @@ -149,7 +175,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) { struct nr_sock *nr = nr_sk(s); - + if (nr->my_index == index && nr->my_id == id) { bh_lock_sock(s); goto found; @@ -173,10 +199,10 @@ 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) { struct nr_sock *nr = nr_sk(s); - + if (nr->your_index == index && nr->your_id == id && !ax25cmp(&nr->dest_addr, dest)) { - bh_lock_sock(s); + bh_lock_sock(s); goto found; } } @@ -333,17 +359,17 @@ static int nr_getsockopt(struct socket *sock, int level, int optname, struct sock *sk = sock->sk; struct nr_sock *nr = nr_sk(sk); int val = 0; - int len; + int len; if (level != SOL_NETROM) return -ENOPROTOOPT; - + if (get_user(len, optlen)) return -EFAULT; if (len < 0) return -EINVAL; - + switch (optname) { case NETROM_T1: val = nr->t1 / HZ; @@ -400,15 +426,19 @@ static struct proto nr_proto = { .obj_size = sizeof(struct nr_sock), }; -static int nr_create(struct socket *sock, int protocol) +static int nr_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct nr_sock *nr; + if (net != &init_net) + return -EAFNOSUPPORT; + if (sock->type != SOCK_SEQPACKET || protocol != 0) return -ESOCKTNOSUPPORT; - if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL) + sk = sk_alloc(net, PF_NETROM, GFP_ATOMIC, &nr_proto); + if (sk == NULL) return -ENOMEM; nr = nr_sk(sk); @@ -424,11 +454,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; @@ -445,7 +480,8 @@ static struct sock *nr_make_new(struct sock *osk) if (osk->sk_type != SOCK_SEQPACKET) return NULL; - if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL) + sk = sk_alloc(sock_net(osk), PF_NETROM, GFP_ATOMIC, osk->sk_prot); + if (sk == NULL) return NULL; nr = nr_sk(sk); @@ -453,13 +489,11 @@ static struct sock *nr_make_new(struct sock *osk) sock_init_data(NULL, sk); sk->sk_type = osk->sk_type; - sk->sk_socket = osk->sk_socket; sk->sk_priority = osk->sk_priority; sk->sk_protocol = osk->sk_protocol; sk->sk_rcvbuf = osk->sk_rcvbuf; sk->sk_sndbuf = osk->sk_sndbuf; sk->sk_state = TCP_ESTABLISHED; - sk->sk_sleep = osk->sk_sleep; sock_copy_flags(sk, osk); skb_queue_head_init(&nr->ack_queue); @@ -491,6 +525,7 @@ static int nr_release(struct socket *sock) if (sk == NULL) return 0; sock_hold(sk); + sock_orphan(sk); lock_sock(sk); nr = nr_sk(sk); @@ -514,17 +549,14 @@ static int nr_release(struct socket *sock) sk->sk_state = TCP_CLOSE; sk->sk_shutdown |= SEND_SHUTDOWN; sk->sk_state_change(sk); - sock_orphan(sk); sock_set_flag(sk, SOCK_DESTROY); - sk->sk_socket = NULL; break; default: - sk->sk_socket = NULL; break; } - sock->sk = NULL; + sock->sk = NULL; release_sock(sk); sock_put(sk); @@ -577,7 +609,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) } else { source = &addr->fsa_ax25.sax25_call; - user = ax25_findbyuid(current->euid); + user = ax25_findbyuid(current_euid()); if (user) { nr->user_addr = user->call; ax25_uid_put(user); @@ -612,54 +644,54 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, ax25_address *source = NULL; ax25_uid_assoc *user; struct net_device *dev; + int err = 0; lock_sock(sk); if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { sock->state = SS_CONNECTED; - release_sock(sk); - return 0; /* Connect completed during a ERESTARTSYS event */ + goto out_release; /* Connect completed during a ERESTARTSYS event */ } if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) { sock->state = SS_UNCONNECTED; - release_sock(sk); - return -ECONNREFUSED; + err = -ECONNREFUSED; + goto out_release; } if (sk->sk_state == TCP_ESTABLISHED) { - release_sock(sk); - return -EISCONN; /* No reconnect on a seqpacket socket */ + err = -EISCONN; /* No reconnect on a seqpacket socket */ + goto out_release; } - sk->sk_state = TCP_CLOSE; + sk->sk_state = TCP_CLOSE; sock->state = SS_UNCONNECTED; if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) { - release_sock(sk); - return -EINVAL; + err = -EINVAL; + goto out_release; } if (addr->sax25_family != AF_NETROM) { - release_sock(sk); - return -EINVAL; + err = -EINVAL; + goto out_release; } 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); - return -ENETUNREACH; + err = -ENETUNREACH; + goto out_release; } source = (ax25_address *)dev->dev_addr; - user = ax25_findbyuid(current->euid); + 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; + err = -EPERM; + goto out_release; } nr->user_addr = *source; } @@ -694,55 +726,55 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, /* Now the loop */ if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) { - release_sock(sk); - return -EINPROGRESS; + err = -EINPROGRESS; + goto out_release; } - + /* * A Connect Ack with Choke or timeout or failed routing will go to * closed. */ if (sk->sk_state == TCP_SYN_SENT) { - struct task_struct *tsk = current; - DECLARE_WAITQUEUE(wait, tsk); + DEFINE_WAIT(wait); - add_wait_queue(sk->sk_sleep, &wait); for (;;) { - set_current_state(TASK_INTERRUPTIBLE); + prepare_to_wait(sk->sk_sleep, &wait, + TASK_INTERRUPTIBLE); if (sk->sk_state != TCP_SYN_SENT) break; - release_sock(sk); - if (!signal_pending(tsk)) { + if (!signal_pending(current)) { + release_sock(sk); schedule(); lock_sock(sk); continue; } - current->state = TASK_RUNNING; - remove_wait_queue(sk->sk_sleep, &wait); - return -ERESTARTSYS; + err = -ERESTARTSYS; + break; } - current->state = TASK_RUNNING; - remove_wait_queue(sk->sk_sleep, &wait); + finish_wait(sk->sk_sleep, &wait); + if (err) + goto out_release; } if (sk->sk_state != TCP_ESTABLISHED) { sock->state = SS_UNCONNECTED; - release_sock(sk); - return sock_error(sk); /* Always set at this point */ + err = sock_error(sk); /* Always set at this point */ + goto out_release; } sock->state = SS_CONNECTED; + +out_release: release_sock(sk); - return 0; + return err; } static int nr_accept(struct socket *sock, struct socket *newsock, int flags) { - struct task_struct *tsk = current; - DECLARE_WAITQUEUE(wait, tsk); struct sk_buff *skb; struct sock *newsk; + DEFINE_WAIT(wait); struct sock *sk; int err = 0; @@ -752,54 +784,51 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) lock_sock(sk); if (sk->sk_type != SOCK_SEQPACKET) { err = -EOPNOTSUPP; - goto out; + goto out_release; } if (sk->sk_state != TCP_LISTEN) { err = -EINVAL; - goto out; + goto out_release; } /* * The write queue this time is holding sockets ready to use * hooked into the SABM we saved */ - add_wait_queue(sk->sk_sleep, &wait); for (;;) { + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); skb = skb_dequeue(&sk->sk_receive_queue); if (skb) break; - current->state = TASK_INTERRUPTIBLE; - release_sock(sk); if (flags & O_NONBLOCK) { - current->state = TASK_RUNNING; - remove_wait_queue(sk->sk_sleep, &wait); - return -EWOULDBLOCK; + err = -EWOULDBLOCK; + break; } - if (!signal_pending(tsk)) { + if (!signal_pending(current)) { + release_sock(sk); schedule(); lock_sock(sk); continue; } - current->state = TASK_RUNNING; - remove_wait_queue(sk->sk_sleep, &wait); - return -ERESTARTSYS; + err = -ERESTARTSYS; + break; } - current->state = TASK_RUNNING; - remove_wait_queue(sk->sk_sleep, &wait); + finish_wait(sk->sk_sleep, &wait); + if (err) + goto out_release; newsk = skb->sk; - newsk->sk_socket = newsock; - newsk->sk_sleep = &newsock->wait; + sock_graft(newsk, newsock); /* Now attach up the new socket */ kfree_skb(skb); - sk->sk_ack_backlog--; - newsock->sk = newsk; + sk_acceptq_removed(sk); -out: +out_release: release_sock(sk); + return err; } @@ -835,7 +864,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr, int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) { struct sock *sk; - struct sock *make; + struct sock *make; struct nr_sock *nr_make; ax25_address *src, *dest, *user; unsigned short circuit_index, circuit_id; @@ -865,7 +894,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) 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; + skb_reset_transport_header(skb); return nr_rx_ip(skb, dev); } @@ -891,7 +920,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) } if (sk != NULL) { - skb->h.raw = skb->data; + skb_reset_transport_header(skb); if (frametype == NR_CONNACK && skb->len == 22) nr_sk(sk)->bpqext = 1; @@ -980,19 +1009,19 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) nr_make->vr = 0; nr_make->vl = 0; nr_make->state = NR_STATE_3; - sk->sk_ack_backlog++; - - nr_insert_socket(make); - + sk_acceptq_added(sk); skb_queue_head(&sk->sk_receive_queue, skb); - nr_start_heartbeat(make); - nr_start_idletimer(make); - if (!sock_flag(sk, SOCK_DEAD)) sk->sk_data_ready(sk, skb->len); bh_unlock_sock(sk); + + nr_insert_socket(make); + + nr_start_heartbeat(make); + nr_start_idletimer(make); + return 1; } @@ -1053,7 +1082,13 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n"); - /* Build a packet */ + /* Build a packet - the conventional user limit is 236 bytes. We can + do ludicrously large NetROM frames but must not overflow */ + if (len > 65536) { + err = -EMSGSIZE; + goto out; + } + SOCK_DEBUG(sk, "NET/ROM: sendto: building packet.\n"); size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN; @@ -1061,6 +1096,7 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, goto out; skb_reserve(skb, size - len); + skb_reset_transport_header(skb); /* * Push down the NET/ROM header @@ -1081,14 +1117,12 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, /* * Put the data on the end */ + skb_put(skb, len); - skb->h.raw = skb_put(skb, len); - - asmptr = skb->h.raw; SOCK_DEBUG(sk, "NET/ROM: Appending user data\n"); /* User data follows immediately after the NET/ROM transport header */ - if (memcpy_fromiovec(asmptr, msg->msg_iov, len)) { + if (memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len)) { kfree_skb(skb); err = -EFAULT; goto out; @@ -1136,7 +1170,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, return er; } - skb->h.raw = skb->data; + skb_reset_transport_header(skb); copied = skb->len; if (copied > size) { @@ -1148,7 +1182,8 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, if (sax != NULL) { sax->sax25_family = AF_NETROM; - memcpy(sax->sax25_call.ax25_call, skb->data + 7, AX25_ADDR_LEN); + skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, + AX25_ADDR_LEN); } msg->msg_namelen = sizeof(*sax); @@ -1196,6 +1231,12 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) release_sock(sk); return ret; + case SIOCGSTAMPNS: + lock_sock(sk); + ret = sock_get_timestampns(sk, argp); + release_sock(sk); + return ret; + case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFDSTADDR: @@ -1215,7 +1256,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return nr_rt_ioctl(cmd, argp); default: - return dev_ioctl(cmd, argp); + return -ENOIOCTLCMD; } return 0; @@ -1245,10 +1286,10 @@ static void *nr_info_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; - return (v == SEQ_START_TOKEN) ? sk_head(&nr_list) + return (v == SEQ_START_TOKEN) ? sk_head(&nr_list) : sk_next((struct sock *)v); } - + static void nr_info_stop(struct seq_file *seq, void *v) { spin_unlock_bh(&nr_list_lock); @@ -1278,7 +1319,7 @@ static int nr_info_show(struct seq_file *seq, void *v) seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr)); seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr)); - seq_printf(seq, + 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(buf, &nr->source_addr), devname, @@ -1310,19 +1351,19 @@ static int nr_info_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations nr_info_seqops = { +static const struct seq_operations nr_info_seqops = { .start = nr_info_start, .next = nr_info_next, .stop = nr_info_stop, .show = nr_info_show, }; - + static int nr_info_open(struct inode *inode, struct file *file) { return seq_open(file, &nr_info_seqops); } - -static struct file_operations nr_info_fops = { + +static const struct file_operations nr_info_fops = { .owner = THIS_MODULE, .open = nr_info_open, .read = seq_read, @@ -1364,7 +1405,14 @@ 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 struct ax25_protocol nr_pid = { + .pid = AX25_P_NETROM, + .func = nr_route_frame +}; + +static struct ax25_linkfail nr_linkfail_notifier = { + .func = nr_link_failed, +}; static int __init nr_proto_init(void) { @@ -1379,31 +1427,30 @@ static int __init nr_proto_init(void) return -1; } - dev_nr = kmalloc(nr_ndevs * sizeof(struct net_device *), GFP_KERNEL); + dev_nr = kzalloc(nr_ndevs * sizeof(struct net_device *), GFP_KERNEL); if (dev_nr == NULL) { printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device array\n"); return -1; } - memset(dev_nr, 0x00, nr_ndevs * sizeof(struct net_device *)); - for (i = 0; i < nr_ndevs; i++) { char name[IFNAMSIZ]; struct net_device *dev; sprintf(name, "nr%d", i); - dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup); + dev = alloc_netdev(0, name, nr_setup); if (!dev) { printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); goto fail; } - + dev->base_addr = i; if (register_netdev(dev)) { printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register network device\n"); free_netdev(dev); goto fail; } + nr_set_lockdep_key(dev); dev_nr[i] = dev; } @@ -1411,12 +1458,11 @@ static int __init nr_proto_init(void) printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register socket family\n"); goto fail; } - + register_netdevice_notifier(&nr_dev_notifier); - printk(banner); - ax25_protocol_register(AX25_P_NETROM, nr_route_frame); - ax25_linkfail_register(nr_link_failed); + ax25_register_pid(&nr_pid); + ax25_linkfail_register(&nr_linkfail_notifier); #ifdef CONFIG_SYSCTL nr_register_sysctl(); @@ -1424,9 +1470,9 @@ static int __init nr_proto_init(void) nr_loopback_init(); - 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); + proc_net_fops_create(&init_net, "nr", S_IRUGO, &nr_info_fops); + proc_net_fops_create(&init_net, "nr_neigh", S_IRUGO, &nr_neigh_fops); + proc_net_fops_create(&init_net, "nr_nodes", S_IRUGO, &nr_nodes_fops); out: return rc; fail: @@ -1454,9 +1500,9 @@ static void __exit nr_exit(void) { int i; - proc_net_remove("nr"); - proc_net_remove("nr_neigh"); - proc_net_remove("nr_nodes"); + proc_net_remove(&init_net, "nr"); + proc_net_remove(&init_net, "nr_neigh"); + proc_net_remove(&init_net, "nr_nodes"); nr_loopback_clear(); nr_rt_free(); @@ -1465,7 +1511,7 @@ static void __exit nr_exit(void) nr_unregister_sysctl(); #endif - ax25_linkfail_release(nr_link_failed); + ax25_linkfail_release(&nr_linkfail_notifier); ax25_protocol_release(AX25_P_NETROM); unregister_netdevice_notifier(&nr_dev_notifier);