diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/appletalk/ddp.c | 31 | ||||
-rw-r--r-- | net/atm/addr.c | 6 | ||||
-rw-r--r-- | net/atm/common.c | 4 | ||||
-rw-r--r-- | net/atm/ioctl.c | 34 | ||||
-rw-r--r-- | net/atm/signaling.c | 8 | ||||
-rw-r--r-- | net/atm/svc.c | 1 | ||||
-rw-r--r-- | net/core/datagram.c | 81 | ||||
-rw-r--r-- | net/core/dev.c | 2 | ||||
-rw-r--r-- | net/core/sock.c | 20 | ||||
-rw-r--r-- | net/ethernet/eth.c | 31 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 11 | ||||
-rw-r--r-- | net/rose/af_rose.c | 26 | ||||
-rw-r--r-- | net/socket.c | 13 |
13 files changed, 150 insertions, 118 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 1d31b3a3f1e..7982656b9c8 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -100,8 +100,7 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to, continue; if (to->sat_addr.s_net == ATADDR_ANYNET && - to->sat_addr.s_node == ATADDR_BCAST && - at->src_net == atif->address.s_net) + to->sat_addr.s_node == ATADDR_BCAST) goto found; if (to->sat_addr.s_net == at->src_net && @@ -1443,8 +1442,10 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, else atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); - /* Not ours, so we route the packet via the correct AppleTalk iface */ if (!atif) { + /* Not ours, so we route the packet via the correct + * AppleTalk iface + */ atalk_route_packet(skb, dev, ddp, &ddphv, origlen); goto out; } @@ -1592,9 +1593,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { rt = atrtr_find(&usat->sat_addr); - if (!rt) - return -ENETUNREACH; - dev = rt->dev; } else { struct atalk_addr at_hint; @@ -1603,11 +1601,12 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr at_hint.s_net = at->src_net; rt = atrtr_find(&at_hint); - if (!rt) - return -ENETUNREACH; - dev = rt->dev; } + if (!rt) + return -ENETUNREACH; + + dev = rt->dev; SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name); @@ -1677,6 +1676,20 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); /* loop back */ skb_orphan(skb); + if (ddp->deh_dnode == ATADDR_BCAST) { + struct atalk_addr at_lo; + + at_lo.s_node = 0; + at_lo.s_net = 0; + + rt = atrtr_find(&at_lo); + if (!rt) { + kfree_skb(skb); + return -ENETUNREACH; + } + dev = rt->dev; + skb->dev = dev; + } ddp_dl->request(ddp_dl, skb, dev->dev_addr); } else { SOCK_DEBUG(sk, "SK %p: send out.\n", sk); diff --git a/net/atm/addr.c b/net/atm/addr.c index 1c8867f7f54..a30d0bf4806 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -50,8 +50,10 @@ void atm_reset_addr(struct atm_dev *dev) struct atm_dev_addr *this, *p; spin_lock_irqsave(&dev->lock, flags); - list_for_each_entry_safe(this, p, &dev->local, entry) - kfree(this); + list_for_each_entry_safe(this, p, &dev->local, entry) { + list_del(&this->entry); + kfree(this); + } spin_unlock_irqrestore(&dev->lock, flags); notify_sigd(dev); } diff --git a/net/atm/common.c b/net/atm/common.c index e93e838069e..801a5813ec6 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -178,8 +178,6 @@ static void vcc_destroy_socket(struct sock *sk) if (vcc->push) vcc->push(vcc, NULL); /* atmarpd has no push */ - vcc_remove_socket(sk); /* no more receive */ - while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { atm_return(vcc,skb->truesize); kfree_skb(skb); @@ -188,6 +186,8 @@ static void vcc_destroy_socket(struct sock *sk) module_put(vcc->dev->ops->owner); atm_dev_put(vcc->dev); } + + vcc_remove_socket(sk); } diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index d89056ec44d..a150198b05a 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -105,17 +105,35 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (!error) sock->state = SS_CONNECTED; goto done; - default: + case ATM_SETBACKEND: + case ATM_NEWBACKENDIF: + { + atm_backend_t backend; + error = get_user(backend, (atm_backend_t __user *) argp); + if (error) + goto done; + switch (backend) { + case ATM_BACKEND_PPP: + request_module("pppoatm"); + break; + case ATM_BACKEND_BR2684: + request_module("br2684"); + break; + } + } + break; + case ATMMPC_CTRL: + case ATMMPC_DATA: + request_module("mpoa"); + break; + case ATMARPD_CTRL: + request_module("clip"); + break; + case ATMLEC_CTRL: + request_module("lec"); break; } - if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA) - request_module("mpoa"); - if (cmd == ATMARPD_CTRL) - request_module("clip"); - if (cmd == ATMLEC_CTRL) - request_module("lec"); - error = -ENOIOCTLCMD; down(&ioctl_mutex); diff --git a/net/atm/signaling.c b/net/atm/signaling.c index f7c449ac180..e7211a7f382 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -217,8 +217,9 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, static void purge_vcc(struct atm_vcc *vcc) { if (sk_atm(vcc)->sk_family == PF_ATMSVC && - !test_bit(ATM_VF_META,&vcc->flags)) { - set_bit(ATM_VF_RELEASED,&vcc->flags); + !test_bit(ATM_VF_META, &vcc->flags)) { + set_bit(ATM_VF_RELEASED, &vcc->flags); + clear_bit(ATM_VF_REGIS, &vcc->flags); vcc_release_async(vcc, -EUNATCH); } } @@ -243,8 +244,7 @@ static void sigd_close(struct atm_vcc *vcc) sk_for_each(s, node, head) { struct atm_vcc *vcc = atm_sk(s); - if (vcc->dev) - purge_vcc(vcc); + purge_vcc(vcc); } } read_unlock(&vcc_sklist_lock); diff --git a/net/atm/svc.c b/net/atm/svc.c index 08e46052a3e..d7b266136bf 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -302,6 +302,7 @@ static int svc_listen(struct socket *sock,int backlog) error = -EINVAL; goto out; } + vcc_insert_socket(sk); set_bit(ATM_VF_WAITING, &vcc->flags); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); diff --git a/net/core/datagram.c b/net/core/datagram.c index da9bf71421a..81987df536e 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -211,74 +211,45 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, struct iovec *to, int len) { - int start = skb_headlen(skb); - int i, copy = start - offset; - - /* Copy header. */ - if (copy > 0) { - if (copy > len) - copy = len; - if (memcpy_toiovec(to, skb->data + offset, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - } + int i, err, fraglen, end = 0; + struct sk_buff *next = skb_shinfo(skb)->frag_list; +next_skb: + fraglen = skb_headlen(skb); + i = -1; - /* Copy paged appendix. Hmm... why does this look so complicated? */ - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); + while (1) { + int start = end; - end = start + skb_shinfo(skb)->frags[i].size; - if ((copy = end - offset) > 0) { - int err; - u8 *vaddr; - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - struct page *page = frag->page; + if ((end += fraglen) > offset) { + int copy = end - offset, o = offset - start; if (copy > len) copy = len; - vaddr = kmap(page); - err = memcpy_toiovec(to, vaddr + frag->page_offset + - offset - start, copy); - kunmap(page); + if (i == -1) + err = memcpy_toiovec(to, skb->data + o, copy); + else { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + struct page *page = frag->page; + void *p = kmap(page) + frag->page_offset + o; + err = memcpy_toiovec(to, p, copy); + kunmap(page); + } if (err) goto fault; if (!(len -= copy)) return 0; offset += copy; } - start = end; + if (++i >= skb_shinfo(skb)->nr_frags) + break; + fraglen = skb_shinfo(skb)->frags[i].size; } - - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; - - for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - if (skb_copy_datagram_iovec(list, - offset - start, - to, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - } - start = end; - } + if (next) { + skb = next; + BUG_ON(skb_shinfo(skb)->frag_list); + next = skb->next; + goto next_skb; } - if (!len) - return 0; - fault: return -EFAULT; } diff --git a/net/core/dev.c b/net/core/dev.c index 37c88107096..9066c874e27 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1259,6 +1259,8 @@ int dev_queue_xmit(struct sk_buff *skb) if (skb_checksum_help(skb, 0)) goto out_kfree_skb; + spin_lock_prefetch(&dev->queue_lock); + /* Disable soft irqs for various locks below. Also * stops preemption for RCU. */ diff --git a/net/core/sock.c b/net/core/sock.c index ac63b56e23b..928d2a1d6d8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -660,16 +660,20 @@ struct sock *sk_alloc(int family, unsigned int __nocast priority, sock_lock_init(sk); } - if (security_sk_alloc(sk, family, priority)) { - if (slab != NULL) - kmem_cache_free(slab, sk); - else - kfree(sk); - sk = NULL; - } else - __module_get(prot->owner); + if (security_sk_alloc(sk, family, priority)) + goto out_free; + + if (!try_module_get(prot->owner)) + goto out_free; } return sk; + +out_free: + if (slab != NULL) + kmem_cache_free(slab, sk); + else + kfree(sk); + return NULL; } void sk_free(struct sock *sk) diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 87a052a9a84..68a5ca86644 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -146,6 +146,19 @@ int eth_rebuild_header(struct sk_buff *skb) return 0; } +static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b) +{ + const unsigned short *dest = (unsigned short *) __a; + const unsigned short *devaddr = (unsigned short *) __b; + unsigned int res; + + BUILD_BUG_ON(ETH_ALEN != 6); + res = ((dest[0] ^ devaddr[0]) | + (dest[1] ^ devaddr[1]) | + (dest[2] ^ devaddr[2])) != 0; + + return res; +} /* * Determine the packet's protocol ID. The rule here is that we @@ -158,16 +171,15 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) struct ethhdr *eth; unsigned char *rawp; - skb->mac.raw=skb->data; + skb->mac.raw = skb->data; skb_pull(skb,ETH_HLEN); eth = eth_hdr(skb); - if(*eth->h_dest&1) - { - if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) - skb->pkt_type=PACKET_BROADCAST; + if (*eth->h_dest&1) { + if (!compare_eth_addr(eth->h_dest, dev->broadcast)) + skb->pkt_type = PACKET_BROADCAST; else - skb->pkt_type=PACKET_MULTICAST; + skb->pkt_type = PACKET_MULTICAST; } /* @@ -178,10 +190,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) * seems to set IFF_PROMISC. */ - else if(1 /*dev->flags&IFF_PROMISC*/) - { - if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) - skb->pkt_type=PACKET_OTHERHOST; + else if(1 /*dev->flags&IFF_PROMISC*/) { + if (unlikely(compare_eth_addr(eth->h_dest, dev->dev_addr))) + skb->pkt_type = PACKET_OTHERHOST; } if (ntohs(eth->h_proto) >= 1536) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index d6e3d269e90..caf2e2cff29 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -190,15 +190,16 @@ void tcp_select_initial_window(int __space, __u32 mss, } /* Set initial window to value enough for senders, - * following RFC1414. Senders, not following this RFC, + * following RFC2414. Senders, not following this RFC, * will be satisfied with 2. */ if (mss > (1<<*rcv_wscale)) { - int init_cwnd = 4; - if (mss > 1460*3) + int init_cwnd; + + if (mss > 1460) init_cwnd = 2; - else if (mss > 1460) - init_cwnd = 3; + else + init_cwnd = (mss > 1095) ? 3 : 4; if (*rcv_wnd > init_cwnd*mss) *rcv_wnd = init_cwnd*mss; } diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 5acb1680524..829fdbc4400 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1472,22 +1472,25 @@ static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 static int __init rose_proto_init(void) { int i; - int rc = proto_register(&rose_proto, 0); + int rc; + if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { + printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); + rc = -EINVAL; + goto out; + } + + rc = proto_register(&rose_proto, 0); if (rc != 0) goto out; rose_callsign = null_ax25_address; - if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { - printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); - return -1; - } - dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL); if (dev_rose == NULL) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n"); - return -1; + rc = -ENOMEM; + goto out_proto_unregister; } memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*)); @@ -1500,10 +1503,12 @@ static int __init rose_proto_init(void) name, rose_setup); if (!dev) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); + rc = -ENOMEM; goto fail; } - if (register_netdev(dev)) { - printk(KERN_ERR "ROSE: netdevice regeistration failed\n"); + rc = register_netdev(dev); + if (rc) { + printk(KERN_ERR "ROSE: netdevice registration failed\n"); free_netdev(dev); goto fail; } @@ -1536,8 +1541,9 @@ fail: free_netdev(dev_rose[i]); } kfree(dev_rose); +out_proto_unregister: proto_unregister(&rose_proto); - return -ENOMEM; + goto out; } module_init(rose_proto_init); diff --git a/net/socket.c b/net/socket.c index dbd1a6851ed..3145103cdf5 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1145,8 +1145,11 @@ static int __sock_create(int family, int type, int protocol, struct socket **res if (!try_module_get(net_families[family]->owner)) goto out_release; - if ((err = net_families[family]->create(sock, protocol)) < 0) + if ((err = net_families[family]->create(sock, protocol)) < 0) { + sock->ops = NULL; goto out_module_put; + } + /* * Now to bump the refcnt of the [loadable] module that owns this * socket at sock_release time we decrement its refcnt. @@ -1360,16 +1363,16 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _ newsock->type = sock->type; newsock->ops = sock->ops; - err = security_socket_accept(sock, newsock); - if (err) - goto out_release; - /* * We don't need try_module_get here, as the listening socket (sock) * has the protocol module (sock->ops->owner) held. */ __module_get(newsock->ops->owner); + err = security_socket_accept(sock, newsock); + if (err) + goto out_release; + err = sock->ops->accept(sock, newsock, sock->file->f_flags); if (err < 0) goto out_release; |