Commit 306f0825 authored by David S. Miller's avatar David S. Miller

Merge http://kernel-acme.bkbits.net:8080/net-cleanups-2.5-tcp_ipv4

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 2ab0a8c8 6c1e10b4
...@@ -32,7 +32,8 @@ ...@@ -32,7 +32,8 @@
* and the rest go in the other half. * and the rest go in the other half.
* Andi Kleen : Add support for syncookies and fixed * Andi Kleen : Add support for syncookies and fixed
* some bugs: ip options weren't passed to * some bugs: ip options weren't passed to
* the TCP layer, missed a check for an ACK bit. * the TCP layer, missed a check for an
* ACK bit.
* Andi Kleen : Implemented fast path mtu discovery. * Andi Kleen : Implemented fast path mtu discovery.
* Fixed many serious bugs in the * Fixed many serious bugs in the
* open_request handling and moved * open_request handling and moved
...@@ -42,7 +43,8 @@ ...@@ -42,7 +43,8 @@
* Mike McLagan : Routing by source * Mike McLagan : Routing by source
* Juan Jose Ciarlante: ip_dynaddr bits * Juan Jose Ciarlante: ip_dynaddr bits
* Andi Kleen: various fixes. * Andi Kleen: various fixes.
* Vitaly E. Lavrov : Transparent proxy revived after year coma. * Vitaly E. Lavrov : Transparent proxy revived after year
* coma.
* Andi Kleen : Fix new listen. * Andi Kleen : Fix new listen.
* Andi Kleen : Fix accept error reporting. * Andi Kleen : Fix accept error reporting.
*/ */
...@@ -65,7 +67,7 @@ ...@@ -65,7 +67,7 @@
extern int sysctl_ip_dynaddr; extern int sysctl_ip_dynaddr;
extern int sysctl_ip_default_ttl; extern int sysctl_ip_default_ttl;
int sysctl_tcp_tw_reuse = 0; int sysctl_tcp_tw_reuse;
/* Check TCP sequence numbers in ICMP packets. */ /* Check TCP sequence numbers in ICMP packets. */
#define ICMP_MIN_LENGTH 8 #define ICMP_MIN_LENGTH 8
...@@ -76,15 +78,7 @@ static struct socket *tcp_socket; ...@@ -76,15 +78,7 @@ static struct socket *tcp_socket;
void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
struct sk_buff *skb); struct sk_buff *skb);
/*
* ALL members must be initialised to prevent gcc-2.7.2.3 miscompilation
*/
struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = { struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = {
__tcp_ehash: NULL,
__tcp_bhash: NULL,
__tcp_bhash_size: 0,
__tcp_ehash_size: 0,
__tcp_listening_hash: { NULL, },
__tcp_lhash_lock: RW_LOCK_UNLOCKED, __tcp_lhash_lock: RW_LOCK_UNLOCKED,
__tcp_lhash_users: ATOMIC_INIT(0), __tcp_lhash_users: ATOMIC_INIT(0),
__tcp_lhash_wait: __tcp_lhash_wait:
...@@ -98,14 +92,14 @@ struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = { ...@@ -98,14 +92,14 @@ struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = {
* 32768-61000 * 32768-61000
*/ */
int sysctl_local_port_range[2] = { 1024, 4999 }; int sysctl_local_port_range[2] = { 1024, 4999 };
int tcp_port_rover = (1024 - 1); int tcp_port_rover = 1024 - 1;
static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport, static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
__u32 faddr, __u16 fport) __u32 faddr, __u16 fport)
{ {
int h = ((laddr ^ lport) ^ (faddr ^ fport)); int h = (laddr ^ lport) ^ (faddr ^ fport);
h ^= h>>16; h ^= h >> 16;
h ^= h>>8; h ^= h >> 8;
return h & (tcp_ehash_size - 1); return h & (tcp_ehash_size - 1);
} }
...@@ -126,14 +120,13 @@ static __inline__ int tcp_sk_hashfn(struct sock *sk) ...@@ -126,14 +120,13 @@ static __inline__ int tcp_sk_hashfn(struct sock *sk)
struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head, struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
unsigned short snum) unsigned short snum)
{ {
struct tcp_bind_bucket *tb; struct tcp_bind_bucket *tb = kmem_cache_alloc(tcp_bucket_cachep,
SLAB_ATOMIC);
tb = kmem_cache_alloc(tcp_bucket_cachep, SLAB_ATOMIC); if (tb) {
if(tb != NULL) {
tb->port = snum; tb->port = snum;
tb->fastreuse = 0; tb->fastreuse = 0;
tb->owners = NULL; tb->owners = NULL;
if((tb->next = head->chain) != NULL) if ((tb->next = head->chain) != NULL)
tb->next->pprev = &tb->next; tb->next->pprev = &tb->next;
head->chain = tb; head->chain = tb;
tb->pprev = &head->chain; tb->pprev = &head->chain;
...@@ -154,7 +147,7 @@ static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child) ...@@ -154,7 +147,7 @@ static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
tb->owners->bind_pprev = &child->bind_next; tb->owners->bind_pprev = &child->bind_next;
tb->owners = child; tb->owners = child;
child->bind_pprev = &tb->owners; child->bind_pprev = &tb->owners;
child->prev = (struct sock *) tb; child->prev = (struct sock *)tb;
spin_unlock(&head->lock); spin_unlock(&head->lock);
} }
...@@ -165,14 +158,15 @@ __inline__ void tcp_inherit_port(struct sock *sk, struct sock *child) ...@@ -165,14 +158,15 @@ __inline__ void tcp_inherit_port(struct sock *sk, struct sock *child)
local_bh_enable(); local_bh_enable();
} }
static inline void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, unsigned short snum) static inline void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb,
unsigned short snum)
{ {
inet_sk(sk)->num = snum; inet_sk(sk)->num = snum;
if ((sk->bind_next = tb->owners) != NULL) if ((sk->bind_next = tb->owners) != NULL)
tb->owners->bind_pprev = &sk->bind_next; tb->owners->bind_pprev = &sk->bind_next;
tb->owners = sk; tb->owners = sk;
sk->bind_pprev = &tb->owners; sk->bind_pprev = &tb->owners;
sk->prev = (struct sock *) tb; sk->prev = (struct sock *)tb;
} }
static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
...@@ -181,16 +175,13 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) ...@@ -181,16 +175,13 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
struct sock *sk2 = tb->owners; struct sock *sk2 = tb->owners;
int sk_reuse = sk->reuse; int sk_reuse = sk->reuse;
for( ; sk2 != NULL; sk2 = sk2->bind_next) { for ( ; sk2; sk2 = sk2->bind_next) {
if (sk != sk2 && if (sk != sk2 && sk->bound_dev_if == sk2->bound_dev_if) {
sk->bound_dev_if == sk2->bound_dev_if) { if (!sk_reuse || !sk2->reuse ||
if (!sk_reuse ||
!sk2->reuse ||
sk2->state == TCP_LISTEN) { sk2->state == TCP_LISTEN) {
struct inet_opt *inet2 = inet_sk(sk2); struct inet_opt *inet2 = inet_sk(sk2);
if (!inet2->rcv_saddr || if (!inet2->rcv_saddr || !inet->rcv_saddr ||
!inet->rcv_saddr || inet2->rcv_saddr == inet->rcv_saddr)
(inet2->rcv_saddr == inet->rcv_saddr))
break; break;
} }
} }
...@@ -208,7 +199,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -208,7 +199,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
int ret; int ret;
local_bh_disable(); local_bh_disable();
if (snum == 0) { if (!snum) {
int low = sysctl_local_port_range[0]; int low = sysctl_local_port_range[0];
int high = sysctl_local_port_range[1]; int high = sysctl_local_port_range[1];
int remaining = (high - low) + 1; int remaining = (high - low) + 1;
...@@ -216,8 +207,9 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -216,8 +207,9 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
spin_lock(&tcp_portalloc_lock); spin_lock(&tcp_portalloc_lock);
rover = tcp_port_rover; rover = tcp_port_rover;
do { rover++; do {
if ((rover < low) || (rover > high)) rover++;
if (rover < low || rover > high)
rover = low; rover = low;
head = &tcp_bhash[tcp_bhashfn(rover)]; head = &tcp_bhash[tcp_bhashfn(rover)];
spin_lock(&head->lock); spin_lock(&head->lock);
...@@ -244,14 +236,14 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -244,14 +236,14 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
} else { } else {
head = &tcp_bhash[tcp_bhashfn(snum)]; head = &tcp_bhash[tcp_bhashfn(snum)];
spin_lock(&head->lock); spin_lock(&head->lock);
for (tb = head->chain; tb != NULL; tb = tb->next) for (tb = head->chain; tb; tb = tb->next)
if (tb->port == snum) if (tb->port == snum)
break; break;
} }
if (tb != NULL && tb->owners != NULL) { if (tb && tb->owners) {
if (sk->reuse > 1) if (sk->reuse > 1)
goto success; goto success;
if (tb->fastreuse > 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) { if (tb->fastreuse > 0 && sk->reuse && sk->state != TCP_LISTEN) {
goto success; goto success;
} else { } else {
ret = 1; ret = 1;
...@@ -260,21 +252,19 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -260,21 +252,19 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
} }
} }
ret = 1; ret = 1;
if (tb == NULL && if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL)
(tb = tcp_bucket_create(head, snum)) == NULL)
goto fail_unlock; goto fail_unlock;
if (tb->owners == NULL) { if (!tb->owners) {
if (sk->reuse && sk->state != TCP_LISTEN) if (sk->reuse && sk->state != TCP_LISTEN)
tb->fastreuse = 1; tb->fastreuse = 1;
else else
tb->fastreuse = 0; tb->fastreuse = 0;
} else if (tb->fastreuse && } else if (tb->fastreuse && (!sk->reuse || sk->state == TCP_LISTEN))
((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
tb->fastreuse = 0; tb->fastreuse = 0;
success: success:
if (sk->prev == NULL) if (!sk->prev)
tcp_bind_hash(sk, tb, snum); tcp_bind_hash(sk, tb, snum);
BUG_TRAP(sk->prev == (struct sock *) tb); BUG_TRAP(sk->prev == (struct sock *)tb);
ret = 0; ret = 0;
fail_unlock: fail_unlock:
...@@ -300,7 +290,7 @@ __inline__ void __tcp_put_port(struct sock *sk) ...@@ -300,7 +290,7 @@ __inline__ void __tcp_put_port(struct sock *sk)
*(sk->bind_pprev) = sk->bind_next; *(sk->bind_pprev) = sk->bind_next;
sk->prev = NULL; sk->prev = NULL;
inet->num = 0; inet->num = 0;
if (tb->owners == NULL) { if (!tb->owners) {
if (tb->next) if (tb->next)
tb->next->pprev = tb->pprev; tb->next->pprev = tb->pprev;
*(tb->pprev) = tb->next; *(tb->pprev) = tb->next;
...@@ -333,7 +323,7 @@ void tcp_listen_wlock(void) ...@@ -333,7 +323,7 @@ void tcp_listen_wlock(void)
add_wait_queue_exclusive(&tcp_lhash_wait, &wait); add_wait_queue_exclusive(&tcp_lhash_wait, &wait);
for (;;) { for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
if (atomic_read(&tcp_lhash_users) == 0) if (!atomic_read(&tcp_lhash_users))
break; break;
write_unlock_bh(&tcp_lhash_lock); write_unlock_bh(&tcp_lhash_lock);
schedule(); schedule();
...@@ -350,8 +340,8 @@ static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible) ...@@ -350,8 +340,8 @@ static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible)
struct sock **skp; struct sock **skp;
rwlock_t *lock; rwlock_t *lock;
BUG_TRAP(sk->pprev==NULL); BUG_TRAP(!sk->pprev);
if(listen_possible && sk->state == TCP_LISTEN) { if (listen_possible && sk->state == TCP_LISTEN) {
skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)]; skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
lock = &tcp_lhash_lock; lock = &tcp_lhash_lock;
tcp_listen_wlock(); tcp_listen_wlock();
...@@ -360,7 +350,7 @@ static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible) ...@@ -360,7 +350,7 @@ static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible)
lock = &tcp_ehash[sk->hashent].lock; lock = &tcp_ehash[sk->hashent].lock;
write_lock(lock); write_lock(lock);
} }
if((sk->next = *skp) != NULL) if ((sk->next = *skp) != NULL)
(*skp)->pprev = &sk->next; (*skp)->pprev = &sk->next;
*skp = sk; *skp = sk;
sk->pprev = skp; sk->pprev = skp;
...@@ -396,8 +386,8 @@ void tcp_unhash(struct sock *sk) ...@@ -396,8 +386,8 @@ void tcp_unhash(struct sock *sk)
write_lock_bh(&head->lock); write_lock_bh(&head->lock);
} }
if(sk->pprev) { if (sk->pprev) {
if(sk->next) if (sk->next)
sk->next->pprev = sk->pprev; sk->next->pprev = sk->pprev;
*sk->pprev = sk->next; *sk->pprev = sk->next;
sk->pprev = NULL; sk->pprev = NULL;
...@@ -416,20 +406,21 @@ void tcp_unhash(struct sock *sk) ...@@ -416,20 +406,21 @@ void tcp_unhash(struct sock *sk)
* connection. So always assume those are both wildcarded * connection. So always assume those are both wildcarded
* during the search since they can never be otherwise. * during the search since they can never be otherwise.
*/ */
static struct sock *__tcp_v4_lookup_listener(struct sock *sk, u32 daddr, unsigned short hnum, int dif) static struct sock *__tcp_v4_lookup_listener(struct sock *sk, u32 daddr,
unsigned short hnum, int dif)
{ {
struct sock *result = NULL; struct sock *result = NULL;
int score, hiscore; int score, hiscore;
hiscore=0; hiscore=0;
for(; sk; sk = sk->next) { for (; sk; sk = sk->next) {
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
if(inet->num == hnum) { if (inet->num == hnum) {
__u32 rcv_saddr = inet->rcv_saddr; __u32 rcv_saddr = inet->rcv_saddr;
score = 1; score = 1;
if(rcv_saddr) { if (rcv_saddr) {
if (rcv_saddr != daddr) if (rcv_saddr != daddr)
continue; continue;
score++; score++;
...@@ -451,7 +442,8 @@ static struct sock *__tcp_v4_lookup_listener(struct sock *sk, u32 daddr, unsigne ...@@ -451,7 +442,8 @@ static struct sock *__tcp_v4_lookup_listener(struct sock *sk, u32 daddr, unsigne
} }
/* Optimize the common listener case. */ /* Optimize the common listener case. */
__inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int dif) __inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum,
int dif)
{ {
struct sock *sk; struct sock *sk;
...@@ -460,8 +452,7 @@ __inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, i ...@@ -460,8 +452,7 @@ __inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, i
if (sk) { if (sk) {
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
if (inet->num == hnum && if (inet->num == hnum && !sk->next &&
sk->next == NULL &&
(!inet->rcv_saddr || inet->rcv_saddr == daddr) && (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
!sk->bound_dev_if) !sk->bound_dev_if)
goto sherry_cache; goto sherry_cache;
...@@ -482,53 +473,47 @@ __inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, i ...@@ -482,53 +473,47 @@ __inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, i
*/ */
static inline struct sock *__tcp_v4_lookup_established(u32 saddr, u16 sport, static inline struct sock *__tcp_v4_lookup_established(u32 saddr, u16 sport,
u32 daddr, u16 hnum, int dif) u32 daddr, u16 hnum,
int dif)
{ {
struct tcp_ehash_bucket *head; struct tcp_ehash_bucket *head;
TCP_V4_ADDR_COOKIE(acookie, saddr, daddr) TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
__u32 ports = TCP_COMBINED_PORTS(sport, hnum); __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
struct sock *sk; struct sock *sk;
int hash;
/* Optimize here for direct hit, only listening connections can /* Optimize here for direct hit, only listening connections can
* have wildcards anyways. * have wildcards anyways.
*/ */
hash = tcp_hashfn(daddr, hnum, saddr, sport); int hash = tcp_hashfn(daddr, hnum, saddr, sport);
head = &tcp_ehash[hash]; head = &tcp_ehash[hash];
read_lock(&head->lock); read_lock(&head->lock);
for(sk = head->chain; sk; sk = sk->next) { for (sk = head->chain; sk; sk = sk->next) {
if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif)) if (TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
goto hit; /* You sunk my battleship! */ goto hit; /* You sunk my battleship! */
} }
/* Must check for a TIME_WAIT'er before going to listener hash. */ /* Must check for a TIME_WAIT'er before going to listener hash. */
for(sk = (head + tcp_ehash_size)->chain; sk; sk = sk->next) for (sk = (head + tcp_ehash_size)->chain; sk; sk = sk->next)
if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif)) if (TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
goto hit; goto hit;
out:
read_unlock(&head->lock); read_unlock(&head->lock);
return sk;
return NULL;
hit: hit:
sock_hold(sk); sock_hold(sk);
read_unlock(&head->lock); goto out;
return sk;
} }
static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport, static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport,
u32 daddr, u16 hnum, int dif) u32 daddr, u16 hnum, int dif)
{ {
struct sock *sk; struct sock *sk = __tcp_v4_lookup_established(saddr, sport,
daddr, hnum, dif);
sk = __tcp_v4_lookup_established(saddr, sport, daddr, hnum, dif); return sk ? : tcp_v4_lookup_listener(daddr, hnum, dif);
if (sk)
return sk;
return tcp_v4_lookup_listener(daddr, hnum, dif);
} }
__inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif) __inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr,
u16 dport, int dif)
{ {
struct sock *sk; struct sock *sk;
...@@ -565,11 +550,11 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport, ...@@ -565,11 +550,11 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
write_lock(&head->lock); write_lock(&head->lock);
/* Check TIME-WAIT sockets first. */ /* Check TIME-WAIT sockets first. */
for(skp = &(head + tcp_ehash_size)->chain; (sk2=*skp) != NULL; for (skp = &(head + tcp_ehash_size)->chain; (sk2 = *skp) != NULL;
skp = &sk2->next) { skp = &sk2->next) {
tw = (struct tcp_tw_bucket*)sk2; tw = (struct tcp_tw_bucket *)sk2;
if(TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif)) { if (TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
struct tcp_opt *tp = tcp_sk(sk); struct tcp_opt *tp = tcp_sk(sk);
/* With PAWS, it is safe from the viewpoint /* With PAWS, it is safe from the viewpoint
...@@ -588,7 +573,8 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport, ...@@ -588,7 +573,8 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
*/ */
if (tw->ts_recent_stamp && if (tw->ts_recent_stamp &&
(!twp || (sysctl_tcp_tw_reuse && (!twp || (sysctl_tcp_tw_reuse &&
xtime.tv_sec - tw->ts_recent_stamp > 1))) { xtime.tv_sec -
tw->ts_recent_stamp > 1))) {
if ((tp->write_seq = if ((tp->write_seq =
tw->snd_nxt + 65535 + 2) == 0) tw->snd_nxt + 65535 + 2) == 0)
tp->write_seq = 1; tp->write_seq = 1;
...@@ -604,8 +590,8 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport, ...@@ -604,8 +590,8 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
tw = NULL; tw = NULL;
/* And established part... */ /* And established part... */
for(skp = &head->chain; (sk2=*skp)!=NULL; skp = &sk2->next) { for (skp = &head->chain; (sk2 = *skp) != NULL; skp = &sk2->next) {
if(TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif)) if (TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif))
goto not_unique; goto not_unique;
} }
...@@ -614,7 +600,7 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport, ...@@ -614,7 +600,7 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
* in hash table socket with a funny identity. */ * in hash table socket with a funny identity. */
inet->num = lport; inet->num = lport;
inet->sport = htons(lport); inet->sport = htons(lport);
BUG_TRAP(sk->pprev==NULL); BUG_TRAP(!sk->pprev);
if ((sk->next = *skp) != NULL) if ((sk->next = *skp) != NULL)
(*skp)->pprev = &sk->next; (*skp)->pprev = &sk->next;
...@@ -651,8 +637,9 @@ static int tcp_v4_hash_connect(struct sock *sk) ...@@ -651,8 +637,9 @@ static int tcp_v4_hash_connect(struct sock *sk)
unsigned short snum = inet_sk(sk)->num; unsigned short snum = inet_sk(sk)->num;
struct tcp_bind_hashbucket *head; struct tcp_bind_hashbucket *head;
struct tcp_bind_bucket *tb; struct tcp_bind_bucket *tb;
int ret;
if (snum == 0) { if (!snum) {
int rover; int rover;
int low = sysctl_local_port_range[0]; int low = sysctl_local_port_range[0];
int high = sysctl_local_port_range[1]; int high = sysctl_local_port_range[1];
...@@ -690,10 +677,12 @@ static int tcp_v4_hash_connect(struct sock *sk) ...@@ -690,10 +677,12 @@ static int tcp_v4_hash_connect(struct sock *sk)
*/ */
for (tb = head->chain; tb; tb = tb->next) { for (tb = head->chain; tb; tb = tb->next) {
if (tb->port == rover) { if (tb->port == rover) {
BUG_TRAP(tb->owners != NULL); BUG_TRAP(tb->owners);
if (tb->fastreuse >= 0) if (tb->fastreuse >= 0)
goto next_port; goto next_port;
if (!__tcp_v4_check_established(sk, rover, &tw)) if (!__tcp_v4_check_established(sk,
rover,
&tw))
goto ok; goto ok;
goto next_port; goto next_port;
} }
...@@ -717,7 +706,7 @@ static int tcp_v4_hash_connect(struct sock *sk) ...@@ -717,7 +706,7 @@ static int tcp_v4_hash_connect(struct sock *sk)
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
ok: ok:
/* All locks still held and bhs disabled */ /* All locks still held and bhs disabled */
tcp_port_rover = rover; tcp_port_rover = rover;
spin_unlock(&tcp_portalloc_lock); spin_unlock(&tcp_portalloc_lock);
...@@ -735,22 +724,22 @@ static int tcp_v4_hash_connect(struct sock *sk) ...@@ -735,22 +724,22 @@ static int tcp_v4_hash_connect(struct sock *sk)
tcp_tw_put(tw); tcp_tw_put(tw);
} }
local_bh_enable(); ret = 0;
return 0; goto out;
} }
head = &tcp_bhash[tcp_bhashfn(snum)]; head = &tcp_bhash[tcp_bhashfn(snum)];
tb = (struct tcp_bind_bucket *)sk->prev; tb = (struct tcp_bind_bucket *)sk->prev;
spin_lock_bh(&head->lock); spin_lock_bh(&head->lock);
if (tb->owners == sk && sk->bind_next == NULL) { if (tb->owners == sk && !sk->bind_next) {
__tcp_v4_hash(sk, 0); __tcp_v4_hash(sk, 0);
spin_unlock_bh(&head->lock); spin_unlock_bh(&head->lock);
return 0; return 0;
} else { } else {
int ret;
spin_unlock(&head->lock); spin_unlock(&head->lock);
/* No definite answer... Walk to established hash table */ /* No definite answer... Walk to established hash table */
ret = __tcp_v4_check_established(sk, snum, NULL); ret = __tcp_v4_check_established(sk, snum, NULL);
out:
local_bh_enable(); local_bh_enable();
return ret; return ret;
} }
...@@ -761,21 +750,21 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -761,21 +750,21 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{ {
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct tcp_opt *tp = tcp_sk(sk); struct tcp_opt *tp = tcp_sk(sk);
struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
struct rtable *rt; struct rtable *rt;
u32 daddr, nexthop; u32 daddr, nexthop;
int tmp; int tmp;
int err; int err;
if (addr_len < sizeof(struct sockaddr_in)) if (addr_len < sizeof(struct sockaddr_in))
return(-EINVAL); return -EINVAL;
if (usin->sin_family != AF_INET) if (usin->sin_family != AF_INET)
return(-EAFNOSUPPORT); return -EAFNOSUPPORT;
nexthop = daddr = usin->sin_addr.s_addr; nexthop = daddr = usin->sin_addr.s_addr;
if (inet->opt && inet->opt->srr) { if (inet->opt && inet->opt->srr) {
if (daddr == 0) if (!daddr)
return -EINVAL; return -EINVAL;
nexthop = inet->opt->faddr; nexthop = inet->opt->faddr;
} }
...@@ -785,7 +774,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -785,7 +774,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (tmp < 0) if (tmp < 0)
return tmp; return tmp;
if (rt->rt_flags&(RTCF_MULTICAST|RTCF_BROADCAST)) { if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
ip_rt_put(rt); ip_rt_put(rt);
return -ENETUNREACH; return -ENETUNREACH;
} }
...@@ -808,8 +797,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -808,8 +797,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
} }
if (sysctl_tcp_tw_recycle && if (sysctl_tcp_tw_recycle &&
!tp->ts_recent_stamp && !tp->ts_recent_stamp && rt->rt_dst == daddr) {
rt->rt_dst == daddr) {
struct inet_peer *peer = rt_get_peer(rt); struct inet_peer *peer = rt_get_peer(rt);
/* VJ's idea. We save last timestamp seen from /* VJ's idea. We save last timestamp seen from
...@@ -866,15 +854,15 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -866,15 +854,15 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
static __inline__ int tcp_v4_iif(struct sk_buff *skb) static __inline__ int tcp_v4_iif(struct sk_buff *skb)
{ {
return ((struct rtable*)skb->dst)->rt_iif; return ((struct rtable *)skb->dst)->rt_iif;
} }
static __inline__ unsigned tcp_v4_synq_hash(u32 raddr, u16 rport) static __inline__ unsigned tcp_v4_synq_hash(u32 raddr, u16 rport)
{ {
unsigned h = raddr ^ rport; unsigned h = raddr ^ rport;
h ^= h>>16; h ^= h >> 16;
h ^= h>>8; h ^= h >> 8;
return h&(TCP_SYNQ_HSIZE-1); return h & (TCP_SYNQ_HSIZE - 1);
} }
static struct open_request *tcp_v4_search_req(struct tcp_opt *tp, static struct open_request *tcp_v4_search_req(struct tcp_opt *tp,
...@@ -892,13 +880,13 @@ static struct open_request *tcp_v4_search_req(struct tcp_opt *tp, ...@@ -892,13 +880,13 @@ static struct open_request *tcp_v4_search_req(struct tcp_opt *tp,
req->af.v4_req.rmt_addr == raddr && req->af.v4_req.rmt_addr == raddr &&
req->af.v4_req.loc_addr == laddr && req->af.v4_req.loc_addr == laddr &&
TCP_INET_FAMILY(req->class->family)) { TCP_INET_FAMILY(req->class->family)) {
BUG_TRAP(req->sk == NULL); BUG_TRAP(!req->sk);
*prevp = prev; *prevp = prev;
return req; break;
} }
} }
return NULL; return req;
} }
static void tcp_v4_synq_add(struct sock *sk, struct open_request *req) static void tcp_v4_synq_add(struct sock *sk, struct open_request *req)
...@@ -985,8 +973,8 @@ static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, ...@@ -985,8 +973,8 @@ static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *iph,
void tcp_v4_err(struct sk_buff *skb, u32 info) void tcp_v4_err(struct sk_buff *skb, u32 info)
{ {
struct iphdr *iph = (struct iphdr*)skb->data; struct iphdr *iph = (struct iphdr *)skb->data;
struct tcphdr *th = (struct tcphdr*)(skb->data+(iph->ihl<<2)); struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
struct tcp_opt *tp; struct tcp_opt *tp;
struct inet_opt *inet; struct inet_opt *inet;
int type = skb->h.icmph->type; int type = skb->h.icmph->type;
...@@ -1000,13 +988,14 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1000,13 +988,14 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
return; return;
} }
sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, th->source, tcp_v4_iif(skb)); sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr,
if (sk == NULL) { th->source, tcp_v4_iif(skb));
if (!sk) {
ICMP_INC_STATS_BH(IcmpInErrors); ICMP_INC_STATS_BH(IcmpInErrors);
return; return;
} }
if (sk->state == TCP_TIME_WAIT) { if (sk->state == TCP_TIME_WAIT) {
tcp_tw_put((struct tcp_tw_bucket*)sk); tcp_tw_put((struct tcp_tw_bucket *)sk);
return; return;
} }
...@@ -1014,7 +1003,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1014,7 +1003,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
/* If too many ICMPs get dropped on busy /* If too many ICMPs get dropped on busy
* servers this needs to be solved differently. * servers this needs to be solved differently.
*/ */
if (sk->lock.users != 0) if (sk->lock.users)
NET_INC_STATS_BH(LockDroppedIcmps); NET_INC_STATS_BH(LockDroppedIcmps);
if (sk->state == TCP_CLOSE) if (sk->state == TCP_CLOSE)
...@@ -1033,7 +1022,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1033,7 +1022,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
/* This is deprecated, but if someone generated it, /* This is deprecated, but if someone generated it,
* we have no reasons to ignore it. * we have no reasons to ignore it.
*/ */
if (sk->lock.users == 0) if (!sk->lock.users)
tcp_enter_cwr(tp); tcp_enter_cwr(tp);
goto out; goto out;
case ICMP_PARAMETERPROB: case ICMP_PARAMETERPROB:
...@@ -1044,7 +1033,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1044,7 +1033,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
goto out; goto out;
if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
if (sk->lock.users == 0) if (!sk->lock.users)
do_pmtu_discovery(sk, iph, info); do_pmtu_discovery(sk, iph, info);
goto out; goto out;
} }
...@@ -1061,11 +1050,10 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1061,11 +1050,10 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
switch (sk->state) { switch (sk->state) {
struct open_request *req, **prev; struct open_request *req, **prev;
case TCP_LISTEN: case TCP_LISTEN:
if (sk->lock.users != 0) if (sk->lock.users)
goto out; goto out;
req = tcp_v4_search_req(tp, &prev, req = tcp_v4_search_req(tp, &prev, th->dest,
th->dest,
iph->daddr, iph->saddr); iph->daddr, iph->saddr);
if (!req) if (!req)
goto out; goto out;
...@@ -1073,7 +1061,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1073,7 +1061,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
/* ICMPs are not backlogged, hence we cannot get /* ICMPs are not backlogged, hence we cannot get
an established socket here. an established socket here.
*/ */
BUG_TRAP(req->sk == NULL); BUG_TRAP(!req->sk);
if (seq != req->snt_isn) { if (seq != req->snt_isn) {
NET_INC_STATS_BH(OutOfWindowIcmps); NET_INC_STATS_BH(OutOfWindowIcmps);
...@@ -1093,7 +1081,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1093,7 +1081,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
case TCP_SYN_RECV: /* Cannot happen. case TCP_SYN_RECV: /* Cannot happen.
It can f.e. if SYNs crossed. It can f.e. if SYNs crossed.
*/ */
if (sk->lock.users == 0) { if (!sk->lock.users) {
TCP_INC_STATS_BH(TcpAttemptFails); TCP_INC_STATS_BH(TcpAttemptFails);
sk->err = err; sk->err = err;
...@@ -1123,7 +1111,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) ...@@ -1123,7 +1111,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
*/ */
inet = inet_sk(sk); inet = inet_sk(sk);
if (sk->lock.users == 0 && inet->recverr) { if (!sk->lock.users && inet->recverr) {
sk->err = err; sk->err = err;
sk->error_report(sk); sk->error_report(sk);
} else { /* Only an error on timeout */ } else { /* Only an error on timeout */
...@@ -1146,7 +1134,9 @@ void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, ...@@ -1146,7 +1134,9 @@ void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
skb->csum = offsetof(struct tcphdr, check); skb->csum = offsetof(struct tcphdr, check);
} else { } else {
th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr,
csum_partial((char *)th, th->doff<<2, skb->csum)); csum_partial((char *)th,
th->doff << 2,
skb->csum));
} }
} }
...@@ -1173,22 +1163,22 @@ static void tcp_v4_send_reset(struct sk_buff *skb) ...@@ -1173,22 +1163,22 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
if (th->rst) if (th->rst)
return; return;
if (((struct rtable*)skb->dst)->rt_type != RTN_LOCAL) if (((struct rtable *)skb->dst)->rt_type != RTN_LOCAL)
return; return;
/* Swap the send and the receive. */ /* Swap the send and the receive. */
memset(&rth, 0, sizeof(struct tcphdr)); memset(&rth, 0, sizeof(struct tcphdr));
rth.dest = th->source; rth.dest = th->source;
rth.source = th->dest; rth.source = th->dest;
rth.doff = sizeof(struct tcphdr)/4; rth.doff = sizeof(struct tcphdr) / 4;
rth.rst = 1; rth.rst = 1;
if (th->ack) { if (th->ack) {
rth.seq = th->ack_seq; rth.seq = th->ack_seq;
} else { } else {
rth.ack = 1; rth.ack = 1;
rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
+ skb->len - (th->doff<<2)); skb->len - (th->doff << 2));
} }
memset(&arg, 0, sizeof arg); memset(&arg, 0, sizeof arg);
...@@ -1196,9 +1186,7 @@ static void tcp_v4_send_reset(struct sk_buff *skb) ...@@ -1196,9 +1186,7 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
arg.iov[0].iov_len = sizeof rth; arg.iov[0].iov_len = sizeof rth;
arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
skb->nh.iph->saddr, /*XXX*/ skb->nh.iph->saddr, /*XXX*/
sizeof(struct tcphdr), sizeof(struct tcphdr), IPPROTO_TCP, 0);
IPPROTO_TCP,
0);
arg.n_iov = 1; arg.n_iov = 1;
arg.csumoffset = offsetof(struct tcphdr, check) / 2; arg.csumoffset = offsetof(struct tcphdr, check) / 2;
...@@ -1213,7 +1201,8 @@ static void tcp_v4_send_reset(struct sk_buff *skb) ...@@ -1213,7 +1201,8 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
outside socket context is ugly, certainly. What can I do? outside socket context is ugly, certainly. What can I do?
*/ */
static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
u32 win, u32 ts)
{ {
struct tcphdr *th = skb->h.th; struct tcphdr *th = skb->h.th;
struct { struct {
...@@ -1229,8 +1218,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ...@@ -1229,8 +1218,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
arg.iov[0].iov_len = sizeof(rep.th); arg.iov[0].iov_len = sizeof(rep.th);
arg.n_iov = 1; arg.n_iov = 1;
if (ts) { if (ts) {
rep.tsopt[0] = __constant_htonl((TCPOPT_NOP << 24) | rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
(TCPOPT_NOP << 16) |
(TCPOPT_TIMESTAMP << 8) | (TCPOPT_TIMESTAMP << 8) |
TCPOLEN_TIMESTAMP); TCPOLEN_TIMESTAMP);
rep.tsopt[1] = htonl(tcp_time_stamp); rep.tsopt[1] = htonl(tcp_time_stamp);
...@@ -1241,7 +1229,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ...@@ -1241,7 +1229,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
/* Swap the send and the receive. */ /* Swap the send and the receive. */
rep.th.dest = th->source; rep.th.dest = th->source;
rep.th.source = th->dest; rep.th.source = th->dest;
rep.th.doff = arg.iov[0].iov_len/4; rep.th.doff = arg.iov[0].iov_len / 4;
rep.th.seq = htonl(seq); rep.th.seq = htonl(seq);
rep.th.ack_seq = htonl(ack); rep.th.ack_seq = htonl(ack);
rep.th.ack = 1; rep.th.ack = 1;
...@@ -1249,9 +1237,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ...@@ -1249,9 +1237,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
skb->nh.iph->saddr, /*XXX*/ skb->nh.iph->saddr, /*XXX*/
arg.iov[0].iov_len, arg.iov[0].iov_len, IPPROTO_TCP, 0);
IPPROTO_TCP,
0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2; arg.csumoffset = offsetof(struct tcphdr, check) / 2;
ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len); ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
...@@ -1264,25 +1250,24 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) ...@@ -1264,25 +1250,24 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk; struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
tcp_v4_send_ack(skb, tw->snd_nxt, tw->rcv_nxt, tcp_v4_send_ack(skb, tw->snd_nxt, tw->rcv_nxt,
tw->rcv_wnd>>tw->rcv_wscale, tw->ts_recent); tw->rcv_wnd >> tw->rcv_wscale, tw->ts_recent);
tcp_tw_put(tw); tcp_tw_put(tw);
} }
static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req) static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req)
{ {
tcp_v4_send_ack(skb, req->snt_isn+1, req->rcv_isn+1, req->rcv_wnd, tcp_v4_send_ack(skb, req->snt_isn + 1, req->rcv_isn + 1, req->rcv_wnd,
req->ts_recent); req->ts_recent);
} }
static struct dst_entry* tcp_v4_route_req(struct sock *sk, struct open_request *req) static struct dst_entry* tcp_v4_route_req(struct sock *sk,
struct open_request *req)
{ {
struct rtable *rt; struct rtable *rt;
struct ip_options *opt; struct ip_options *opt = req->af.v4_req.opt;
opt = req->af.v4_req.opt; if (ip_route_output(&rt, ((opt && opt->srr) ? opt->faddr :
if(ip_route_output(&rt, ((opt && opt->srr) ?
opt->faddr :
req->af.v4_req.rmt_addr), req->af.v4_req.rmt_addr),
req->af.v4_req.loc_addr, req->af.v4_req.loc_addr,
RT_CONN_FLAGS(sk), sk->bound_dev_if)) { RT_CONN_FLAGS(sk), sk->bound_dev_if)) {
...@@ -1309,8 +1294,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct open_request *req, ...@@ -1309,8 +1294,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct open_request *req,
struct sk_buff * skb; struct sk_buff * skb;
/* First, grab a route. */ /* First, grab a route. */
if (dst == NULL && if (!dst && (dst = tcp_v4_route_req(sk, req)) == NULL)
(dst = tcp_v4_route_req(sk, req)) == NULL)
goto out; goto out;
skb = tcp_make_synack(sk, dst, req); skb = tcp_make_synack(sk, dst, req);
...@@ -1319,11 +1303,14 @@ static int tcp_v4_send_synack(struct sock *sk, struct open_request *req, ...@@ -1319,11 +1303,14 @@ static int tcp_v4_send_synack(struct sock *sk, struct open_request *req,
struct tcphdr *th = skb->h.th; struct tcphdr *th = skb->h.th;
th->check = tcp_v4_check(th, skb->len, th->check = tcp_v4_check(th, skb->len,
req->af.v4_req.loc_addr, req->af.v4_req.rmt_addr, req->af.v4_req.loc_addr,
csum_partial((char *)th, skb->len, skb->csum)); req->af.v4_req.rmt_addr,
csum_partial((char *)th, skb->len,
skb->csum));
err = ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr, err = ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr,
req->af.v4_req.rmt_addr, req->af.v4_req.opt); req->af.v4_req.rmt_addr,
req->af.v4_req.opt);
if (err == NET_XMIT_CN) if (err == NET_XMIT_CN)
err = 0; err = 0;
} }
...@@ -1346,7 +1333,7 @@ static inline void syn_flood_warning(struct sk_buff *skb) ...@@ -1346,7 +1333,7 @@ static inline void syn_flood_warning(struct sk_buff *skb)
{ {
static unsigned long warntime; static unsigned long warntime;
if (jiffies - warntime > HZ*60) { if (jiffies - warntime > HZ * 60) {
warntime = jiffies; warntime = jiffies;
printk(KERN_INFO printk(KERN_INFO
"possible SYN flooding on port %d. Sending cookies.\n", "possible SYN flooding on port %d. Sending cookies.\n",
...@@ -1357,8 +1344,8 @@ static inline void syn_flood_warning(struct sk_buff *skb) ...@@ -1357,8 +1344,8 @@ static inline void syn_flood_warning(struct sk_buff *skb)
/* /*
* Save and compile IPv4 options into the open_request if needed. * Save and compile IPv4 options into the open_request if needed.
*/ */
static inline struct ip_options * static inline struct ip_options *tcp_v4_save_options(struct sock *sk,
tcp_v4_save_options(struct sock *sk, struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ip_options *opt = &(IPCB(skb)->opt); struct ip_options *opt = &(IPCB(skb)->opt);
struct ip_options *dopt = NULL; struct ip_options *dopt = NULL;
...@@ -1392,11 +1379,11 @@ tcp_v4_save_options(struct sock *sk, struct sk_buff *skb) ...@@ -1392,11 +1379,11 @@ tcp_v4_save_options(struct sock *sk, struct sk_buff *skb)
int sysctl_max_syn_backlog = 256; int sysctl_max_syn_backlog = 256;
struct or_calltable or_ipv4 = { struct or_calltable or_ipv4 = {
PF_INET, family: PF_INET,
tcp_v4_send_synack, rtx_syn_ack: tcp_v4_send_synack,
tcp_v4_or_send_ack, send_ack: tcp_v4_or_send_ack,
tcp_v4_or_free, destructor: tcp_v4_or_free,
tcp_v4_send_reset send_reset: tcp_v4_send_reset,
}; };
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
...@@ -1415,7 +1402,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ...@@ -1415,7 +1402,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
/* Never answer to SYNs send to broadcast or multicast */ /* Never answer to SYNs send to broadcast or multicast */
if (((struct rtable *)skb->dst)->rt_flags & if (((struct rtable *)skb->dst)->rt_flags &
(RTCF_BROADCAST|RTCF_MULTICAST)) (RTCF_BROADCAST | RTCF_MULTICAST))
goto drop; goto drop;
/* TW buckets are converted to open requests without /* TW buckets are converted to open requests without
...@@ -1440,7 +1427,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ...@@ -1440,7 +1427,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
goto drop; goto drop;
req = tcp_openreq_alloc(); req = tcp_openreq_alloc();
if (req == NULL) if (!req)
goto drop; goto drop;
tcp_clear_options(&tp); tcp_clear_options(&tp);
...@@ -1454,7 +1441,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ...@@ -1454,7 +1441,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
tp.saw_tstamp = 0; tp.saw_tstamp = 0;
} }
if (tp.saw_tstamp && tp.rcv_tsval == 0) { if (tp.saw_tstamp && !tp.rcv_tsval) {
/* Some OSes (unknown ones, but I see them on web server, which /* Some OSes (unknown ones, but I see them on web server, which
* contains information interesting only for windows' * contains information interesting only for windows'
* users) do not send their stamp in SYN. It is easy case. * users) do not send their stamp in SYN. It is easy case.
...@@ -1479,7 +1466,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ...@@ -1479,7 +1466,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
syn_flood_warning(skb); syn_flood_warning(skb);
#endif #endif
isn = cookie_v4_init_sequence(sk, skb, &req->mss); isn = cookie_v4_init_sequence(sk, skb, &req->mss);
} else if (isn == 0) { } else if (!isn) {
struct inet_peer *peer = NULL; struct inet_peer *peer = NULL;
/* VJ's idea. We save last timestamp seen /* VJ's idea. We save last timestamp seen
...@@ -1494,10 +1481,11 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ...@@ -1494,10 +1481,11 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (tp.saw_tstamp && if (tp.saw_tstamp &&
sysctl_tcp_tw_recycle && sysctl_tcp_tw_recycle &&
(dst = tcp_v4_route_req(sk, req)) != NULL && (dst = tcp_v4_route_req(sk, req)) != NULL &&
(peer = rt_get_peer((struct rtable*)dst)) != NULL && (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
peer->v4daddr == saddr) { peer->v4daddr == saddr) {
if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL && if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
(s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) { (s32)(peer->tcp_ts - req->ts_recent) >
TCP_PAWS_WINDOW) {
NET_INC_STATS_BH(PAWSPassiveRejected); NET_INC_STATS_BH(PAWSPassiveRejected);
dst_release(dst); dst_release(dst);
goto drop_and_free; goto drop_and_free;
...@@ -1505,19 +1493,23 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ...@@ -1505,19 +1493,23 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
} }
/* Kill the following clause, if you dislike this way. */ /* Kill the following clause, if you dislike this way. */
else if (!sysctl_tcp_syncookies && else if (!sysctl_tcp_syncookies &&
(sysctl_max_syn_backlog - tcp_synq_len(sk) (sysctl_max_syn_backlog - tcp_synq_len(sk) <
< (sysctl_max_syn_backlog>>2)) && (sysctl_max_syn_backlog >> 2)) &&
(!peer || !peer->tcp_ts_stamp) && (!peer || !peer->tcp_ts_stamp) &&
(!dst || !dst->rtt)) { (!dst || !dst->rtt)) {
/* Without syncookies last quarter of /* Without syncookies last quarter of
* backlog is filled with destinations, proven to be alive. * backlog is filled with destinations,
* proven to be alive.
* It means that we continue to communicate * It means that we continue to communicate
* to destinations, already remembered * to destinations, already remembered
* to the moment of synflood. * to the moment of synflood.
*/ */
NETDEBUG(if (net_ratelimit()) \ NETDEBUG(if (net_ratelimit()) \
printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \ printk(KERN_DEBUG "TCP: drop open "
NIPQUAD(saddr), ntohs(skb->h.th->source))); "request from %u.%u."
"%u.%u/%u\n", \
NIPQUAD(saddr),
ntohs(skb->h.th->source)));
dst_release(dst); dst_release(dst);
goto drop_and_free; goto drop_and_free;
} }
...@@ -1548,7 +1540,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ...@@ -1548,7 +1540,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
* The three way handshake has completed - we got a valid synack - * The three way handshake has completed - we got a valid synack -
* now create the new socket. * now create the new socket.
*/ */
struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
struct open_request *req, struct open_request *req,
struct dst_entry *dst) struct dst_entry *dst)
{ {
...@@ -1559,8 +1551,7 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, ...@@ -1559,8 +1551,7 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (tcp_acceptq_is_full(sk)) if (tcp_acceptq_is_full(sk))
goto exit_overflow; goto exit_overflow;
if (dst == NULL && if (!dst && (dst = tcp_v4_route_req(sk, req)) == NULL)
(dst = tcp_v4_route_req(sk, req)) == NULL)
goto exit; goto exit;
newsk = tcp_create_openreq_child(sk, req, skb); newsk = tcp_create_openreq_child(sk, req, skb);
...@@ -1601,17 +1592,15 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, ...@@ -1601,17 +1592,15 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
return NULL; return NULL;
} }
static struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb) static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
{ {
struct open_request *req, **prev;
struct tcphdr *th = skb->h.th; struct tcphdr *th = skb->h.th;
struct iphdr *iph = skb->nh.iph; struct iphdr *iph = skb->nh.iph;
struct tcp_opt *tp = tcp_sk(sk); struct tcp_opt *tp = tcp_sk(sk);
struct sock *nsk; struct sock *nsk;
struct open_request **prev;
/* Find possible connection requests. */ /* Find possible connection requests. */
req = tcp_v4_search_req(tp, &prev, struct open_request *req = tcp_v4_search_req(tp, &prev, th->source,
th->source,
iph->saddr, iph->daddr); iph->saddr, iph->daddr);
if (req) if (req)
return tcp_check_req(sk, skb, req, prev); return tcp_check_req(sk, skb, req, prev);
...@@ -1627,7 +1616,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb) ...@@ -1627,7 +1616,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb)
bh_lock_sock(nsk); bh_lock_sock(nsk);
return nsk; return nsk;
} }
tcp_tw_put((struct tcp_tw_bucket*)nsk); tcp_tw_put((struct tcp_tw_bucket *)nsk);
return NULL; return NULL;
} }
...@@ -1642,22 +1631,24 @@ static int tcp_v4_checksum_init(struct sk_buff *skb) ...@@ -1642,22 +1631,24 @@ static int tcp_v4_checksum_init(struct sk_buff *skb)
{ {
if (skb->ip_summed == CHECKSUM_HW) { if (skb->ip_summed == CHECKSUM_HW) {
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
if (!tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr, if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
skb->nh.iph->daddr,skb->csum)) skb->nh.iph->daddr, skb->csum))
return 0; return 0;
NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "hw tcp v4 csum failed\n")); NETDEBUG(if (net_ratelimit())
printk(KERN_DEBUG "hw tcp v4 csum failed\n"));
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
} }
if (skb->len <= 76) { if (skb->len <= 76) {
if (tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr, if (tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
skb->nh.iph->daddr, skb->nh.iph->daddr,
skb_checksum(skb, 0, skb->len, 0))) skb_checksum(skb, 0, skb->len, 0)))
return -1; return -1;
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
} else { } else {
skb->csum = ~tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr, skb->csum = ~tcp_v4_check(skb->h.th, skb->len,
skb->nh.iph->daddr,0); skb->nh.iph->saddr,
skb->nh.iph->daddr, 0);
} }
return 0; return 0;
} }
...@@ -1689,7 +1680,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -1689,7 +1680,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
return 0; return 0;
} }
if (skb->len < (skb->h.th->doff<<2) || tcp_checksum_complete(skb)) if (skb->len < (skb->h.th->doff << 2) || tcp_checksum_complete(skb))
goto csum_err; goto csum_err;
if (sk->state == TCP_LISTEN) { if (sk->state == TCP_LISTEN) {
...@@ -1736,7 +1727,7 @@ int tcp_v4_rcv(struct sk_buff *skb) ...@@ -1736,7 +1727,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
struct sock *sk; struct sock *sk;
int ret; int ret;
if (skb->pkt_type!=PACKET_HOST) if (skb->pkt_type != PACKET_HOST)
goto discard_it; goto discard_it;
/* Count it even if it's bad */ /* Count it even if it's bad */
...@@ -1747,9 +1738,9 @@ int tcp_v4_rcv(struct sk_buff *skb) ...@@ -1747,9 +1738,9 @@ int tcp_v4_rcv(struct sk_buff *skb)
th = skb->h.th; th = skb->h.th;
if (th->doff < sizeof(struct tcphdr)/4) if (th->doff < sizeof(struct tcphdr) / 4)
goto bad_packet; goto bad_packet;
if (!pskb_may_pull(skb, th->doff*4)) if (!pskb_may_pull(skb, th->doff * 4))
goto discard_it; goto discard_it;
/* An explanation is required here, I think. /* An explanation is required here, I think.
...@@ -1763,20 +1754,21 @@ int tcp_v4_rcv(struct sk_buff *skb) ...@@ -1763,20 +1754,21 @@ int tcp_v4_rcv(struct sk_buff *skb)
th = skb->h.th; th = skb->h.th;
TCP_SKB_CB(skb)->seq = ntohl(th->seq); TCP_SKB_CB(skb)->seq = ntohl(th->seq);
TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
skb->len - th->doff*4); skb->len - th->doff * 4);
TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
TCP_SKB_CB(skb)->when = 0; TCP_SKB_CB(skb)->when = 0;
TCP_SKB_CB(skb)->flags = skb->nh.iph->tos; TCP_SKB_CB(skb)->flags = skb->nh.iph->tos;
TCP_SKB_CB(skb)->sacked = 0; TCP_SKB_CB(skb)->sacked = 0;
sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source, sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source,
skb->nh.iph->daddr, ntohs(th->dest), tcp_v4_iif(skb)); skb->nh.iph->daddr, ntohs(th->dest),
tcp_v4_iif(skb));
if (!sk) if (!sk)
goto no_tcp_socket; goto no_tcp_socket;
process: process:
if(!ipsec_sk_policy(sk,skb)) if (!ipsec_sk_policy(sk, skb))
goto discard_and_relse; goto discard_and_relse;
if (sk->state == TCP_TIME_WAIT) if (sk->state == TCP_TIME_WAIT)
...@@ -1798,7 +1790,7 @@ int tcp_v4_rcv(struct sk_buff *skb) ...@@ -1798,7 +1790,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
return ret; return ret;
no_tcp_socket: no_tcp_socket:
if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
bad_packet: bad_packet:
TCP_INC_STATS_BH(TcpInErrs); TCP_INC_STATS_BH(TcpInErrs);
} else { } else {
...@@ -1815,18 +1807,17 @@ int tcp_v4_rcv(struct sk_buff *skb) ...@@ -1815,18 +1807,17 @@ int tcp_v4_rcv(struct sk_buff *skb)
goto discard_it; goto discard_it;
do_time_wait: do_time_wait:
if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
TCP_INC_STATS_BH(TcpInErrs); TCP_INC_STATS_BH(TcpInErrs);
goto discard_and_relse; goto discard_and_relse;
} }
switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk, switch (tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
skb, th, skb->len)) { skb, th, skb->len)) {
case TCP_TW_SYN: case TCP_TW_SYN: {
{ struct sock *sk2 = tcp_v4_lookup_listener(skb->nh.iph->daddr,
struct sock *sk2; ntohs(th->dest),
tcp_v4_iif(skb));
sk2 = tcp_v4_lookup_listener(skb->nh.iph->daddr, ntohs(th->dest), tcp_v4_iif(skb)); if (sk2) {
if (sk2 != NULL) {
tcp_tw_deschedule((struct tcp_tw_bucket *)sk); tcp_tw_deschedule((struct tcp_tw_bucket *)sk);
tcp_timewait_kill((struct tcp_tw_bucket *)sk); tcp_timewait_kill((struct tcp_tw_bucket *)sk);
tcp_tw_put((struct tcp_tw_bucket *)sk); tcp_tw_put((struct tcp_tw_bucket *)sk);
...@@ -1910,7 +1901,7 @@ int tcp_v4_rebuild_header(struct sock *sk) ...@@ -1910,7 +1901,7 @@ int tcp_v4_rebuild_header(struct sock *sk)
int err; int err;
/* Route is OK, nothing to do. */ /* Route is OK, nothing to do. */
if (rt != NULL) if (rt)
return 0; return 0;
/* Reroute. */ /* Reroute. */
...@@ -1958,15 +1949,15 @@ int tcp_v4_remember_stamp(struct sock *sk) ...@@ -1958,15 +1949,15 @@ int tcp_v4_remember_stamp(struct sock *sk)
{ {
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct tcp_opt *tp = tcp_sk(sk); struct tcp_opt *tp = tcp_sk(sk);
struct rtable *rt = (struct rtable*)__sk_dst_get(sk); struct rtable *rt = (struct rtable *)__sk_dst_get(sk);
struct inet_peer *peer = NULL; struct inet_peer *peer = NULL;
int release_it = 0; int release_it = 0;
if (rt == NULL || rt->rt_dst != inet->daddr) { if (!rt || rt->rt_dst != inet->daddr) {
peer = inet_getpeer(inet->daddr, 1); peer = inet_getpeer(inet->daddr, 1);
release_it = 1; release_it = 1;
} else { } else {
if (rt->peer == NULL) if (!rt->peer)
rt_bind_peer(rt, 1); rt_bind_peer(rt, 1);
peer = rt->peer; peer = rt->peer;
} }
...@@ -2007,18 +1998,17 @@ int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw) ...@@ -2007,18 +1998,17 @@ int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw)
} }
struct tcp_func ipv4_specific = { struct tcp_func ipv4_specific = {
ip_queue_xmit, queue_xmit: ip_queue_xmit,
tcp_v4_send_check, send_check: tcp_v4_send_check,
tcp_v4_rebuild_header, rebuild_header: tcp_v4_rebuild_header,
tcp_v4_conn_request, conn_request: tcp_v4_conn_request,
tcp_v4_syn_recv_sock, syn_recv_sock: tcp_v4_syn_recv_sock,
tcp_v4_remember_stamp, remember_stamp: tcp_v4_remember_stamp,
sizeof(struct iphdr), net_header_len: sizeof(struct iphdr),
setsockopt: ip_setsockopt,
ip_setsockopt, getsockopt: ip_getsockopt,
ip_getsockopt, addr2sockaddr: v4_addr2sockaddr,
v4_addr2sockaddr, sockaddr_len: sizeof(struct sockaddr_in),
sizeof(struct sockaddr_in)
}; };
/* NOTE: A lot of things set to zero explicitly by call to /* NOTE: A lot of things set to zero explicitly by call to
...@@ -2082,7 +2072,7 @@ static int tcp_v4_destroy_sock(struct sock *sk) ...@@ -2082,7 +2072,7 @@ static int tcp_v4_destroy_sock(struct sock *sk)
__skb_queue_purge(&tp->ucopy.prequeue); __skb_queue_purge(&tp->ucopy.prequeue);
/* Clean up a referenced TCP bind bucket. */ /* Clean up a referenced TCP bind bucket. */
if(sk->prev != NULL) if (sk->prev)
tcp_put_port(sk); tcp_put_port(sk);
/* If sendmsg cached page exists, toss it. */ /* If sendmsg cached page exists, toss it. */
...@@ -2095,7 +2085,8 @@ static int tcp_v4_destroy_sock(struct sock *sk) ...@@ -2095,7 +2085,8 @@ static int tcp_v4_destroy_sock(struct sock *sk)
} }
/* Proc filesystem TCP sock list dumping. */ /* Proc filesystem TCP sock list dumping. */
static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf, int i, int uid) static void get_openreq(struct sock *sk, struct open_request *req,
char *tmpbuf, int i, int uid)
{ {
int ttd = req->expires - jiffies; int ttd = req->expires - jiffies;
...@@ -2107,7 +2098,7 @@ static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf, ...@@ -2107,7 +2098,7 @@ static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf,
req->af.v4_req.rmt_addr, req->af.v4_req.rmt_addr,
ntohs(req->rmt_port), ntohs(req->rmt_port),
TCP_SYN_RECV, TCP_SYN_RECV,
0,0, /* could print option size, but that is af dependent. */ 0, 0, /* could print option size, but that is af dependent. */
1, /* timers active (only the expire timer) */ 1, /* timers active (only the expire timer) */
ttd, ttd,
req->retrans, req->retrans,
...@@ -2115,23 +2106,20 @@ static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf, ...@@ -2115,23 +2106,20 @@ static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf,
0, /* non standard timer */ 0, /* non standard timer */
0, /* open_requests have no inode */ 0, /* open_requests have no inode */
atomic_read(&sk->refcnt), atomic_read(&sk->refcnt),
req req);
);
} }
static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i) static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i)
{ {
unsigned int dest, src;
__u16 destp, srcp;
int timer_active; int timer_active;
unsigned long timer_expires; unsigned long timer_expires;
struct tcp_opt *tp = tcp_sk(sp); struct tcp_opt *tp = tcp_sk(sp);
struct inet_opt *inet = inet_sk(sp); struct inet_opt *inet = inet_sk(sp);
unsigned int dest = inet->daddr;
unsigned int src = inet->rcv_saddr;
__u16 destp = ntohs(inet->dport);
__u16 srcp = ntohs(inet->sport);
dest = inet->daddr;
src = inet->rcv_saddr;
destp = ntohs(inet->dport);
srcp = ntohs(inet->sport);
if (tp->pending == TCP_TIME_RETRANS) { if (tp->pending == TCP_TIME_RETRANS) {
timer_active = 1; timer_active = 1;
timer_expires = tp->timeout; timer_expires = tp->timeout;
...@@ -2146,19 +2134,19 @@ static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i) ...@@ -2146,19 +2134,19 @@ static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i)
timer_expires = jiffies; timer_expires = jiffies;
} }
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d", "%08X %5d %8d %lu %d %p %u %u %u %u %d",
i, src, srcp, dest, destp, sp->state, i, src, srcp, dest, destp, sp->state,
tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq, tp->write_seq - tp->snd_una, tp->rcv_nxt - tp->copied_seq,
timer_active, timer_expires-jiffies, timer_active, timer_expires - jiffies,
tp->retransmits, tp->retransmits,
sock_i_uid(sp), sock_i_uid(sp),
tp->probes_out, tp->probes_out,
sock_i_ino(sp), sock_i_ino(sp),
atomic_read(&sp->refcnt), sp, atomic_read(&sp->refcnt), sp,
tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong, tp->rto, tp->ack.ato, (tp->ack.quick << 1) | tp->ack.pingpong,
tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh tp->snd_cwnd,
); tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
} }
static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i) static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
...@@ -2188,18 +2176,19 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -2188,18 +2176,19 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length)
{ {
int len = 0, num = 0, i; int len = 0, num = 0, i;
off_t begin, pos = 0; off_t begin, pos = 0;
char tmpbuf[TMPSZ+1]; char tmpbuf[TMPSZ + 1];
if (offset < TMPSZ) if (offset < TMPSZ)
len += sprintf(buffer, "%-*s\n", TMPSZ-1, len += sprintf(buffer, "%-*s\n", TMPSZ - 1,
" sl local_address rem_address st tx_queue " " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout inode"); "rx_queue tr tm->when retrnsmt uid timeout "
"inode");
pos = TMPSZ; pos = TMPSZ;
/* First, walk listening socket table. */ /* First, walk listening socket table. */
tcp_listen_lock(); tcp_listen_lock();
for(i = 0; i < TCP_LHTABLE_SIZE; i++) { for (i = 0; i < TCP_LHTABLE_SIZE; i++) {
struct sock *sk; struct sock *sk;
struct tcp_listen_opt *lopt; struct tcp_listen_opt *lopt;
int k; int k;
...@@ -2215,7 +2204,8 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -2215,7 +2204,8 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length)
pos += TMPSZ; pos += TMPSZ;
if (pos >= offset) { if (pos >= offset) {
get_tcp_sock(sk, tmpbuf, num); get_tcp_sock(sk, tmpbuf, num);
len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf); len += sprintf(buffer + len, "%-*s\n",
TMPSZ - 1, tmpbuf);
if (pos >= offset + length) { if (pos >= offset + length) {
tcp_listen_unlock(); tcp_listen_unlock();
goto out_no_bh; goto out_no_bh;
...@@ -2226,17 +2216,22 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -2226,17 +2216,22 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length)
uid = sock_i_uid(sk); uid = sock_i_uid(sk);
read_lock_bh(&tp->syn_wait_lock); read_lock_bh(&tp->syn_wait_lock);
lopt = tp->listen_opt; lopt = tp->listen_opt;
if (lopt && lopt->qlen != 0) { if (lopt && lopt->qlen) {
for (k=0; k<TCP_SYNQ_HSIZE; k++) { for (k = 0; k < TCP_SYNQ_HSIZE; k++) {
for (req = lopt->syn_table[k]; req; req = req->dl_next, num++) { for (req = lopt->syn_table[k];
req; req = req->dl_next, num++) {
if (!TCP_INET_FAMILY(req->class->family)) if (!TCP_INET_FAMILY(req->class->family))
continue; continue;
pos += TMPSZ; pos += TMPSZ;
if (pos <= offset) if (pos <= offset)
continue; continue;
get_openreq(sk, req, tmpbuf, num, uid); get_openreq(sk, req, tmpbuf,
len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf); num, uid);
len += sprintf(buffer + len,
"%-*s\n",
TMPSZ - 1,
tmpbuf);
if (pos >= offset + length) { if (pos >= offset + length) {
read_unlock_bh(&tp->syn_wait_lock); read_unlock_bh(&tp->syn_wait_lock);
tcp_listen_unlock(); tcp_listen_unlock();
...@@ -2261,21 +2256,23 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -2261,21 +2256,23 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length)
struct tcp_tw_bucket *tw; struct tcp_tw_bucket *tw;
read_lock(&head->lock); read_lock(&head->lock);
for(sk = head->chain; sk; sk = sk->next, num++) { for (sk = head->chain; sk; sk = sk->next, num++) {
if (!TCP_INET_FAMILY(sk->family)) if (!TCP_INET_FAMILY(sk->family))
continue; continue;
pos += TMPSZ; pos += TMPSZ;
if (pos <= offset) if (pos <= offset)
continue; continue;
get_tcp_sock(sk, tmpbuf, num); get_tcp_sock(sk, tmpbuf, num);
len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf); len += sprintf(buffer + len, "%-*s\n",
TMPSZ - 1, tmpbuf);
if (pos >= offset + length) { if (pos >= offset + length) {
read_unlock(&head->lock); read_unlock(&head->lock);
goto out; goto out;
} }
} }
for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain; for (tw = (struct tcp_tw_bucket *)tcp_ehash[i +
tw != NULL; tcp_ehash_size].chain;
tw;
tw = (struct tcp_tw_bucket *)tw->next, num++) { tw = (struct tcp_tw_bucket *)tw->next, num++) {
if (!TCP_INET_FAMILY(tw->family)) if (!TCP_INET_FAMILY(tw->family))
continue; continue;
...@@ -2283,7 +2280,8 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -2283,7 +2280,8 @@ int tcp_get_info(char *buffer, char **start, off_t offset, int length)
if (pos <= offset) if (pos <= offset)
continue; continue;
get_timewait_sock(tw, tmpbuf, num); get_timewait_sock(tw, tmpbuf, num);
len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf); len += sprintf(buffer + len, "%-*s\n",
TMPSZ - 1, tmpbuf);
if (pos >= offset + length) { if (pos >= offset + length) {
read_unlock(&head->lock); read_unlock(&head->lock);
goto out; goto out;
...@@ -2333,7 +2331,7 @@ void __init tcp_v4_init(struct net_proto_family *ops) ...@@ -2333,7 +2331,7 @@ void __init tcp_v4_init(struct net_proto_family *ops)
int err = sock_create(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket); int err = sock_create(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket);
if (err < 0) if (err < 0)
panic("Failed to create the TCP control socket.\n"); panic("Failed to create the TCP control socket.\n");
tcp_socket->sk->allocation=GFP_ATOMIC; tcp_socket->sk->allocation = GFP_ATOMIC;
inet_sk(tcp_socket->sk)->ttl = MAXTTL; inet_sk(tcp_socket->sk)->ttl = MAXTTL;
/* Unhash it so that IP input processing does not even /* Unhash it so that IP input processing does not even
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment