diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2012-09-28 13:46:28 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-09-28 14:50:15 -0400 |
commit | daa22703f14c007e93b464c45fa60019a36f546d (patch) | |
tree | a1a130b6e128dc9d57c35c026977e1b4953105e1 /net/ipv4/tcp.c | |
parent | 5aa287dcf1b5879aa0150b0511833c52885f5b4c (diff) |
Apply k4412 kernel from HardKernel for ODROID-X.
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b6ec23c7ffc..31741cf9bb6 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -266,11 +266,15 @@ | |||
266 | #include <linux/crypto.h> | 266 | #include <linux/crypto.h> |
267 | #include <linux/time.h> | 267 | #include <linux/time.h> |
268 | #include <linux/slab.h> | 268 | #include <linux/slab.h> |
269 | #include <linux/uid_stat.h> | ||
269 | 270 | ||
270 | #include <net/icmp.h> | 271 | #include <net/icmp.h> |
271 | #include <net/tcp.h> | 272 | #include <net/tcp.h> |
272 | #include <net/xfrm.h> | 273 | #include <net/xfrm.h> |
273 | #include <net/ip.h> | 274 | #include <net/ip.h> |
275 | #include <net/ip6_route.h> | ||
276 | #include <net/ipv6.h> | ||
277 | #include <net/transp_v6.h> | ||
274 | #include <net/netdma.h> | 278 | #include <net/netdma.h> |
275 | #include <net/sock.h> | 279 | #include <net/sock.h> |
276 | 280 | ||
@@ -1111,6 +1115,9 @@ out: | |||
1111 | if (copied) | 1115 | if (copied) |
1112 | tcp_push(sk, flags, mss_now, tp->nonagle); | 1116 | tcp_push(sk, flags, mss_now, tp->nonagle); |
1113 | release_sock(sk); | 1117 | release_sock(sk); |
1118 | |||
1119 | if (copied > 0) | ||
1120 | uid_stat_tcp_snd(current_uid(), copied); | ||
1114 | return copied; | 1121 | return copied; |
1115 | 1122 | ||
1116 | do_fault: | 1123 | do_fault: |
@@ -1387,8 +1394,11 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
1387 | tcp_rcv_space_adjust(sk); | 1394 | tcp_rcv_space_adjust(sk); |
1388 | 1395 | ||
1389 | /* Clean up data we have read: This will do ACK frames. */ | 1396 | /* Clean up data we have read: This will do ACK frames. */ |
1390 | if (copied > 0) | 1397 | if (copied > 0) { |
1391 | tcp_cleanup_rbuf(sk, copied); | 1398 | tcp_cleanup_rbuf(sk, copied); |
1399 | uid_stat_tcp_rcv(current_uid(), copied); | ||
1400 | } | ||
1401 | |||
1392 | return copied; | 1402 | return copied; |
1393 | } | 1403 | } |
1394 | EXPORT_SYMBOL(tcp_read_sock); | 1404 | EXPORT_SYMBOL(tcp_read_sock); |
@@ -1770,6 +1780,9 @@ skip_copy: | |||
1770 | tcp_cleanup_rbuf(sk, copied); | 1780 | tcp_cleanup_rbuf(sk, copied); |
1771 | 1781 | ||
1772 | release_sock(sk); | 1782 | release_sock(sk); |
1783 | |||
1784 | if (copied > 0) | ||
1785 | uid_stat_tcp_rcv(current_uid(), copied); | ||
1773 | return copied; | 1786 | return copied; |
1774 | 1787 | ||
1775 | out: | 1788 | out: |
@@ -1778,6 +1791,8 @@ out: | |||
1778 | 1791 | ||
1779 | recv_urg: | 1792 | recv_urg: |
1780 | err = tcp_recv_urg(sk, msg, len, flags); | 1793 | err = tcp_recv_urg(sk, msg, len, flags); |
1794 | if (err > 0) | ||
1795 | uid_stat_tcp_rcv(current_uid(), err); | ||
1781 | goto out; | 1796 | goto out; |
1782 | } | 1797 | } |
1783 | EXPORT_SYMBOL(tcp_recvmsg); | 1798 | EXPORT_SYMBOL(tcp_recvmsg); |
@@ -3313,3 +3328,107 @@ void __init tcp_init(void) | |||
3313 | tcp_secret_retiring = &tcp_secret_two; | 3328 | tcp_secret_retiring = &tcp_secret_two; |
3314 | tcp_secret_secondary = &tcp_secret_two; | 3329 | tcp_secret_secondary = &tcp_secret_two; |
3315 | } | 3330 | } |
3331 | |||
3332 | static int tcp_is_local(struct net *net, __be32 addr) { | ||
3333 | struct rtable *rt; | ||
3334 | struct flowi4 fl4 = { .daddr = addr }; | ||
3335 | rt = ip_route_output_key(net, &fl4); | ||
3336 | if (IS_ERR_OR_NULL(rt)) | ||
3337 | return 0; | ||
3338 | return rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK); | ||
3339 | } | ||
3340 | |||
3341 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3342 | static int tcp_is_local6(struct net *net, struct in6_addr *addr) { | ||
3343 | struct rt6_info *rt6 = rt6_lookup(net, addr, addr, 0, 0); | ||
3344 | return rt6 && rt6->rt6i_dev && (rt6->rt6i_dev->flags & IFF_LOOPBACK); | ||
3345 | } | ||
3346 | #endif | ||
3347 | |||
3348 | /* | ||
3349 | * tcp_nuke_addr - destroy all sockets on the given local address | ||
3350 | * if local address is the unspecified address (0.0.0.0 or ::), destroy all | ||
3351 | * sockets with local addresses that are not configured. | ||
3352 | */ | ||
3353 | int tcp_nuke_addr(struct net *net, struct sockaddr *addr) | ||
3354 | { | ||
3355 | int family = addr->sa_family; | ||
3356 | unsigned int bucket; | ||
3357 | |||
3358 | struct in_addr *in; | ||
3359 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3360 | struct in6_addr *in6; | ||
3361 | #endif | ||
3362 | if (family == AF_INET) { | ||
3363 | in = &((struct sockaddr_in *)addr)->sin_addr; | ||
3364 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3365 | } else if (family == AF_INET6) { | ||
3366 | in6 = &((struct sockaddr_in6 *)addr)->sin6_addr; | ||
3367 | #endif | ||
3368 | } else { | ||
3369 | return -EAFNOSUPPORT; | ||
3370 | } | ||
3371 | |||
3372 | for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) { | ||
3373 | struct hlist_nulls_node *node; | ||
3374 | struct sock *sk; | ||
3375 | spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket); | ||
3376 | |||
3377 | restart: | ||
3378 | spin_lock_bh(lock); | ||
3379 | sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) { | ||
3380 | struct inet_sock *inet = inet_sk(sk); | ||
3381 | |||
3382 | if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT) | ||
3383 | continue; | ||
3384 | if (sock_flag(sk, SOCK_DEAD)) | ||
3385 | continue; | ||
3386 | |||
3387 | if (family == AF_INET) { | ||
3388 | __be32 s4 = inet->inet_rcv_saddr; | ||
3389 | if (s4 == LOOPBACK4_IPV6) | ||
3390 | continue; | ||
3391 | |||
3392 | if (in->s_addr != s4 && | ||
3393 | !(in->s_addr == INADDR_ANY && | ||
3394 | !tcp_is_local(net, s4))) | ||
3395 | continue; | ||
3396 | } | ||
3397 | |||
3398 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3399 | if (family == AF_INET6) { | ||
3400 | struct in6_addr *s6; | ||
3401 | if (!inet->pinet6) | ||
3402 | continue; | ||
3403 | |||
3404 | s6 = &inet->pinet6->rcv_saddr; | ||
3405 | if (ipv6_addr_type(s6) == IPV6_ADDR_MAPPED) | ||
3406 | continue; | ||
3407 | |||
3408 | if (!ipv6_addr_equal(in6, s6) && | ||
3409 | !(ipv6_addr_equal(in6, &in6addr_any) && | ||
3410 | !tcp_is_local6(net, s6))) | ||
3411 | continue; | ||
3412 | } | ||
3413 | #endif | ||
3414 | |||
3415 | sock_hold(sk); | ||
3416 | spin_unlock_bh(lock); | ||
3417 | |||
3418 | local_bh_disable(); | ||
3419 | bh_lock_sock(sk); | ||
3420 | sk->sk_err = ETIMEDOUT; | ||
3421 | sk->sk_error_report(sk); | ||
3422 | |||
3423 | tcp_done(sk); | ||
3424 | bh_unlock_sock(sk); | ||
3425 | local_bh_enable(); | ||
3426 | sock_put(sk); | ||
3427 | |||
3428 | goto restart; | ||
3429 | } | ||
3430 | spin_unlock_bh(lock); | ||
3431 | } | ||
3432 | |||
3433 | return 0; | ||
3434 | } | ||