X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=net%2Fipv4%2Faf_inet.c;h=760516a56ac6e66acdff3e21c80f226df23d2e6f;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=c4a967b818f8930c545dfc34ac8890472112a418;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index c4a967b81..760516a56 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -122,11 +122,6 @@ atomic_t inet_sock_nr; extern void ip_mc_drop_socket(struct sock *sk); -/* Per protocol sock slabcache */ -kmem_cache_t *tcp_sk_cachep; -static kmem_cache_t *udp_sk_cachep; -static kmem_cache_t *raw4_sk_cachep; - /* The inetsw table contains everything that inet_create needs to * build a new socket. */ @@ -159,7 +154,7 @@ void inet_sock_destruct(struct sock *sk) if (inet->opt) kfree(inet->opt); - + vx_sock_dec(sk); clr_vx_info(&sk->sk_vx_info); sk->sk_xid = -1; @@ -236,28 +231,6 @@ out: return err; } -static __inline__ kmem_cache_t *inet_sk_slab(int protocol) -{ - kmem_cache_t* rc = tcp_sk_cachep; - - if (protocol == IPPROTO_UDP) - rc = udp_sk_cachep; - else if (protocol == IPPROTO_RAW) - rc = raw4_sk_cachep; - return rc; -} - -static __inline__ int inet_sk_size(int protocol) -{ - int rc = sizeof(struct tcp_sock); - - if (protocol == IPPROTO_UDP) - rc = sizeof(struct udp_sock); - else if (protocol == IPPROTO_RAW) - rc = sizeof(struct raw_sock); - return rc; -} - /* * Create an inet socket. */ @@ -268,13 +241,12 @@ static int inet_create(struct socket *sock, int protocol) struct list_head *p; struct inet_protosw *answer; struct inet_opt *inet; - int err = -ENOBUFS; + struct proto *answer_prot; + unsigned char answer_flags; + char answer_no_check; + int err; sock->state = SS_UNCONNECTED; - sk = sk_alloc(PF_INET, GFP_KERNEL, inet_sk_size(protocol), - inet_sk_slab(protocol)); - if (!sk) - goto out; /* Look for the requested type/protocol pair. */ answer = NULL; @@ -300,24 +272,38 @@ static int inet_create(struct socket *sock, int protocol) err = -ESOCKTNOSUPPORT; if (!answer) - goto out_sk_free; + goto out_rcu_unlock; err = -EPERM; if ((protocol == IPPROTO_ICMP) && vx_ccaps(VXC_RAW_ICMP)) goto override; if (answer->capability > 0 && !capable(answer->capability)) - goto out_sk_free; + goto out_rcu_unlock; override: err = -EPROTONOSUPPORT; if (!protocol) - goto out_sk_free; - err = 0; + goto out_rcu_unlock; + sock->ops = answer->ops; - sk->sk_prot = answer->prot; - sk->sk_no_check = answer->no_check; - if (INET_PROTOSW_REUSE & answer->flags) - sk->sk_reuse = 1; + answer_prot = answer->prot; + answer_no_check = answer->no_check; + answer_flags = answer->flags; rcu_read_unlock(); + BUG_TRAP(answer_prot->slab != NULL); + + err = -ENOBUFS; + sk = sk_alloc(PF_INET, GFP_KERNEL, + answer_prot->slab_obj_size, + answer_prot->slab); + if (sk == NULL) + goto out; + + err = 0; + sk->sk_prot = answer_prot; + sk->sk_no_check = answer_no_check; + if (INET_PROTOSW_REUSE & answer_flags) + sk->sk_reuse = 1; + inet = inet_sk(sk); if (SOCK_RAW == sock->type) { @@ -337,11 +323,10 @@ override: sk_set_owner(sk, THIS_MODULE); sk->sk_destruct = inet_sock_destruct; - sk->sk_zapped = 0; sk->sk_family = PF_INET; sk->sk_protocol = protocol; sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; - + set_vx_info(&sk->sk_vx_info, current->vx_info); sk->sk_xid = vx_current_xid(); vx_sock_inc(sk); @@ -376,9 +361,8 @@ override: } out: return err; -out_sk_free: +out_rcu_unlock: rcu_read_unlock(); - sk_free(sk); goto out; } @@ -432,8 +416,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) int chk_addr_ret; int err; __u32 s_addr; /* Address used for validation */ - __u32 s_addr1; - __u32 s_addr2 = 0xffffffffl; /* Optional address of the socket */ + __u32 s_addr1; /* Address used for socket */ + __u32 s_addr2; /* Broadcast address for the socket */ struct nx_info *nxi = sk->sk_nx_info; /* If the socket has its own bind function then use it. (RAW) */ @@ -445,38 +429,41 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len < sizeof(struct sockaddr_in)) goto out; - s_addr = s_addr1 = addr->sin_addr.s_addr; + s_addr = addr->sin_addr.s_addr; + s_addr1 = s_addr; + s_addr2 = 0xffffffffl; + vxdprintk(VXD_CBIT(net, 3), - "inet_bind(%p) %p,%p;%lx", + "inet_bind(%p)* %p,%p;%lx %d.%d.%d.%d", sk, sk->sk_nx_info, sk->sk_socket, - (sk->sk_socket?sk->sk_socket->flags:0)); + (sk->sk_socket?sk->sk_socket->flags:0), + VXD_QUAD(s_addr)); if (nxi) { __u32 v4_bcast = nxi->v4_bcast; __u32 ipv4root = nxi->ipv4[0]; int nbipv4 = nxi->nbipv4; + if (s_addr == 0) { + /* bind to any for 1-n */ s_addr = ipv4root; - if (nbipv4 > 1) - s_addr1 = 0; - else { - s_addr1 = ipv4root; - } + s_addr1 = (nbipv4 > 1) ? 0 : s_addr; s_addr2 = v4_bcast; } else if (s_addr == 0x0100007f) { - s_addr = s_addr1 = ipv4root; + /* rewrite localhost to ipv4root */ + s_addr = ipv4root; + s_addr1 = ipv4root; } else if (s_addr != v4_bcast) { - int i; - for (i=0; iipv4[i]) - break; - } - if (i == nbipv4) { + /* normal address bind */ + if (!addr_in_nx_info(nxi, s_addr)) return -EADDRNOTAVAIL; - } } } chk_addr_ret = inet_addr_type(s_addr); + vxdprintk(VXD_CBIT(net, 3), + "inet_bind(%p) %d.%d.%d.%d, %d.%d.%d.%d, %d.%d.%d.%d", + sk, VXD_QUAD(s_addr), VXD_QUAD(s_addr1), VXD_QUAD(s_addr2)); + /* Not specified by any standard per-se, however it breaks too * many applications when removed. It is unfortunate since * allowing applications to make a non-local bind solves @@ -894,7 +881,7 @@ struct proto_ops inet_dgram_ops = { .sendpage = inet_sendpage, }; -struct net_proto_family inet_family_ops = { +static struct net_proto_family inet_family_ops = { .family = PF_INET, .create = inet_create, .owner = THIS_MODULE, @@ -1067,24 +1054,29 @@ static int __init inet_init(void) struct sk_buff *dummy_skb; struct inet_protosw *q; struct list_head *r; + int rc = -EINVAL; if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "%s: panic\n", __FUNCTION__); - return -EINVAL; + goto out; + } + + rc = sk_alloc_slab(&tcp_prot, "tcp_sock"); + if (rc) { + sk_alloc_slab_error(&tcp_prot); + goto out; + } + rc = sk_alloc_slab(&udp_prot, "udp_sock"); + if (rc) { + sk_alloc_slab_error(&udp_prot); + goto out_tcp_free_slab; + } + rc = sk_alloc_slab(&raw_prot, "raw_sock"); + if (rc) { + sk_alloc_slab_error(&raw_prot); + goto out_udp_free_slab; } - tcp_sk_cachep = kmem_cache_create("tcp_sock", - sizeof(struct tcp_sock), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - udp_sk_cachep = kmem_cache_create("udp_sock", - sizeof(struct udp_sock), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - raw4_sk_cachep = kmem_cache_create("raw4_sock", - sizeof(struct raw_sock), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!tcp_sk_cachep || !udp_sk_cachep || !raw4_sk_cachep) - printk(KERN_CRIT - "inet_init: Can't create protocol sock SLAB caches!\n"); /* * Tell SOCKET that we are alive... */ @@ -1154,7 +1146,14 @@ static int __init inet_init(void) ipfrag_init(); - return 0; + rc = 0; +out: + return rc; +out_tcp_free_slab: + sk_free_slab(&tcp_prot); +out_udp_free_slab: + sk_free_slab(&udp_prot); + goto out; } module_init(inet_init); @@ -1214,7 +1213,6 @@ EXPORT_SYMBOL(inet_accept); EXPORT_SYMBOL(inet_bind); EXPORT_SYMBOL(inet_dgram_connect); EXPORT_SYMBOL(inet_dgram_ops); -EXPORT_SYMBOL(inet_family_ops); EXPORT_SYMBOL(inet_getname); EXPORT_SYMBOL(inet_ioctl); EXPORT_SYMBOL(inet_listen);