aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/sock.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2005-09-03 02:44:09 -0400
committerLen Brown <len.brown@intel.com>2005-09-03 02:44:09 -0400
commit129521dcc94f781890f8f668219ab79f0073ff9f (patch)
tree9f70707c88da65577f38814fe37b24c4b4957d64 /net/core/sock.c
parent824b558bbe2c298b165cdb54c33718994dda30bb (diff)
parentf505380ba7b98ec97bf25300c2a58aeae903530b (diff)
Merge linux-2.6 into linux-acpi-2.6 test
Diffstat (limited to 'net/core/sock.c')
-rw-r--r--net/core/sock.c133
1 files changed, 125 insertions, 8 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index 12f6d9a2a522..ccd10fd65682 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -260,7 +260,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
260 260
261 if (val > sysctl_wmem_max) 261 if (val > sysctl_wmem_max)
262 val = sysctl_wmem_max; 262 val = sysctl_wmem_max;
263 263set_sndbuf:
264 sk->sk_userlocks |= SOCK_SNDBUF_LOCK; 264 sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
265 if ((val * 2) < SOCK_MIN_SNDBUF) 265 if ((val * 2) < SOCK_MIN_SNDBUF)
266 sk->sk_sndbuf = SOCK_MIN_SNDBUF; 266 sk->sk_sndbuf = SOCK_MIN_SNDBUF;
@@ -274,6 +274,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
274 sk->sk_write_space(sk); 274 sk->sk_write_space(sk);
275 break; 275 break;
276 276
277 case SO_SNDBUFFORCE:
278 if (!capable(CAP_NET_ADMIN)) {
279 ret = -EPERM;
280 break;
281 }
282 goto set_sndbuf;
283
277 case SO_RCVBUF: 284 case SO_RCVBUF:
278 /* Don't error on this BSD doesn't and if you think 285 /* Don't error on this BSD doesn't and if you think
279 about it this is right. Otherwise apps have to 286 about it this is right. Otherwise apps have to
@@ -282,7 +289,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
282 289
283 if (val > sysctl_rmem_max) 290 if (val > sysctl_rmem_max)
284 val = sysctl_rmem_max; 291 val = sysctl_rmem_max;
285 292set_rcvbuf:
286 sk->sk_userlocks |= SOCK_RCVBUF_LOCK; 293 sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
287 /* FIXME: is this lower bound the right one? */ 294 /* FIXME: is this lower bound the right one? */
288 if ((val * 2) < SOCK_MIN_RCVBUF) 295 if ((val * 2) < SOCK_MIN_RCVBUF)
@@ -291,6 +298,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
291 sk->sk_rcvbuf = val * 2; 298 sk->sk_rcvbuf = val * 2;
292 break; 299 break;
293 300
301 case SO_RCVBUFFORCE:
302 if (!capable(CAP_NET_ADMIN)) {
303 ret = -EPERM;
304 break;
305 }
306 goto set_rcvbuf;
307
294 case SO_KEEPALIVE: 308 case SO_KEEPALIVE:
295#ifdef CONFIG_INET 309#ifdef CONFIG_INET
296 if (sk->sk_protocol == IPPROTO_TCP) 310 if (sk->sk_protocol == IPPROTO_TCP)
@@ -686,6 +700,80 @@ void sk_free(struct sock *sk)
686 module_put(owner); 700 module_put(owner);
687} 701}
688 702
703struct sock *sk_clone(const struct sock *sk, const unsigned int __nocast priority)
704{
705 struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0);
706
707 if (newsk != NULL) {
708 struct sk_filter *filter;
709
710 memcpy(newsk, sk, sk->sk_prot->obj_size);
711
712 /* SANITY */
713 sk_node_init(&newsk->sk_node);
714 sock_lock_init(newsk);
715 bh_lock_sock(newsk);
716
717 atomic_set(&newsk->sk_rmem_alloc, 0);
718 atomic_set(&newsk->sk_wmem_alloc, 0);
719 atomic_set(&newsk->sk_omem_alloc, 0);
720 skb_queue_head_init(&newsk->sk_receive_queue);
721 skb_queue_head_init(&newsk->sk_write_queue);
722
723 rwlock_init(&newsk->sk_dst_lock);
724 rwlock_init(&newsk->sk_callback_lock);
725
726 newsk->sk_dst_cache = NULL;
727 newsk->sk_wmem_queued = 0;
728 newsk->sk_forward_alloc = 0;
729 newsk->sk_send_head = NULL;
730 newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL;
731 newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
732
733 sock_reset_flag(newsk, SOCK_DONE);
734 skb_queue_head_init(&newsk->sk_error_queue);
735
736 filter = newsk->sk_filter;
737 if (filter != NULL)
738 sk_filter_charge(newsk, filter);
739
740 if (unlikely(xfrm_sk_clone_policy(newsk))) {
741 /* It is still raw copy of parent, so invalidate
742 * destructor and make plain sk_free() */
743 newsk->sk_destruct = NULL;
744 sk_free(newsk);
745 newsk = NULL;
746 goto out;
747 }
748
749 newsk->sk_err = 0;
750 newsk->sk_priority = 0;
751 atomic_set(&newsk->sk_refcnt, 2);
752
753 /*
754 * Increment the counter in the same struct proto as the master
755 * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that
756 * is the same as sk->sk_prot->socks, as this field was copied
757 * with memcpy).
758 *
759 * This _changes_ the previous behaviour, where
760 * tcp_create_openreq_child always was incrementing the
761 * equivalent to tcp_prot->socks (inet_sock_nr), so this have
762 * to be taken into account in all callers. -acme
763 */
764 sk_refcnt_debug_inc(newsk);
765 newsk->sk_socket = NULL;
766 newsk->sk_sleep = NULL;
767
768 if (newsk->sk_prot->sockets_allocated)
769 atomic_inc(newsk->sk_prot->sockets_allocated);
770 }
771out:
772 return newsk;
773}
774
775EXPORT_SYMBOL_GPL(sk_clone);
776
689void __init sk_init(void) 777void __init sk_init(void)
690{ 778{
691 if (num_physpages <= 4096) { 779 if (num_physpages <= 4096) {
@@ -1353,11 +1441,7 @@ void sk_common_release(struct sock *sk)
1353 1441
1354 xfrm_sk_free_policy(sk); 1442 xfrm_sk_free_policy(sk);
1355 1443
1356#ifdef INET_REFCNT_DEBUG 1444 sk_refcnt_debug_release(sk);
1357 if (atomic_read(&sk->sk_refcnt) != 1)
1358 printk(KERN_DEBUG "Destruction of the socket %p delayed, c=%d\n",
1359 sk, atomic_read(&sk->sk_refcnt));
1360#endif
1361 sock_put(sk); 1445 sock_put(sk);
1362} 1446}
1363 1447
@@ -1368,7 +1452,8 @@ static LIST_HEAD(proto_list);
1368 1452
1369int proto_register(struct proto *prot, int alloc_slab) 1453int proto_register(struct proto *prot, int alloc_slab)
1370{ 1454{
1371 char *request_sock_slab_name; 1455 char *request_sock_slab_name = NULL;
1456 char *timewait_sock_slab_name;
1372 int rc = -ENOBUFS; 1457 int rc = -ENOBUFS;
1373 1458
1374 if (alloc_slab) { 1459 if (alloc_slab) {
@@ -1399,6 +1484,23 @@ int proto_register(struct proto *prot, int alloc_slab)
1399 goto out_free_request_sock_slab_name; 1484 goto out_free_request_sock_slab_name;
1400 } 1485 }
1401 } 1486 }
1487
1488 if (prot->twsk_obj_size) {
1489 static const char mask[] = "tw_sock_%s";
1490
1491 timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
1492
1493 if (timewait_sock_slab_name == NULL)
1494 goto out_free_request_sock_slab;
1495
1496 sprintf(timewait_sock_slab_name, mask, prot->name);
1497 prot->twsk_slab = kmem_cache_create(timewait_sock_slab_name,
1498 prot->twsk_obj_size,
1499 0, SLAB_HWCACHE_ALIGN,
1500 NULL, NULL);
1501 if (prot->twsk_slab == NULL)
1502 goto out_free_timewait_sock_slab_name;
1503 }
1402 } 1504 }
1403 1505
1404 write_lock(&proto_list_lock); 1506 write_lock(&proto_list_lock);
@@ -1407,6 +1509,13 @@ int proto_register(struct proto *prot, int alloc_slab)
1407 rc = 0; 1509 rc = 0;
1408out: 1510out:
1409 return rc; 1511 return rc;
1512out_free_timewait_sock_slab_name:
1513 kfree(timewait_sock_slab_name);
1514out_free_request_sock_slab:
1515 if (prot->rsk_prot && prot->rsk_prot->slab) {
1516 kmem_cache_destroy(prot->rsk_prot->slab);
1517 prot->rsk_prot->slab = NULL;
1518 }
1410out_free_request_sock_slab_name: 1519out_free_request_sock_slab_name:
1411 kfree(request_sock_slab_name); 1520 kfree(request_sock_slab_name);
1412out_free_sock_slab: 1521out_free_sock_slab:
@@ -1434,6 +1543,14 @@ void proto_unregister(struct proto *prot)
1434 prot->rsk_prot->slab = NULL; 1543 prot->rsk_prot->slab = NULL;
1435 } 1544 }
1436 1545
1546 if (prot->twsk_slab != NULL) {
1547 const char *name = kmem_cache_name(prot->twsk_slab);
1548
1549 kmem_cache_destroy(prot->twsk_slab);
1550 kfree(name);
1551 prot->twsk_slab = NULL;
1552 }
1553
1437 list_del(&prot->node); 1554 list_del(&prot->node);
1438 write_unlock(&proto_list_lock); 1555 write_unlock(&proto_list_lock);
1439} 1556}