X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Feconet%2Faf_econet.c;h=4d66aac134835fb082044c26041c6f6039e3ba24;hb=refs%2Fheads%2Fvserver;hp=c792994d795257a90aaa87ad33d305db31613dd2;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index c792994d7..4d66aac13 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -9,7 +9,6 @@ * */ -#include #include #include @@ -42,6 +41,7 @@ #include #include #include +#include #include #include @@ -49,6 +49,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. */ @@ -124,6 +125,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 @@ -174,6 +177,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; } @@ -184,8 +188,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 @@ -195,11 +199,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; } @@ -284,6 +295,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); @@ -292,8 +305,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; @@ -304,19 +319,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; @@ -374,6 +391,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: @@ -384,14 +402,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. */ @@ -438,8 +460,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; @@ -447,8 +471,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; @@ -475,6 +502,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, #else err = -EPROTOTYPE; #endif + mutex_unlock(&econet_mutex); + return err; } @@ -485,18 +514,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; } @@ -522,10 +558,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); @@ -549,10 +588,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; } @@ -608,6 +651,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 @@ -621,38 +665,34 @@ 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); + edev = kzalloc(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; @@ -660,12 +700,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; } /* @@ -699,7 +746,7 @@ static struct net_proto_family econet_family_ops = { .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, @@ -720,9 +767,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { .sendpage = sock_no_sendpage, }; -#include -SOCKOPS_WRAP(econet, PF_ECONET); - #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) /* * Find the listening socket, if any, for the given data.