aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2012-09-28 13:46:28 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2012-09-28 14:50:15 -0400
commitdaa22703f14c007e93b464c45fa60019a36f546d (patch)
treea1a130b6e128dc9d57c35c026977e1b4953105e1 /net/ipv4/tcp.c
parent5aa287dcf1b5879aa0150b0511833c52885f5b4c (diff)
Apply k4412 kernel from HardKernel for ODROID-X.
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c121
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
1116do_fault: 1123do_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}
1394EXPORT_SYMBOL(tcp_read_sock); 1404EXPORT_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
1775out: 1788out:
@@ -1778,6 +1791,8 @@ out:
1778 1791
1779recv_urg: 1792recv_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}
1783EXPORT_SYMBOL(tcp_recvmsg); 1798EXPORT_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
3332static 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)
3342static 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 */
3353int 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
3377restart:
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}