summaryrefslogtreecommitdiffstats
path: root/net/packet
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-04-05 11:23:36 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-04-05 11:23:36 +0000
commit4318fbda2a7ee51caafdc4eb1f8028a3f0605142 (patch)
treecddb50a81d7d1a628cc400519162080c6d87868e /net/packet
parent36ea5120664550fae6d31f1c6f695e4f8975cb06 (diff)
o Merge with Linux 2.1.91.
o First round of bugfixes for the SC/MC CPUs. o FPU context switch fixes. o Lazy context switches. o Faster syscalls. o Removed dead code. o Shitloads of other things I forgot ...
Diffstat (limited to 'net/packet')
-rw-r--r--net/packet/af_packet.c172
1 files changed, 79 insertions, 93 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 74fc7af82..858ea0e73 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -262,9 +262,9 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
+ struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
struct sk_buff *skb;
struct device *dev;
- struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
unsigned short proto=0;
int err;
@@ -309,6 +309,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
return -EMSGSIZE;
dev_lock_list();
+ err = -ENOBUFS;
skb = sock_wmalloc(sk, len+dev->hard_header_len+15, 0, GFP_KERNEL);
/*
@@ -318,10 +319,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
*/
if (skb == NULL)
- {
- dev_unlock_list();
- return(-ENOBUFS);
- }
+ goto out_unlock;
/*
* Fill it in
@@ -339,36 +337,32 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
skb->data -= dev->hard_header_len;
skb->tail -= dev->hard_header_len;
}
+
+ /* Returns -EFAULT on error */
err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
skb->protocol = proto;
skb->dev = dev;
skb->priority = sk->priority;
- dev_unlock_list();
+ if (err)
+ goto out_free;
+
+ err = -ENETDOWN;
+ if (!(dev->flags & IFF_UP))
+ goto out_free;
/*
* Now send it
*/
- if (err)
- {
- err = -EFAULT;
- }
- else
- {
- if (!(dev->flags & IFF_UP))
- {
- err = -ENETDOWN;
- }
- }
-
- if (err)
- {
- kfree_skb(skb);
- return err;
- }
-
+ dev_unlock_list();
dev_queue_xmit(skb);
return(len);
+
+out_free:
+ kfree_skb(skb);
+out_unlock:
+ dev_unlock_list();
+ return err;
}
#endif
@@ -434,13 +428,12 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
+ struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
struct sk_buff *skb;
struct device *dev;
- struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
unsigned short proto;
- int ifindex;
- int err;
- int reserve = 0;
+ unsigned char *addr;
+ int ifindex, err, reserve = 0;
/*
* Check the flags.
@@ -454,13 +447,15 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
*/
if (saddr == NULL) {
- ifindex = sk->protinfo.af_packet->ifindex;
- proto = sk->num;
+ ifindex = sk->protinfo.af_packet->ifindex;
+ proto = sk->num;
+ addr = NULL;
} else {
if (msg->msg_namelen < sizeof(struct sockaddr_ll))
return -EINVAL;
- ifindex = saddr->sll_ifindex;
- proto = saddr->sll_protocol;
+ ifindex = saddr->sll_ifindex;
+ proto = saddr->sll_protocol;
+ addr = saddr->sll_addr;
}
dev = dev_get_by_index(ifindex);
@@ -474,55 +469,50 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
dev_lock_list();
- skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, msg->msg_flags&MSG_DONTWAIT, &err);
-
- if (skb==NULL) {
- dev_unlock_list();
- return err;
- }
+ skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0,
+ msg->msg_flags & MSG_DONTWAIT, &err);
+ if (skb==NULL)
+ goto out_unlock;
skb_reserve(skb, (dev->hard_header_len+15)&~15);
skb->nh.raw = skb->data;
if (dev->hard_header) {
- if (dev->hard_header(skb, dev, ntohs(proto),
- saddr ? saddr->sll_addr : NULL,
- NULL, len) < 0
- && sock->type == SOCK_DGRAM) {
- kfree_skb(skb);
- dev_unlock_list();
- return -EINVAL;
- }
+ int res;
+ err = -EINVAL;
+ res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len);
if (sock->type != SOCK_DGRAM) {
skb->tail = skb->data;
skb->len = 0;
- }
+ } else if (res < 0)
+ goto out_free;
}
+ /* Returns -EFAULT on error */
err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
skb->protocol = proto;
skb->dev = dev;
skb->priority = sk->priority;
- dev_unlock_list();
+ if (err)
+ goto out_free;
+
+ err = -ENETDOWN;
+ if (!(dev->flags & IFF_UP))
+ goto out_free;
/*
* Now send it
*/
- if (err) {
- err = -EFAULT;
- } else {
- if (!(dev->flags & IFF_UP))
- err = -ENETDOWN;
- }
-
- if (err) {
- kfree_skb(skb);
- return err;
- }
-
+ dev_unlock_list();
dev_queue_xmit(skb);
return(len);
+
+out_free:
+ kfree_skb(skb);
+out_unlock:
+ dev_unlock_list();
+ return err;
}
static void packet_destroy_timer(unsigned long data)
@@ -699,6 +689,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
static int packet_create(struct socket *sock, int protocol)
{
struct sock *sk;
+ int err;
if (!suser())
return -EPERM;
@@ -711,27 +702,23 @@ static int packet_create(struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
MOD_INC_USE_COUNT;
+
+ err = -ENOBUFS;
sk = sk_alloc(AF_PACKET, GFP_KERNEL, 1);
- if (sk == NULL) {
- MOD_DEC_USE_COUNT;
- return -ENOBUFS;
- }
+ if (sk == NULL)
+ goto out;
sk->reuse = 1;
+ sock->ops = &packet_ops;
#ifdef CONFIG_SOCK_PACKET
if (sock->type == SOCK_PACKET)
sock->ops = &packet_ops_spkt;
- else
#endif
- sock->ops = &packet_ops;
sock_init_data(sock,sk);
sk->protinfo.af_packet = kmalloc(sizeof(struct packet_opt), GFP_KERNEL);
- if (sk->protinfo.af_packet == NULL) {
- sk_free(sk);
- MOD_DEC_USE_COUNT;
- return -ENOBUFS;
- }
+ if (sk->protinfo.af_packet == NULL)
+ goto out_free;
memset(sk->protinfo.af_packet, 0, sizeof(struct packet_opt));
sk->zapped=0;
sk->family = AF_PACKET;
@@ -741,13 +728,11 @@ static int packet_create(struct socket *sock, int protocol)
* Attach a protocol block
*/
+ sk->protinfo.af_packet->prot_hook.func = packet_rcv;
#ifdef CONFIG_SOCK_PACKET
if (sock->type == SOCK_PACKET)
sk->protinfo.af_packet->prot_hook.func = packet_rcv_spkt;
- else
#endif
- sk->protinfo.af_packet->prot_hook.func = packet_rcv;
-
sk->protinfo.af_packet->prot_hook.data = (void *)sk;
if (protocol) {
@@ -758,6 +743,12 @@ static int packet_create(struct socket *sock, int protocol)
sklist_insert_socket(&packet_sklist, sk);
return(0);
+
+out_free:
+ sk_free(sk);
+out:
+ MOD_DEC_USE_COUNT;
+ return err;
}
/*
@@ -832,10 +823,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, int len,
/* We can't use skb_copy_datagram here */
err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
- if (err) {
- err = -EFAULT;
+ if (err)
goto out_free;
- }
sk->stamp=skb->stamp;
if (msg->msg_name)
@@ -932,37 +921,39 @@ static void packet_dev_mclist(struct device *dev, struct packet_mclist *i, int w
static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
{
- int err;
struct packet_mclist *ml, *i;
struct device *dev;
+ int err;
rtnl_shlock();
- dev = dev_get_by_index(mreq->mr_ifindex);
-
- i = NULL;
err = -ENODEV;
+ dev = dev_get_by_index(mreq->mr_ifindex);
if (!dev)
goto done;
+
err = -EINVAL;
if (mreq->mr_alen > dev->addr_len)
goto done;
+ err = -ENOBUFS;
i = (struct packet_mclist *)kmalloc(sizeof(*i), GFP_KERNEL);
+ if (i == NULL)
+ goto done;
+ err = 0;
for (ml=sk->protinfo.af_packet->mclist; ml; ml=ml->next) {
if (ml->ifindex == mreq->mr_ifindex &&
ml->type == mreq->mr_type &&
ml->alen == mreq->mr_alen &&
memcmp(ml->addr, mreq->mr_address, ml->alen) == 0) {
ml->count++;
- err = 0;
+ /* Free the new element ... */
+ kfree(i);
goto done;
}
}
- err = -ENOBUFS;
- if (i == NULL)
- goto done;
+
i->type = mreq->mr_type;
i->ifindex = mreq->mr_ifindex;
i->alen = mreq->mr_alen;
@@ -971,13 +962,9 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
i->next = sk->protinfo.af_packet->mclist;
sk->protinfo.af_packet->mclist = i;
packet_dev_mc(dev, i, +1);
- i = NULL;
- err = 0;
done:
rtnl_shunlock();
- if (i)
- kfree(i);
return err;
}
@@ -1109,13 +1096,12 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
case FIOGETOWN:
case SIOCGPGRP:
return put_user(sk->proc, (int *)arg);
- return(0);
case SIOCGSTAMP:
if(sk->stamp.tv_sec==0)
return -ENOENT;
- err = copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
- if (err)
- err = -EFAULT;
+ err = -EFAULT;
+ if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+ err = 0;
return err;
case SIOCGIFFLAGS:
#ifndef CONFIG_INET