Loading net/econet/af_econet.c +85 −55 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/bitops.h> #include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/system.h> Loading @@ -49,6 +50,7 @@ static const struct proto_ops econet_ops; static struct hlist_head econet_sklist; static DEFINE_RWLOCK(econet_lock); static DEFINE_MUTEX(econet_mutex); /* Since there are only 256 possible network numbers (or fewer, depends how you count) it makes sense to use a simple lookup table. */ Loading Loading @@ -124,6 +126,8 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = sizeof(struct sockaddr_ec); mutex_lock(&econet_mutex); /* * Call the generic datagram receiver. This handles all sorts * of horrible races and re-entrancy so we can forget about it Loading Loading @@ -174,6 +178,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock, out_free: skb_free_datagram(sk, skb); out: mutex_unlock(&econet_mutex); return err; } Loading @@ -184,8 +189,8 @@ out: static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; struct sock *sk=sock->sk; struct econet_sock *eo = ec_sk(sk); struct sock *sk; struct econet_sock *eo; /* * Check legality Loading @@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len sec->sec_family != AF_ECONET) return -EINVAL; mutex_lock(&econet_mutex); sk = sock->sk; eo = ec_sk(sk); eo->cb = sec->cb; eo->port = sec->port; eo->station = sec->addr.station; eo->net = sec->addr.net; mutex_unlock(&econet_mutex); return 0; } Loading Loading @@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, * Get and verify the address. */ mutex_lock(&econet_mutex); if (saddr == NULL) { struct econet_sock *eo = ec_sk(sk); Loading @@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, port = eo->port; cb = eo->cb; } else { if (msg->msg_namelen < sizeof(struct sockaddr_ec)) if (msg->msg_namelen < sizeof(struct sockaddr_ec)) { mutex_unlock(&econet_mutex); return -EINVAL; } addr.station = saddr->addr.station; addr.net = saddr->addr.net; port = saddr->port; Loading @@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, dev = net2dev_map[addr.net]; /* If not directly reachable, use some default */ if (dev == NULL) { if (dev == NULL) { dev = net2dev_map[0]; /* No interfaces at all? */ if (dev == NULL) if (dev == NULL) { mutex_unlock(&econet_mutex); return -ENETDOWN; } } if (len + 15 > dev->mtu) if (len + 15 > dev->mtu) { mutex_unlock(&econet_mutex); return -EMSGSIZE; } if (dev->type == ARPHRD_ECONET) { if (dev->type == ARPHRD_ECONET) { /* Real hardware Econet. We're not worthy etc. */ #ifdef CONFIG_ECONET_NATIVE unsigned short proto = 0; Loading Loading @@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, dev_queue_xmit(skb); dev_put(dev); mutex_unlock(&econet_mutex); return(len); out_free: Loading @@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, #else err = -EPROTOTYPE; #endif mutex_unlock(&econet_mutex); return err; } #ifdef CONFIG_ECONET_AUNUDP /* AUN virtual Econet. */ if (udpsock == NULL) if (udpsock == NULL) { mutex_unlock(&econet_mutex); return -ENETDOWN; /* No socket - can't send */ } /* Make up a UDP datagram and hand it off to some higher intellect. */ Loading Loading @@ -438,8 +461,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, void __user *base = msg->msg_iov[i].iov_base; size_t len = msg->msg_iov[i].iov_len; /* Check it now since we switch to KERNEL_DS later. */ if (!access_ok(VERIFY_READ, base, len)) if (!access_ok(VERIFY_READ, base, len)) { mutex_unlock(&econet_mutex); return -EFAULT; } iov[i+1].iov_base = base; iov[i+1].iov_len = len; size += len; Loading @@ -447,8 +472,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, /* Get a skbuff (no data, just holds our cb information) */ if ((skb = sock_alloc_send_skb(sk, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) { mutex_unlock(&econet_mutex); return err; } eb = (struct ec_cb *)&skb->cb; Loading @@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, #else err = -EPROTOTYPE; #endif mutex_unlock(&econet_mutex); return err; } Loading @@ -485,18 +515,25 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, static int econet_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sock *sk = sock->sk; struct econet_sock *eo = ec_sk(sk); struct sock *sk; struct econet_sock *eo; struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; if (peer) return -EOPNOTSUPP; mutex_lock(&econet_mutex); sk = sock->sk; eo = ec_sk(sk); sec->sec_family = AF_ECONET; sec->port = eo->port; sec->addr.station = eo->station; sec->addr.net = eo->net; mutex_unlock(&econet_mutex); *uaddr_len = sizeof(*sec); return 0; } Loading @@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data) static int econet_release(struct socket *sock) { struct sock *sk = sock->sk; struct sock *sk; mutex_lock(&econet_mutex); sk = sock->sk; if (!sk) return 0; goto out_unlock; econet_remove_socket(&econet_sklist, sk); Loading @@ -549,10 +589,14 @@ static int econet_release(struct socket *sock) sk->sk_timer.expires = jiffies + HZ; sk->sk_timer.function = econet_destroy_timer; add_timer(&sk->sk_timer); return 0; goto out_unlock; } sk_free(sk); out_unlock: mutex_unlock(&econet_mutex); return 0; } Loading Loading @@ -608,6 +652,7 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) struct ec_device *edev; struct net_device *dev; struct sockaddr_ec *sec; int err; /* * Fetch the caller's info block into kernel space Loading @@ -621,38 +666,35 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) sec = (struct sockaddr_ec *)&ifr.ifr_addr; switch (cmd) { mutex_lock(&econet_mutex); err = 0; switch (cmd) { case SIOCSIFADDR: edev = dev->ec_ptr; if (edev == NULL) { if (edev == NULL) { /* Magic up a new one. */ edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL); if (edev == NULL) { printk("af_ec: memory squeeze.\n"); dev_put(dev); return -ENOMEM; err = -ENOMEM; break; } memset(edev, 0, sizeof(struct ec_device)); dev->ec_ptr = edev; } else } else net2dev_map[edev->net] = NULL; edev->station = sec->addr.station; edev->net = sec->addr.net; net2dev_map[sec->addr.net] = dev; if (!net2dev_map[0]) net2dev_map[0] = dev; dev_put(dev); return 0; break; case SIOCGIFADDR: edev = dev->ec_ptr; if (edev == NULL) { dev_put(dev); return -ENODEV; if (edev == NULL) { err = -ENODEV; break; } memset(sec, 0, sizeof(struct sockaddr_ec)); sec->addr.station = edev->station; Loading @@ -660,12 +702,19 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) sec->sec_family = AF_ECONET; dev_put(dev); if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; return 0; err = -EFAULT; break; default: err = -EINVAL; break; } mutex_unlock(&econet_mutex); dev_put(dev); return -EINVAL; return err; } /* Loading Loading @@ -693,26 +742,13 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg return 0; } #ifdef CONFIG_COMPAT static int econet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { /* * All ioctls provided by econet are standard. There is one gotcha, sockaddr_ec * differs between 32bit and 64bit. Fortunately nobody in kernel uses portion * of sockaddr which differs between 32bit and 64bit, so we do not need special * handling. */ return -ENOIOCTLCMD; } #endif static struct net_proto_family econet_family_ops = { .family = PF_ECONET, .create = econet_create, .owner = THIS_MODULE, }; static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { static const struct proto_ops econet_ops = { .family = PF_ECONET, .owner = THIS_MODULE, .release = econet_release, Loading @@ -723,9 +759,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { .getname = econet_getname, .poll = datagram_poll, .ioctl = econet_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = econet_compat_ioctl, #endif .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = sock_no_setsockopt, Loading @@ -736,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { .sendpage = sock_no_sendpage, }; #include <linux/smp_lock.h> SOCKOPS_WRAP(econet, PF_ECONET); #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) /* * Find the listening socket, if any, for the given data. Loading Loading
net/econet/af_econet.c +85 −55 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/bitops.h> #include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/system.h> Loading @@ -49,6 +50,7 @@ static const struct proto_ops econet_ops; static struct hlist_head econet_sklist; static DEFINE_RWLOCK(econet_lock); static DEFINE_MUTEX(econet_mutex); /* Since there are only 256 possible network numbers (or fewer, depends how you count) it makes sense to use a simple lookup table. */ Loading Loading @@ -124,6 +126,8 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = sizeof(struct sockaddr_ec); mutex_lock(&econet_mutex); /* * Call the generic datagram receiver. This handles all sorts * of horrible races and re-entrancy so we can forget about it Loading Loading @@ -174,6 +178,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock, out_free: skb_free_datagram(sk, skb); out: mutex_unlock(&econet_mutex); return err; } Loading @@ -184,8 +189,8 @@ out: static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; struct sock *sk=sock->sk; struct econet_sock *eo = ec_sk(sk); struct sock *sk; struct econet_sock *eo; /* * Check legality Loading @@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len sec->sec_family != AF_ECONET) return -EINVAL; mutex_lock(&econet_mutex); sk = sock->sk; eo = ec_sk(sk); eo->cb = sec->cb; eo->port = sec->port; eo->station = sec->addr.station; eo->net = sec->addr.net; mutex_unlock(&econet_mutex); return 0; } Loading Loading @@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, * Get and verify the address. */ mutex_lock(&econet_mutex); if (saddr == NULL) { struct econet_sock *eo = ec_sk(sk); Loading @@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, port = eo->port; cb = eo->cb; } else { if (msg->msg_namelen < sizeof(struct sockaddr_ec)) if (msg->msg_namelen < sizeof(struct sockaddr_ec)) { mutex_unlock(&econet_mutex); return -EINVAL; } addr.station = saddr->addr.station; addr.net = saddr->addr.net; port = saddr->port; Loading @@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, dev = net2dev_map[addr.net]; /* If not directly reachable, use some default */ if (dev == NULL) { if (dev == NULL) { dev = net2dev_map[0]; /* No interfaces at all? */ if (dev == NULL) if (dev == NULL) { mutex_unlock(&econet_mutex); return -ENETDOWN; } } if (len + 15 > dev->mtu) if (len + 15 > dev->mtu) { mutex_unlock(&econet_mutex); return -EMSGSIZE; } if (dev->type == ARPHRD_ECONET) { if (dev->type == ARPHRD_ECONET) { /* Real hardware Econet. We're not worthy etc. */ #ifdef CONFIG_ECONET_NATIVE unsigned short proto = 0; Loading Loading @@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, dev_queue_xmit(skb); dev_put(dev); mutex_unlock(&econet_mutex); return(len); out_free: Loading @@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, #else err = -EPROTOTYPE; #endif mutex_unlock(&econet_mutex); return err; } #ifdef CONFIG_ECONET_AUNUDP /* AUN virtual Econet. */ if (udpsock == NULL) if (udpsock == NULL) { mutex_unlock(&econet_mutex); return -ENETDOWN; /* No socket - can't send */ } /* Make up a UDP datagram and hand it off to some higher intellect. */ Loading Loading @@ -438,8 +461,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, void __user *base = msg->msg_iov[i].iov_base; size_t len = msg->msg_iov[i].iov_len; /* Check it now since we switch to KERNEL_DS later. */ if (!access_ok(VERIFY_READ, base, len)) if (!access_ok(VERIFY_READ, base, len)) { mutex_unlock(&econet_mutex); return -EFAULT; } iov[i+1].iov_base = base; iov[i+1].iov_len = len; size += len; Loading @@ -447,8 +472,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, /* Get a skbuff (no data, just holds our cb information) */ if ((skb = sock_alloc_send_skb(sk, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) { mutex_unlock(&econet_mutex); return err; } eb = (struct ec_cb *)&skb->cb; Loading @@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, #else err = -EPROTOTYPE; #endif mutex_unlock(&econet_mutex); return err; } Loading @@ -485,18 +515,25 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, static int econet_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sock *sk = sock->sk; struct econet_sock *eo = ec_sk(sk); struct sock *sk; struct econet_sock *eo; struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; if (peer) return -EOPNOTSUPP; mutex_lock(&econet_mutex); sk = sock->sk; eo = ec_sk(sk); sec->sec_family = AF_ECONET; sec->port = eo->port; sec->addr.station = eo->station; sec->addr.net = eo->net; mutex_unlock(&econet_mutex); *uaddr_len = sizeof(*sec); return 0; } Loading @@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data) static int econet_release(struct socket *sock) { struct sock *sk = sock->sk; struct sock *sk; mutex_lock(&econet_mutex); sk = sock->sk; if (!sk) return 0; goto out_unlock; econet_remove_socket(&econet_sklist, sk); Loading @@ -549,10 +589,14 @@ static int econet_release(struct socket *sock) sk->sk_timer.expires = jiffies + HZ; sk->sk_timer.function = econet_destroy_timer; add_timer(&sk->sk_timer); return 0; goto out_unlock; } sk_free(sk); out_unlock: mutex_unlock(&econet_mutex); return 0; } Loading Loading @@ -608,6 +652,7 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) struct ec_device *edev; struct net_device *dev; struct sockaddr_ec *sec; int err; /* * Fetch the caller's info block into kernel space Loading @@ -621,38 +666,35 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) sec = (struct sockaddr_ec *)&ifr.ifr_addr; switch (cmd) { mutex_lock(&econet_mutex); err = 0; switch (cmd) { case SIOCSIFADDR: edev = dev->ec_ptr; if (edev == NULL) { if (edev == NULL) { /* Magic up a new one. */ edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL); if (edev == NULL) { printk("af_ec: memory squeeze.\n"); dev_put(dev); return -ENOMEM; err = -ENOMEM; break; } memset(edev, 0, sizeof(struct ec_device)); dev->ec_ptr = edev; } else } else net2dev_map[edev->net] = NULL; edev->station = sec->addr.station; edev->net = sec->addr.net; net2dev_map[sec->addr.net] = dev; if (!net2dev_map[0]) net2dev_map[0] = dev; dev_put(dev); return 0; break; case SIOCGIFADDR: edev = dev->ec_ptr; if (edev == NULL) { dev_put(dev); return -ENODEV; if (edev == NULL) { err = -ENODEV; break; } memset(sec, 0, sizeof(struct sockaddr_ec)); sec->addr.station = edev->station; Loading @@ -660,12 +702,19 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) sec->sec_family = AF_ECONET; dev_put(dev); if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; return 0; err = -EFAULT; break; default: err = -EINVAL; break; } mutex_unlock(&econet_mutex); dev_put(dev); return -EINVAL; return err; } /* Loading Loading @@ -693,26 +742,13 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg return 0; } #ifdef CONFIG_COMPAT static int econet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { /* * All ioctls provided by econet are standard. There is one gotcha, sockaddr_ec * differs between 32bit and 64bit. Fortunately nobody in kernel uses portion * of sockaddr which differs between 32bit and 64bit, so we do not need special * handling. */ return -ENOIOCTLCMD; } #endif static struct net_proto_family econet_family_ops = { .family = PF_ECONET, .create = econet_create, .owner = THIS_MODULE, }; static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { static const struct proto_ops econet_ops = { .family = PF_ECONET, .owner = THIS_MODULE, .release = econet_release, Loading @@ -723,9 +759,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { .getname = econet_getname, .poll = datagram_poll, .ioctl = econet_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = econet_compat_ioctl, #endif .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = sock_no_setsockopt, Loading @@ -736,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { .sendpage = sock_no_sendpage, }; #include <linux/smp_lock.h> SOCKOPS_WRAP(econet, PF_ECONET); #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) /* * Find the listening socket, if any, for the given data. Loading