summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
commit0ae8dceaebe3659ee0c3352c08125f403e77ebca (patch)
tree5085c389f09da78182b899d19fe1068b619a69dd /net
parent273767781288c35c9d679e908672b9996cda4c34 (diff)
Merge with 2.3.10.
Diffstat (limited to 'net')
-rw-r--r--net/appletalk/ddp.c6
-rw-r--r--net/ax25/af_ax25.c3
-rw-r--r--net/bridge/br.c4
-rw-r--r--net/core/scm.c9
-rw-r--r--net/decnet/dn_fib.c1
-rw-r--r--net/econet/econet.c3
-rw-r--r--net/ipv4/af_inet.c111
-rw-r--r--net/ipv4/icmp.c1
-rw-r--r--net/ipv4/proc.c185
-rw-r--r--net/ipv4/raw.c124
-rw-r--r--net/ipv4/tcp.c2
-rw-r--r--net/ipv4/tcp_input.c27
-rw-r--r--net/ipv4/tcp_ipv4.c514
-rw-r--r--net/ipv4/tcp_timer.c43
-rw-r--r--net/ipv4/udp.c299
-rw-r--r--net/ipv6/af_inet6.c23
-rw-r--r--net/ipv6/ip6_fw.c7
-rw-r--r--net/ipv6/proc.c136
-rw-r--r--net/ipv6/raw.c137
-rw-r--r--net/ipv6/route.c1
-rw-r--r--net/ipv6/tcp_ipv6.c408
-rw-r--r--net/ipv6/udp.c249
-rw-r--r--net/ipx/af_ipx.c3
-rw-r--r--net/irda/compressors/irda_deflate.c1
-rw-r--r--net/irda/irmod.c2
-rw-r--r--net/netrom/af_netrom.c6
-rw-r--r--net/netsyms.c23
-rw-r--r--net/rose/af_rose.c6
-rw-r--r--net/socket.c2
-rw-r--r--net/sunrpc/xprt.c38
-rw-r--r--net/unix/af_unix.c1
-rw-r--r--net/unix/garbage.c2
-rw-r--r--net/wanrouter/wanproc.c18
-rw-r--r--net/x25/af_x25.c1
-rw-r--r--net/x25/x25_dev.c1
35 files changed, 1258 insertions, 1139 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 4c8c6e390..b9ef2efd5 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -894,7 +894,7 @@ int atif_ioctl(int cmd, void *arg)
else
{
limit = ntohs(nr->nr_lastnet);
- if(limit - ntohs(nr->nr_firstnet) > 256)
+ if(limit - ntohs(nr->nr_firstnet) > 4096)
{
printk(KERN_WARNING "Too many routes/iface.\n");
return (-EINVAL);
@@ -938,6 +938,8 @@ int atif_ioctl(int cmd, void *arg)
return (-EPERM);
if(sa->sat_family != AF_APPLETALK)
return (-EINVAL);
+ if (atif == NULL)
+ return (-EADDRNOTAVAIL);
/*
* for now, we only support proxy AARP on ELAP;
@@ -987,6 +989,8 @@ int atif_ioctl(int cmd, void *arg)
return (-EPERM);
if(sa->sat_family != AF_APPLETALK)
return (-EINVAL);
+ if (atif == NULL)
+ return (-EADDRNOTAVAIL);
/*
* give to aarp module to remove proxy entry
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index a2ad7111f..f6ae5e677 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -462,6 +462,9 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
return -ENODEV;
+ if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
+ return -EINVAL;
+
digi.ndigi = ax25_ctl.digi_count;
for (k = 0; k < digi.ndigi; k++)
digi.calls[k] = ax25_ctl.digi_addr[k];
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 996aeb718..5fbd188d2 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -1831,12 +1831,8 @@ static int br_flood(struct sk_buff *skb, int port)
/* printk("Flood to port %d\n",i);*/
nskb->nh.raw = nskb->data + ETH_HLEN;
-#if LINUX_VERSION_CODE >= 0x20100
nskb->priority = 1;
dev_queue_xmit(nskb);
-#else
- dev_queue_xmit(nskb,nskb->dev,1);
-#endif
}
}
return(0);
diff --git a/net/core/scm.c b/net/core/scm.c
index 7e9f466ca..e2073166f 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -232,8 +232,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
break;
}
/* Bump the usage count and install the file. */
- atomic_inc(&fp[i]->f_count);
- current->files->fd[new_fd] = fp[i];
+ get_file(fp[i]);
+ fd_install(new_fd, fp[i]);
}
if (i > 0)
@@ -271,10 +271,9 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
if (new_fpl) {
- memcpy(new_fpl, fpl, sizeof(*fpl));
-
for (i=fpl->count-1; i>=0; i--)
- atomic_inc(&fpl->fp[i]->f_count);
+ get_file(fpl->fp[i]);
+ memcpy(new_fpl, fpl, sizeof(*fpl));
}
return new_fpl;
}
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 16f2e3e03..1e9de20f2 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -23,7 +23,6 @@
#include <linux/proc_fs.h>
#include <linux/netdevice.h>
#include <linux/timer.h>
-#include <linux/rtnetlink.h>
#include <asm/spinlock.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
diff --git a/net/econet/econet.c b/net/econet/econet.c
index 8930109b3..d790ae536 100644
--- a/net/econet/econet.c
+++ b/net/econet/econet.c
@@ -759,7 +759,8 @@ static struct sock *ec_listening_socket(unsigned char port, unsigned char
(opt->station == station || opt->station == 0) &&
(opt->net == net || opt->net == 0))
return sk;
- sk = sk->sklist_next;
+
+ sk = sk->next;
}
return NULL;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index ca0f27d0c..15b26fa1c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -5,7 +5,7 @@
*
* PF_INET protocol family socket handler.
*
- * Version: $Id: af_inet.c,v 1.91 1999/06/09 08:28:55 davem Exp $
+ * Version: $Id: af_inet.c,v 1.93 1999/07/02 11:26:24 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -162,9 +162,6 @@ static __inline__ void kill_sk_queues(struct sock *sk)
static __inline__ void kill_sk_now(struct sock *sk)
{
- /* No longer exists. */
- del_from_prot_sklist(sk);
-
/* Remove from protocol hash chains. */
sk->prot->unhash(sk);
@@ -239,7 +236,7 @@ int inet_setsockopt(struct socket *sock, int level, int optname,
{
struct sock *sk=sock->sk;
if (sk->prot->setsockopt==NULL)
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
return sk->prot->setsockopt(sk,level,optname,optval,optlen);
}
@@ -256,7 +253,7 @@ int inet_getsockopt(struct socket *sock, int level, int optname,
{
struct sock *sk=sock->sk;
if (sk->prot->getsockopt==NULL)
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
return sk->prot->getsockopt(sk,level,optname,optval,optlen);
}
@@ -268,12 +265,10 @@ static int inet_autobind(struct sock *sk)
{
/* We may need to bind the socket. */
if (sk->num == 0) {
- sk->num = sk->prot->good_socknum();
- if (sk->num == 0)
- return(-EAGAIN);
+ if (sk->prot->get_port(sk, 0) != 0)
+ return -EAGAIN;
sk->sport = htons(sk->num);
sk->prot->hash(sk);
- add_to_prot_sklist(sk);
}
return 0;
}
@@ -293,29 +288,38 @@ static void inet_listen_write_space(struct sock *sk)
int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
+ unsigned char old_state;
if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
- return(-EINVAL);
-
- if (inet_autobind(sk) != 0)
- return -EAGAIN;
+ return -EINVAL;
- /* We might as well re use these. */
if ((unsigned) backlog == 0) /* BSDism */
backlog = 1;
if ((unsigned) backlog > SOMAXCONN)
backlog = SOMAXCONN;
sk->max_ack_backlog = backlog;
- if (sk->state != TCP_LISTEN) {
- sk->ack_backlog = 0;
+
+ /* Really, if the socket is already in listen state
+ * we can only allow the backlog to be adjusted.
+ */
+ old_state = sk->state;
+ if (old_state != TCP_LISTEN) {
sk->state = TCP_LISTEN;
+ sk->ack_backlog = 0;
+ if (sk->num == 0) {
+ if (sk->prot->get_port(sk, 0) != 0) {
+ sk->state = old_state;
+ return -EAGAIN;
+ }
+ sk->sport = htons(sk->num);
+ }
+
dst_release(xchg(&sk->dst_cache, NULL));
- sk->prot->rehash(sk);
- add_to_prot_sklist(sk);
+ sk->prot->hash(sk);
+ sk->socket->flags |= SO_ACCEPTCON;
sk->write_space = inet_listen_write_space;
}
- sk->socket->flags |= SO_ACCEPTCON;
- return(0);
+ return 0;
}
/*
@@ -427,7 +431,6 @@ static int inet_create(struct socket *sock, int protocol)
/* Add to protocol hash chains. */
sk->prot->hash(sk);
- add_to_prot_sklist(sk);
}
if (sk->prot->init) {
@@ -486,11 +489,9 @@ int inet_release(struct socket *sock, struct socket *peersock)
*/
timeout = 0;
if (sk->linger && !(current->flags & PF_EXITING)) {
- timeout = MAX_SCHEDULE_TIMEOUT;
-
- /* XXX This makes no sense whatsoever... -DaveM */
- if (!sk->lingertime)
- timeout = HZ*sk->lingertime;
+ timeout = HZ * sk->lingertime;
+ if (!timeout)
+ timeout = MAX_SCHEDULE_TIMEOUT;
}
sock->sk = NULL;
sk->socket = NULL;
@@ -543,21 +544,17 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if((snum >= PORT_MASQ_BEGIN) && (snum <= PORT_MASQ_END))
return -EADDRINUSE;
#endif
- if (snum == 0)
- snum = sk->prot->good_socknum();
- if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
- return(-EACCES);
+ if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+ return -EACCES;
/* Make sure we are allowed to bind here. */
- if(sk->prot->verify_bind(sk, snum))
+ if (sk->prot->get_port(sk, snum) != 0)
return -EADDRINUSE;
- sk->num = snum;
- sk->sport = htons(snum);
+ sk->sport = htons(sk->num);
sk->daddr = 0;
sk->dport = 0;
- sk->prot->rehash(sk);
- add_to_prot_sklist(sk);
+ sk->prot->hash(sk);
dst_release(sk->dst_cache);
sk->dst_cache=NULL;
return(0);
@@ -570,12 +567,12 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
int err;
if (inet_autobind(sk) != 0)
- return(-EAGAIN);
+ return -EAGAIN;
if (sk->prot->connect == NULL)
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
err = sk->prot->connect(sk, (struct sockaddr *)uaddr, addr_len);
if (err < 0)
- return(err);
+ return err;
return(0);
}
@@ -626,18 +623,20 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
if (flags & O_NONBLOCK)
return -EALREADY;
} else {
+ if (sk->prot->connect == NULL)
+ return -EOPNOTSUPP;
+
/* We may need to bind the socket. */
if (inet_autobind(sk) != 0)
- return(-EAGAIN);
- if (sk->prot->connect == NULL)
- return(-EOPNOTSUPP);
+ return -EAGAIN;
+
err = sk->prot->connect(sk, uaddr, addr_len);
/* Note: there is a theoretical race here when an wake up
occurred before inet_wait_for_connect is entered. In 2.3
the wait queue setup should be moved before the low level
connect call. -AK*/
if (err < 0)
- return(err);
+ return err;
sock->state = SS_CONNECTING;
}
@@ -645,7 +644,7 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
goto sock_error;
if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
- return (-EINPROGRESS);
+ return -EINPROGRESS;
if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
inet_wait_for_connect(sk);
@@ -656,7 +655,7 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
sock->state = SS_CONNECTED;
if ((sk->state != TCP_ESTABLISHED) && sk->err)
goto sock_error;
- return(0);
+ return 0;
sock_error:
/* This is ugly but needed to fix a race in the ICMP error handler */
@@ -750,7 +749,7 @@ static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
sin->sin_family = AF_INET;
if (peer) {
if (!tcp_connected(sk->state))
- return(-ENOTCONN);
+ return -ENOTCONN;
sin->sin_port = sk->dport;
sin->sin_addr.s_addr = sk->daddr;
} else {
@@ -774,12 +773,12 @@ int inet_recvmsg(struct socket *sock, struct msghdr *msg, int size,
int err;
if (sock->flags & SO_ACCEPTCON)
- return(-EINVAL);
+ return -EINVAL;
if (sk->prot->recvmsg == NULL)
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
/* We may need to bind the socket. */
if (inet_autobind(sk) != 0)
- return(-EAGAIN);
+ return -EAGAIN;
err = sk->prot->recvmsg(sk, msg, size, flags&MSG_DONTWAIT,
flags&~MSG_DONTWAIT, &addr_len);
if (err >= 0)
@@ -796,15 +795,15 @@ int inet_sendmsg(struct socket *sock, struct msghdr *msg, int size,
if (sk->shutdown & SEND_SHUTDOWN) {
if (!(msg->msg_flags&MSG_NOSIGNAL))
send_sig(SIGPIPE, current, 1);
- return(-EPIPE);
+ return -EPIPE;
}
if (sk->prot->sendmsg == NULL)
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
if(sk->err)
return sock_error(sk);
/* We may need to bind the socket. */
- if(inet_autobind(sk) != 0)
+ if (inet_autobind(sk) != 0)
return -EAGAIN;
return sk->prot->sendmsg(sk, msg, size);
@@ -822,11 +821,13 @@ int inet_shutdown(struct socket *sock, int how)
1->2 bit 2 snds.
2->3 */
if ((how & ~SHUTDOWN_MASK) || how==0) /* MAXINT->0 */
- return(-EINVAL);
+ return -EINVAL;
+ if (!sk)
+ return -ENOTCONN;
if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
sock->state = SS_CONNECTED;
- if (!sk || !tcp_connected(sk->state))
- return(-ENOTCONN);
+ if (!tcp_connected(sk->state))
+ return -ENOTCONN;
sk->shutdown |= how;
if (sk->prot->shutdown)
sk->prot->shutdown(sk, how);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 9456c7f29..78b5d8f9b 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -269,7 +269,6 @@
#include <net/tcp.h>
#include <net/udp.h>
#include <net/raw.h>
-#include <net/snmp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <linux/errno.h>
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 52c5ee5a4..7057c343a 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -7,7 +7,7 @@
* PROC file system. It is mainly used for debugging and
* statistics.
*
- * Version: $Id: proc.c,v 1.35 1999/05/27 00:37:38 davem Exp $
+ * Version: $Id: proc.c,v 1.36 1999/07/02 11:26:34 davem Exp $
*
* Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -50,189 +50,6 @@
#include <net/sock.h>
#include <net/raw.h>
-/* Format a single open_request into tmpbuf. */
-static inline void get__openreq(struct sock *sk, struct open_request *req,
- char *tmpbuf,
- int i)
-{
- sprintf(tmpbuf, "%4d: %08lX:%04X %08lX:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u",
- i,
- (long unsigned int)req->af.v4_req.loc_addr,
- ntohs(sk->sport),
- (long unsigned int)req->af.v4_req.rmt_addr,
- ntohs(req->rmt_port),
- TCP_SYN_RECV,
- 0,0, /* could print option size, but that is af dependent. */
- 1, /* timers active (only the expire timer) */
- (unsigned long)(req->expires - jiffies),
- req->retrans,
- sk->socket ? sk->socket->inode->i_uid : 0,
- 0, /* non standard timer */
- 0 /* open_requests have no inode */
- );
-}
-
-/* Format a single socket into tmpbuf. */
-static inline void get__sock(struct sock *sp, char *tmpbuf, int i, int format)
-{
- unsigned long dest, src;
- unsigned short destp, srcp;
- int timer_active, timer_active1, timer_active2;
- int tw_bucket = 0;
- unsigned long timer_expires;
- struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
-
- dest = sp->daddr;
- src = sp->rcv_saddr;
- destp = sp->dport;
- srcp = sp->sport;
-
- /* FIXME: The fact that retransmit_timer occurs as a field
- * in two different parts of the socket structure is,
- * to say the least, confusing. This code now uses the
- * right retransmit_timer variable, but I'm not sure
- * the rest of the timer stuff is still correct.
- * In particular I'm not sure what the timeout value
- * is suppose to reflect (as opposed to tm->when). -- erics
- */
-
- destp = ntohs(destp);
- srcp = ntohs(srcp);
- if((format == 0) && (sp->state == TCP_TIME_WAIT)) {
- extern int tcp_tw_death_row_slot;
- struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sp;
- int slot_dist;
-
- tw_bucket = 1;
- timer_active1 = timer_active2 = 0;
- timer_active = 3;
- slot_dist = tw->death_slot;
- if(slot_dist > tcp_tw_death_row_slot)
- slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
- else
- slot_dist = tcp_tw_death_row_slot - slot_dist;
- timer_expires = jiffies + (slot_dist * TCP_TWKILL_PERIOD);
- } else {
- timer_active1 = tp->retransmit_timer.prev != NULL;
- timer_active2 = sp->timer.prev != NULL;
- timer_active = 0;
- timer_expires = (unsigned) -1;
- }
- if (timer_active1 && tp->retransmit_timer.expires < timer_expires) {
- timer_active = 1;
- timer_expires = tp->retransmit_timer.expires;
- }
- if (timer_active2 && sp->timer.expires < timer_expires) {
- timer_active = 2;
- timer_expires = sp->timer.expires;
- }
- if(timer_active == 0)
- timer_expires = jiffies;
- sprintf(tmpbuf, "%4d: %08lX:%04X %08lX:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
- i, src, srcp, dest, destp, sp->state,
- (tw_bucket ?
- 0 :
- (format == 0) ?
- tp->write_seq-tp->snd_una : atomic_read(&sp->wmem_alloc)),
- (tw_bucket ?
- 0 :
- (format == 0) ?
- tp->rcv_nxt-tp->copied_seq: atomic_read(&sp->rmem_alloc)),
- timer_active, timer_expires-jiffies,
- (tw_bucket ? 0 : tp->retransmits),
- (!tw_bucket && sp->socket) ? sp->socket->inode->i_uid : 0,
- (!tw_bucket && timer_active) ? sp->timeout : 0,
- (!tw_bucket && sp->socket) ? sp->socket->inode->i_ino : 0);
-}
-
-/*
- * Get__netinfo returns the length of that string.
- *
- * KNOWN BUGS
- * As in get_unix_netinfo, the buffer might be too small. If this
- * happens, get__netinfo returns only part of the available infos.
- *
- * Assumes that buffer length is a multiply of 128 - if not it will
- * write past the end.
- */
-static int
-get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t offset, int length)
-{
- struct sock *sp, *next;
- int len=0, i = 0;
- off_t pos=0;
- off_t begin;
- char tmpbuf[129];
-
- if (offset < 128)
- len += sprintf(buffer, "%-127s\n",
- " sl local_address rem_address st tx_queue "
- "rx_queue tr tm->when retrnsmt uid timeout inode");
- pos = 128;
- SOCKHASH_LOCK_READ();
- sp = pro->sklist_next;
- while(sp != (struct sock *)pro) {
- if (format == 0 && sp->state == TCP_LISTEN) {
- struct open_request *req;
-
- for (req = sp->tp_pinfo.af_tcp.syn_wait_queue; req;
- i++, req = req->dl_next) {
- if (req->sk)
- continue;
- pos += 128;
- if (pos < offset)
- continue;
- get__openreq(sp, req, tmpbuf, i);
- len += sprintf(buffer+len, "%-127s\n", tmpbuf);
- if(len >= length)
- goto out;
- }
- }
-
- pos += 128;
- if (pos < offset)
- goto next;
-
- get__sock(sp, tmpbuf, i, format);
-
- len += sprintf(buffer+len, "%-127s\n", tmpbuf);
- if(len >= length)
- break;
- next:
- next = sp->sklist_next;
- sp = next;
- i++;
- }
-out:
- SOCKHASH_UNLOCK_READ();
-
- begin = len - (pos - offset);
- *start = buffer + begin;
- len -= begin;
- if(len>length)
- len = length;
- if (len<0)
- len = 0;
- return len;
-}
-
-int tcp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- return get__netinfo(&tcp_prot, buffer,0, start, offset, length);
-}
-
-int udp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- return get__netinfo(&udp_prot, buffer,1, start, offset, length);
-}
-
-int raw_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- return get__netinfo(&raw_prot, buffer,1, start, offset, length);
-}
-
/*
* Report socket allocation statistics [mea@utu.fi]
*/
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index dd2e7555e..584fe81fc 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -5,7 +5,7 @@
*
* RAW - implementation of IP "raw" sockets.
*
- * Version: $Id: raw.c,v 1.41 1999/05/30 01:16:19 davem Exp $
+ * Version: $Id: raw.c,v 1.42 1999/07/02 11:26:26 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -70,60 +70,32 @@ struct sock *raw_v4_htable[RAWV4_HTABLE_SIZE];
static void raw_v4_hash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
+ struct sock **skp = &raw_v4_htable[sk->num & (RAWV4_HTABLE_SIZE - 1)];
- num &= (RAWV4_HTABLE_SIZE - 1);
- skp = &raw_v4_htable[num];
SOCKHASH_LOCK_WRITE();
- sk->next = *skp;
+ if ((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
*skp = sk;
- sk->hashent = num;
+ sk->pprev = skp;
+ sk->prot->inuse++;
+ if(sk->prot->highestinuse < sk->prot->inuse)
+ sk->prot->highestinuse = sk->prot->inuse;
SOCKHASH_UNLOCK_WRITE();
}
static void raw_v4_unhash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
-
- num &= (RAWV4_HTABLE_SIZE - 1);
- skp = &raw_v4_htable[num];
-
SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
+ if (sk->pprev) {
+ if (sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ sk->prot->inuse--;
}
SOCKHASH_UNLOCK_WRITE();
}
-static void raw_v4_rehash(struct sock *sk)
-{
- struct sock **skp;
- int num = sk->num;
- int oldnum = sk->hashent;
-
- num &= (RAWV4_HTABLE_SIZE - 1);
- skp = &raw_v4_htable[oldnum];
-
- SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
- }
- sk->next = raw_v4_htable[num];
- raw_v4_htable[num] = sk;
- sk->hashent = num;
- SOCKHASH_UNLOCK_WRITE();
-}
-
static __inline__ struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
unsigned long raddr, unsigned long laddr,
int dif)
@@ -640,9 +612,69 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
return -ENOPROTOOPT;
}
+static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
+{
+ unsigned int dest, src;
+ __u16 destp, srcp;
+ int timer_active;
+ unsigned long timer_expires;
+
+ dest = sp->daddr;
+ src = sp->rcv_saddr;
+ destp = ntohs(sp->dport);
+ srcp = ntohs(sp->sport);
+ timer_active = (sp->timer.prev != NULL) ? 2 : 0;
+ timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
+ sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
+ i, src, srcp, dest, destp, sp->state,
+ atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
+ timer_active, timer_expires-jiffies, 0,
+ sp->socket->inode->i_uid, timer_active ? sp->timeout : 0,
+ sp->socket ? sp->socket->inode->i_ino : 0);
+}
+
+int raw_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len = 0, num = 0, i;
+ off_t pos = 0;
+ off_t begin;
+ char tmpbuf[129];
+
+ if (offset < 128)
+ len += sprintf(buffer, "%-127s\n",
+ " sl local_address rem_address st tx_queue "
+ "rx_queue tr tm->when retrnsmt uid timeout inode");
+ pos = 128;
+ SOCKHASH_LOCK_READ();
+ for (i = 0; i < RAWV4_HTABLE_SIZE; i++) {
+ struct sock *sk;
+
+ for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) {
+ if (sk->family != PF_INET)
+ continue;
+ pos += 128;
+ if (pos < offset)
+ continue;
+ get_raw_sock(sk, tmpbuf, i);
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+out:
+ SOCKHASH_UNLOCK_READ();
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
struct proto raw_prot = {
- (struct sock *)&raw_prot, /* sklist_next */
- (struct sock *)&raw_prot, /* sklist_prev */
raw_close, /* close */
udp_connect, /* connect */
NULL, /* accept */
@@ -666,9 +698,7 @@ struct proto raw_prot = {
raw_rcv_skb, /* backlog_rcv */
raw_v4_hash, /* hash */
raw_v4_unhash, /* unhash */
- raw_v4_rehash, /* rehash */
- NULL, /* good_socknum */
- NULL, /* verify_bind */
+ NULL, /* get_port */
128, /* max_header */
0, /* retransmits */
"RAW", /* name */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 4a1bdde4a..e68569a68 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1339,7 +1339,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
break;
}
- if(copied > 0 && msg->msg_name)
+ if (copied > 0 && msg->msg_name)
tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
msg->msg_name);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index af4165fce..3080bc201 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.169 1999/06/09 08:29:13 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.170 1999/07/02 11:26:28 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -917,25 +917,26 @@ extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
/* Must be called only from BH context. */
void tcp_timewait_kill(struct tcp_tw_bucket *tw)
{
+ struct tcp_bind_bucket *tb = tw->tb;
+
SOCKHASH_LOCK_WRITE_BH();
- /* Unlink from various places. */
+ /* Disassociate with bind bucket. */
if(tw->bind_next)
tw->bind_next->bind_pprev = tw->bind_pprev;
*(tw->bind_pprev) = tw->bind_next;
- if(tw->tb->owners == NULL)
- tcp_inc_slow_timer(TCP_SLT_BUCKETGC);
+ if (tb->owners == NULL) {
+ if (tb->next)
+ tb->next->pprev = tb->pprev;
+ *(tb->pprev) = tb->next;
+ kmem_cache_free(tcp_bucket_cachep, tb);
+ }
+ /* Unlink from established hashes. */
if(tw->next)
tw->next->pprev = tw->pprev;
*tw->pprev = tw->next;
- /* We decremented the prot->inuse count when we entered TIME_WAIT
- * and the sock from which this came was destroyed.
- */
- tw->sklist_next->sklist_prev = tw->sklist_prev;
- tw->sklist_prev->sklist_next = tw->sklist_next;
-
SOCKHASH_UNLOCK_WRITE_BH();
/* Ok, now free it up. */
@@ -1040,11 +1041,9 @@ static __inline__ void tcp_tw_hashdance(struct sock *sk, struct tcp_tw_bucket *t
sk->bind_next->bind_pprev = &tw->bind_next;
tw->bind_pprev = sk->bind_pprev;
*sk->bind_pprev = (struct sock *)tw;
+ sk->prev = NULL;
- /* Step 3: Same for the protocol sklist. */
- (tw->sklist_next = sk->sklist_next)->sklist_prev = (struct sock *)tw;
- (tw->sklist_prev = sk->sklist_prev)->sklist_next = (struct sock *)tw;
- sk->sklist_next = NULL;
+ /* Step 3: Un-charge protocol socket in-use count. */
sk->prot->inuse--;
/* Step 4: Hash TW into TIMEWAIT half of established hash table. */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 564e859f2..3c5102b42 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_ipv4.c,v 1.180 1999/06/09 08:29:19 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.182 1999/07/05 01:34:07 davem Exp $
*
* IPv4 specific functions
*
@@ -132,28 +132,9 @@ static __inline__ int tcp_sk_hashfn(struct sock *sk)
return tcp_hashfn(laddr, lport, faddr, fport);
}
-/* Invariant, sk->num is non-zero. */
-void tcp_bucket_unlock(struct sock *sk)
-{
- struct tcp_bind_bucket *tb;
- unsigned short snum = sk->num;
-
- SOCKHASH_LOCK_WRITE();
- for(tb = tcp_bhash[tcp_bhashfn(snum)]; tb; tb = tb->next) {
- if(tb->port == snum) {
- if(tb->owners == NULL &&
- (tb->flags & TCPB_FLAG_LOCKED)) {
- tb->flags &= ~(TCPB_FLAG_LOCKED |
- TCPB_FLAG_FASTREUSE);
- tcp_inc_slow_timer(TCP_SLT_BUCKETGC);
- }
- break;
- }
- }
- SOCKHASH_UNLOCK_WRITE();
-}
-
-/* The sockhash lock must be held as a writer here. */
+/* Allocate and initialize a new TCP local port bind bucket.
+ * The sockhash lock must be held as a writer here.
+ */
struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
{
struct tcp_bind_bucket *tb;
@@ -163,7 +144,7 @@ struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
struct tcp_bind_bucket **head =
&tcp_bhash[tcp_bhashfn(snum)];
tb->port = snum;
- tb->flags = TCPB_FLAG_LOCKED;
+ tb->fastreuse = 0;
tb->owners = NULL;
if((tb->next = *head) != NULL)
tb->next->pprev = &tb->next;
@@ -186,133 +167,176 @@ static __inline__ int tcp_bucket_check(unsigned short snum)
tb = tcp_bhash[tcp_bhashfn(snum)];
for( ; (tb && (tb->port != snum)); tb = tb->next)
;
- if(tb == NULL && tcp_bucket_create(snum) == NULL)
- ret = 1;
+ ret = 0;
+ if (tb == NULL) {
+ if ((tb = tcp_bucket_create(snum)) == NULL)
+ ret = 1;
+ }
SOCKHASH_UNLOCK_WRITE();
return ret;
}
#endif
-static int tcp_v4_verify_bind(struct sock *sk, unsigned short snum)
+static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+ struct tcp_bind_bucket *tb = (struct tcp_bind_bucket *)sk->prev;
+
+ if ((child->bind_next = tb->owners) != NULL)
+ tb->owners->bind_pprev = &child->bind_next;
+ tb->owners = child;
+ child->bind_pprev = &tb->owners;
+ child->prev = (struct sock *) tb;
+}
+
+__inline__ void tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+ SOCKHASH_LOCK_WRITE();
+ __tcp_inherit_port(sk, child);
+ SOCKHASH_UNLOCK_WRITE();
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ */
+static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
{
struct tcp_bind_bucket *tb;
- int result = 0;
SOCKHASH_LOCK_WRITE();
- for(tb = tcp_bhash[tcp_bhashfn(snum)];
- (tb && (tb->port != snum));
- tb = tb->next)
- ;
- if(tb && tb->owners) {
- /* Fast path for reuse ports, see include/net/tcp.h for a very
- * detailed description of why this works, and why it is worth
- * the effort at all. -DaveM
- */
- if((tb->flags & TCPB_FLAG_FASTREUSE) &&
- (sk->reuse != 0)) {
- goto go_like_smoke;
+ if (snum == 0) {
+ int rover = tcp_port_rover;
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int remaining = (high - low) + 1;
+
+ do { rover++;
+ if ((rover < low) || (rover > high))
+ rover = low;
+ tb = tcp_bhash[tcp_bhashfn(rover)];
+ for ( ; tb; tb = tb->next)
+ if (tb->port == rover)
+ goto next;
+ break;
+ next:
+ } while (--remaining > 0);
+ tcp_port_rover = rover;
+
+ /* Exhausted local port range during search? */
+ if (remaining <= 0)
+ goto fail;
+
+ /* OK, here is the one we will use. */
+ snum = rover;
+ tb = NULL;
+ } else {
+ for (tb = tcp_bhash[tcp_bhashfn(snum)];
+ tb != NULL;
+ tb = tb->next)
+ if (tb->port == snum)
+ break;
+ }
+ if (tb != NULL && tb->owners != NULL) {
+ if (tb->fastreuse != 0 && sk->reuse != 0) {
+ goto success;
} else {
- struct sock *sk2;
+ struct sock *sk2 = tb->owners;
int sk_reuse = sk->reuse;
- /* We must walk the whole port owner list in this case. -DaveM */
- for(sk2 = tb->owners; sk2; sk2 = sk2->bind_next) {
+ for( ; sk2 != NULL; sk2 = sk2->bind_next) {
if (sk->bound_dev_if == sk2->bound_dev_if) {
- if(!sk_reuse || !sk2->reuse || sk2->state == TCP_LISTEN) {
- if(!sk2->rcv_saddr ||
- !sk->rcv_saddr ||
- (sk2->rcv_saddr == sk->rcv_saddr))
+ if (!sk_reuse ||
+ !sk2->reuse ||
+ sk2->state == TCP_LISTEN) {
+ if (!sk2->rcv_saddr ||
+ !sk->rcv_saddr ||
+ (sk2->rcv_saddr == sk->rcv_saddr))
break;
}
}
}
- if(sk2 != NULL)
- result = 1;
+ /* If we found a conflict, fail. */
+ if (sk2 != NULL)
+ goto fail;
}
}
- if(result == 0) {
- if(tb == NULL) {
- if((tb = tcp_bucket_create(snum)) == NULL)
- result = 1;
- else if (sk->reuse && sk->state != TCP_LISTEN)
- tb->flags |= TCPB_FLAG_FASTREUSE;
- } else {
- /* It could be pending garbage collection, this
- * kills the race and prevents it from disappearing
- * out from under us by the time we use it. -DaveM
- */
- if(tb->owners == NULL) {
- if (!(tb->flags & TCPB_FLAG_LOCKED)) {
- tb->flags = (TCPB_FLAG_LOCKED |
- ((sk->reuse &&
- sk->state != TCP_LISTEN) ?
- TCPB_FLAG_FASTREUSE : 0));
- tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
- } else if (!(tb->flags & TCPB_FLAG_GOODSOCKNUM)) {
- /* Someone is in between the bind
- * and the actual connect or listen.
- * See if it was a legitimate reuse
- * and we are as well, else punt.
- */
- if (sk->reuse == 0 ||
- !(tb->flags & TCPB_FLAG_FASTREUSE))
- result = 1;
- } else
- tb->flags &= ~TCPB_FLAG_GOODSOCKNUM;
- }
- }
- }
-go_like_smoke:
+ if (tb == NULL &&
+ (tb = tcp_bucket_create(snum)) == NULL)
+ goto fail;
+ if (tb->owners == NULL) {
+ if (sk->reuse && sk->state != TCP_LISTEN)
+ tb->fastreuse = 1;
+ else
+ tb->fastreuse = 0;
+ } else if (tb->fastreuse &&
+ ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
+ tb->fastreuse = 0;
+success:
+ sk->num = snum;
+ if ((sk->bind_next = tb->owners) != NULL)
+ tb->owners->bind_pprev = &sk->bind_next;
+ tb->owners = sk;
+ sk->bind_pprev = &tb->owners;
+ sk->prev = (struct sock *) tb;
+
SOCKHASH_UNLOCK_WRITE();
- return result;
+ return 0;
+
+fail:
+ SOCKHASH_UNLOCK_WRITE();
+ return 1;
}
-unsigned short tcp_good_socknum(void)
+/* Get rid of any references to a local port held by the
+ * given sock.
+ */
+__inline__ void __tcp_put_port(struct sock *sk)
{
struct tcp_bind_bucket *tb;
- int low = sysctl_local_port_range[0];
- int high = sysctl_local_port_range[1];
- int remaining = (high - low) + 1;
- int rover;
+ tb = (struct tcp_bind_bucket *) sk->prev;
+ if (sk->bind_next)
+ sk->bind_next->bind_pprev = sk->bind_pprev;
+ *(sk->bind_pprev) = sk->bind_next;
+ sk->prev = NULL;
+ if (tb->owners == NULL) {
+ if (tb->next)
+ tb->next->pprev = tb->pprev;
+ *(tb->pprev) = tb->next;
+ kmem_cache_free(tcp_bucket_cachep, tb);
+ }
+}
+
+void tcp_put_port(struct sock *sk)
+{
SOCKHASH_LOCK_WRITE();
- rover = tcp_port_rover;
- do {
- rover += 1;
- if((rover < low) || (rover > high))
- rover = low;
- tb = tcp_bhash[tcp_bhashfn(rover)];
- for( ; tb; tb = tb->next) {
- if(tb->port == rover)
- goto next;
- }
- break;
- next:
- } while(--remaining > 0);
- tcp_port_rover = rover;
- tb = NULL;
- if((remaining <= 0) || ((tb = tcp_bucket_create(rover)) == NULL))
- rover = 0;
- if (tb != NULL)
- tb->flags |= TCPB_FLAG_GOODSOCKNUM;
+ __tcp_put_port(sk);
SOCKHASH_UNLOCK_WRITE();
+}
- return rover;
+static __inline__ void __tcp_v4_hash(struct sock *sk)
+{
+ struct sock **skp;
+
+ if(sk->state == TCP_LISTEN)
+ skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
+ else
+ skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
+
+ if((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+ sk->prot->inuse++;
+ if(sk->prot->highestinuse < sk->prot->inuse)
+ sk->prot->highestinuse = sk->prot->inuse;
}
static void tcp_v4_hash(struct sock *sk)
{
if (sk->state != TCP_CLOSE) {
- struct sock **skp;
-
SOCKHASH_LOCK_WRITE();
- skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
- if((sk->next = *skp) != NULL)
- (*skp)->pprev = &sk->next;
- *skp = sk;
- sk->pprev = skp;
- tcp_sk_bindify(sk);
+ __tcp_v4_hash(sk);
SOCKHASH_UNLOCK_WRITE();
}
}
@@ -325,39 +349,9 @@ static void tcp_v4_unhash(struct sock *sk)
sk->next->pprev = sk->pprev;
*sk->pprev = sk->next;
sk->pprev = NULL;
+ sk->prot->inuse--;
tcp_reg_zap(sk);
- tcp_sk_unbindify(sk);
- }
- SOCKHASH_UNLOCK_WRITE();
-}
-
-static void tcp_v4_rehash(struct sock *sk)
-{
- unsigned char state;
-
- SOCKHASH_LOCK_WRITE();
- state = sk->state;
- if(sk->pprev != NULL) {
- if(sk->next)
- sk->next->pprev = sk->pprev;
- *sk->pprev = sk->next;
- sk->pprev = NULL;
- tcp_reg_zap(sk);
- }
- if(state != TCP_CLOSE) {
- struct sock **skp;
-
- if(state == TCP_LISTEN)
- skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
- else
- skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
-
- if((sk->next = *skp) != NULL)
- (*skp)->pprev = &sk->next;
- *skp = sk;
- sk->pprev = skp;
- if(state == TCP_LISTEN)
- tcp_sk_bindify(sk);
+ __tcp_put_port(sk);
}
SOCKHASH_UNLOCK_WRITE();
}
@@ -1344,7 +1338,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
#endif
memcpy(newsk, sk, sizeof(*newsk));
- newsk->sklist_next = NULL;
newsk->state = TCP_SYN_RECV;
/* Clone the TCP header template */
@@ -1536,8 +1529,11 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (newsk->sndbuf < (3 * newtp->pmtu_cookie))
newsk->sndbuf = min ((3 * newtp->pmtu_cookie), sysctl_wmem_max);
- tcp_v4_hash(newsk);
- add_to_prot_sklist(newsk);
+ SOCKHASH_LOCK_WRITE();
+ __tcp_v4_hash(newsk);
+ __tcp_inherit_port(sk, newsk);
+ SOCKHASH_UNLOCK_WRITE();
+
sk->data_ready(sk, 0); /* Deliver SIGIO */
return newsk;
@@ -1780,6 +1776,25 @@ do_time_wait:
goto discard_it;
}
+static void __tcp_v4_rehash(struct sock *sk)
+{
+ struct sock **skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
+
+ SOCKHASH_LOCK_WRITE();
+ if(sk->pprev) {
+ if(sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ tcp_reg_zap(sk);
+ }
+ if((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+ SOCKHASH_UNLOCK_WRITE();
+}
+
int tcp_v4_rebuild_header(struct sock *sk)
{
struct rtable *rt = (struct rtable *)sk->dst_cache;
@@ -1853,7 +1868,12 @@ do_rewrite:
sk->saddr = new_saddr;
sk->rcv_saddr = new_saddr;
- tcp_v4_rehash(sk);
+
+ /* XXX The only one ugly spot where we need to
+ * XXX really change the sockets identity after
+ * XXX it has entered the hashes. -DaveM
+ */
+ __tcp_v4_rehash(sk);
}
return 0;
@@ -1948,20 +1968,192 @@ static int tcp_v4_destroy_sock(struct sock *sk)
while((skb = __skb_dequeue(&tp->out_of_order_queue)) != NULL)
kfree_skb(skb);
- /* Clean up a locked TCP bind bucket, this only happens if a
+ /* Clean up a referenced TCP bind bucket, this only happens if a
* port is allocated for a socket, but it never fully connects.
- * In which case we will find num to be non-zero and daddr to
- * be zero.
*/
- if(sk->daddr == 0 && sk->num != 0)
- tcp_bucket_unlock(sk);
+ if(sk->prev != NULL)
+ tcp_put_port(sk);
return 0;
}
+/* Proc filesystem TCP sock list dumping. */
+static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf, int i)
+{
+ sprintf(tmpbuf, "%4d: %08lX:%04X %08lX:%04X"
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u",
+ i,
+ (long unsigned int)req->af.v4_req.loc_addr,
+ ntohs(sk->sport),
+ (long unsigned int)req->af.v4_req.rmt_addr,
+ ntohs(req->rmt_port),
+ TCP_SYN_RECV,
+ 0,0, /* could print option size, but that is af dependent. */
+ 1, /* timers active (only the expire timer) */
+ (unsigned long)(req->expires - jiffies),
+ req->retrans,
+ sk->socket ? sk->socket->inode->i_uid : 0,
+ 0, /* non standard timer */
+ 0 /* open_requests have no inode */
+ );
+}
+
+static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i)
+{
+ unsigned int dest, src;
+ __u16 destp, srcp;
+ int timer_active, timer_active1, timer_active2;
+ unsigned long timer_expires;
+ struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
+
+ dest = sp->daddr;
+ src = sp->rcv_saddr;
+ destp = ntohs(sp->dport);
+ srcp = ntohs(sp->sport);
+ timer_active1 = tp->retransmit_timer.prev != NULL;
+ timer_active2 = sp->timer.prev != NULL;
+ timer_active = 0;
+ timer_expires = (unsigned) -1;
+ if (timer_active1 && tp->retransmit_timer.expires < timer_expires) {
+ timer_active = 1;
+ timer_expires = tp->retransmit_timer.expires;
+ }
+ if (timer_active2 && sp->timer.expires < timer_expires) {
+ timer_active = 2;
+ timer_expires = sp->timer.expires;
+ }
+ if(timer_active == 0)
+ timer_expires = jiffies;
+
+ sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
+ i, src, srcp, dest, destp, sp->state,
+ tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
+ timer_active, timer_expires-jiffies,
+ tp->retransmits,
+ sp->socket ? sp->socket->inode->i_uid : 0,
+ timer_active ? sp->timeout : 0,
+ sp->socket ? sp->socket->inode->i_ino : 0);
+}
+
+static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+{
+ extern int tcp_tw_death_row_slot;
+ unsigned int dest, src;
+ __u16 destp, srcp;
+ int slot_dist;
+
+ dest = tw->daddr;
+ src = tw->rcv_saddr;
+ destp = ntohs(tw->dport);
+ srcp = ntohs(tw->sport);
+
+ slot_dist = tw->death_slot;
+ if(slot_dist > tcp_tw_death_row_slot)
+ slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
+ else
+ slot_dist = tcp_tw_death_row_slot - slot_dist;
+
+ sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+ " %02X %08X:%08X %02X:%08X %08X %5d %8d %d",
+ i, src, srcp, dest, destp, TCP_TIME_WAIT, 0, 0,
+ 3, slot_dist * TCP_TWKILL_PERIOD, 0, 0, 0, 0);
+}
+
+int tcp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len = 0, num = 0, i;
+ off_t begin, pos = 0;
+ char tmpbuf[129];
+
+ if (offset < 128)
+ len += sprintf(buffer, "%-127s\n",
+ " sl local_address rem_address st tx_queue "
+ "rx_queue tr tm->when retrnsmt uid timeout inode");
+
+ pos = 128;
+ SOCKHASH_LOCK_READ();
+
+ /* First, walk listening socket table. */
+ for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
+ struct sock *sk = tcp_listening_hash[i];
+
+ for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) {
+ struct open_request *req;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (sk->family != PF_INET)
+ continue;
+ pos += 128;
+ if (pos >= offset) {
+ get_tcp_sock(sk, tmpbuf, num);
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if (len >= length)
+ goto out;
+ }
+ for (req = tp->syn_wait_queue; req; req = req->dl_next, num++) {
+ if (req->sk)
+ continue;
+ pos += 128;
+ if (pos < offset)
+ continue;
+ get_openreq(sk, req, tmpbuf, num);
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+ }
+
+ /* Next, walk established hash chain. */
+ for (i = 0; i < (tcp_ehash_size >> 1); i++) {
+ struct sock *sk;
+
+ for(sk = tcp_ehash[i]; sk; sk = sk->next, num++) {
+ if (sk->family != PF_INET)
+ continue;
+ pos += 128;
+ if (pos < offset)
+ continue;
+ get_tcp_sock(sk, tmpbuf, num);
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+
+ /* Finally, walk time wait buckets. */
+ for (i = (tcp_ehash_size>>1); i < tcp_ehash_size; i++) {
+ struct tcp_tw_bucket *tw;
+ for (tw = (struct tcp_tw_bucket *)tcp_ehash[i];
+ tw != NULL;
+ tw = (struct tcp_tw_bucket *)tw->next, num++) {
+ if (tw->family != PF_INET)
+ continue;
+ pos += 128;
+ if (pos < offset)
+ continue;
+ get_timewait_sock(tw, tmpbuf, num);
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+
+out:
+ SOCKHASH_UNLOCK_READ();
+
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
struct proto tcp_prot = {
- (struct sock *)&tcp_prot, /* sklist_next */
- (struct sock *)&tcp_prot, /* sklist_prev */
tcp_close, /* close */
tcp_v4_connect, /* connect */
tcp_accept, /* accept */
@@ -1981,9 +2173,7 @@ struct proto tcp_prot = {
tcp_v4_do_rcv, /* backlog_rcv */
tcp_v4_hash, /* hash */
tcp_v4_unhash, /* unhash */
- tcp_v4_rehash, /* rehash */
- tcp_good_socknum, /* good_socknum */
- tcp_v4_verify_bind, /* verify_bind */
+ tcp_v4_get_port, /* get_port */
128, /* max_header */
0, /* retransmits */
"TCP", /* name */
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index d23eef143..05a92f7f7 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_timer.c,v 1.64 1999/05/27 00:37:31 davem Exp $
+ * Version: $Id: tcp_timer.c,v 1.65 1999/07/02 11:26:35 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -31,7 +31,6 @@ int sysctl_tcp_retries2 = TCP_RETR2;
static void tcp_sltimer_handler(unsigned long);
static void tcp_syn_recv_timer(unsigned long);
static void tcp_keepalive(unsigned long data);
-static void tcp_bucketgc(unsigned long);
static void tcp_twkill(unsigned long);
struct timer_list tcp_slow_timer = {
@@ -44,8 +43,7 @@ struct timer_list tcp_slow_timer = {
struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX] = {
{ATOMIC_INIT(0), TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK */
{ATOMIC_INIT(0), TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive}, /* KEEPALIVE */
- {ATOMIC_INIT(0), TCP_TWKILL_PERIOD, 0, tcp_twkill}, /* TWKILL */
- {ATOMIC_INIT(0), TCP_BUCKETGC_PERIOD, 0, tcp_bucketgc} /* BUCKETGC */
+ {ATOMIC_INIT(0), TCP_TWKILL_PERIOD, 0, tcp_twkill} /* TWKILL */
};
const char timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
@@ -252,43 +250,6 @@ static __inline__ int tcp_keepopen_proc(struct sock *sk)
return res;
}
-/* Garbage collect TCP bind buckets. */
-static void tcp_bucketgc(unsigned long data)
-{
- int i, reaped = 0;;
-
- SOCKHASH_LOCK_WRITE_BH();
- for(i = 0; i < tcp_bhash_size; i++) {
- struct tcp_bind_bucket *tb = tcp_bhash[i];
-
- while(tb) {
- struct tcp_bind_bucket *next = tb->next;
-
- if((tb->owners == NULL) &&
- !(tb->flags & TCPB_FLAG_LOCKED)) {
- reaped++;
-
- /* Unlink bucket. */
- if(tb->next)
- tb->next->pprev = tb->pprev;
- *tb->pprev = tb->next;
-
- /* Finally, free it up. */
- kmem_cache_free(tcp_bucket_cachep, tb);
- }
- tb = next;
- }
- }
- SOCKHASH_UNLOCK_WRITE_BH();
-
- if(reaped != 0) {
- struct tcp_sl_timer *slt = (struct tcp_sl_timer *)data;
-
- /* Eat timer references. */
- atomic_sub(reaped, &slt->count);
- }
-}
-
/* Kill off TIME_WAIT sockets once their lifetime has expired. */
int tcp_tw_death_row_slot = 0;
static struct tcp_tw_bucket *tcp_tw_death_row[TCP_TWKILL_SLOTS] =
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 27dd7afcf..c99dffff0 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -5,7 +5,7 @@
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.69 1999/06/09 11:15:31 davem Exp $
+ * Version: $Id: udp.c,v 1.71 1999/07/02 11:26:33 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -123,164 +123,102 @@ struct udp_mib udp_statistics;
struct sock *udp_hash[UDP_HTABLE_SIZE];
-static int udp_v4_verify_bind(struct sock *sk, unsigned short snum)
-{
- struct sock *sk2;
- int retval = 0, sk_reuse = sk->reuse;
-
- SOCKHASH_LOCK_READ();
- for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) {
- if((sk2->num == snum) && (sk2 != sk)) {
- unsigned char state = sk2->state;
- int sk2_reuse = sk2->reuse;
-
- /* Two sockets can be bound to the same port if they're
- * bound to different interfaces.
- */
-
- if(sk2->bound_dev_if != sk->bound_dev_if)
- continue;
+/* Shared by v4/v6 udp. */
+int udp_port_rover = 0;
- if(!sk2->rcv_saddr || !sk->rcv_saddr) {
- if((!sk2_reuse) ||
- (!sk_reuse) ||
- (state == TCP_LISTEN)) {
- retval = 1;
- break;
- }
- } else if(sk2->rcv_saddr == sk->rcv_saddr) {
- if((!sk_reuse) ||
- (!sk2_reuse) ||
- (state == TCP_LISTEN)) {
- retval = 1;
- break;
- }
+static int udp_v4_get_port(struct sock *sk, unsigned short snum)
+{
+ SOCKHASH_LOCK_WRITE();
+ if (snum == 0) {
+ int best_size_so_far, best, result, i;
+
+ if (udp_port_rover > sysctl_local_port_range[1] ||
+ udp_port_rover < sysctl_local_port_range[0])
+ udp_port_rover = sysctl_local_port_range[0];
+ best_size_so_far = 32767;
+ best = result = udp_port_rover;
+ for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
+ struct sock *sk;
+ int size;
+
+ sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+ if (!sk) {
+ if (result > sysctl_local_port_range[1])
+ result = sysctl_local_port_range[0] +
+ ((result - sysctl_local_port_range[0]) &
+ (UDP_HTABLE_SIZE - 1));
+ goto gotit;
}
+ size = 0;
+ do {
+ if (++size >= best_size_so_far)
+ goto next;
+ } while ((sk = sk->next) != NULL);
+ best_size_so_far = size;
+ best = result;
+ next:
+ }
+ result = best;
+ for(;; result += UDP_HTABLE_SIZE) {
+ if (result > sysctl_local_port_range[1])
+ result = sysctl_local_port_range[0]
+ + ((result - sysctl_local_port_range[0]) &
+ (UDP_HTABLE_SIZE - 1));
+ if (!udp_lport_inuse(result))
+ break;
+ }
+gotit:
+ udp_port_rover = snum = result;
+ } else {
+ struct sock *sk2;
+
+ for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+ sk2 != NULL;
+ sk2 = sk2->next) {
+ if (sk2->num == snum &&
+ sk2 != sk &&
+ sk2->bound_dev_if == sk->bound_dev_if &&
+ (!sk2->rcv_saddr ||
+ !sk->rcv_saddr ||
+ sk2->rcv_saddr == sk->rcv_saddr) &&
+ (!sk2->reuse || !sk->reuse))
+ goto fail;
}
}
- SOCKHASH_UNLOCK_READ();
- return retval;
-}
-
-static inline int udp_lport_inuse(u16 num)
-{
- struct sock *sk = udp_hash[num & (UDP_HTABLE_SIZE - 1)];
-
- for(; sk != NULL; sk = sk->next) {
- if(sk->num == num)
- return 1;
- }
+ sk->num = snum;
+ SOCKHASH_UNLOCK_WRITE();
return 0;
-}
-
-/* Shared by v4/v6 udp. */
-unsigned short udp_good_socknum(void)
-{
- int result;
- static int start = 0;
- int i, best, best_size_so_far;
-
- SOCKHASH_LOCK_READ();
- if (start > sysctl_local_port_range[1] || start < sysctl_local_port_range[0])
- start = sysctl_local_port_range[0];
-
- best_size_so_far = 32767; /* "big" num */
- best = result = start;
-
- for(i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
- struct sock *sk;
- int size;
-
- sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
-
- if(!sk) {
- if (result > sysctl_local_port_range[1])
- result = sysctl_local_port_range[0]
- + ((result - sysctl_local_port_range[0]) & (UDP_HTABLE_SIZE - 1));
- goto out;
- }
-
- /* Is this one better than our best so far? */
- size = 0;
- do {
- if(++size >= best_size_so_far)
- goto next;
- } while((sk = sk->next) != NULL);
- best_size_so_far = size;
- best = result;
- next:
- }
- result = best;
-
- for(;; result += UDP_HTABLE_SIZE) {
- /* Get into range (but preserve hash bin)... */
- if (result > sysctl_local_port_range[1])
- result = sysctl_local_port_range[0]
- + ((result - sysctl_local_port_range[0]) & (UDP_HTABLE_SIZE - 1));
- if (!udp_lport_inuse(result))
- break;
- }
-out:
- start = result;
- SOCKHASH_UNLOCK_READ();
- return result;
+fail:
+ SOCKHASH_UNLOCK_WRITE();
+ return 1;
}
static void udp_v4_hash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
-
- num &= (UDP_HTABLE_SIZE - 1);
- skp = &udp_hash[num];
+ struct sock **skp = &udp_hash[sk->num & (UDP_HTABLE_SIZE - 1)];
SOCKHASH_LOCK_WRITE();
- sk->next = *skp;
+ if ((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
*skp = sk;
- sk->hashent = num;
+ sk->pprev = skp;
+ sk->prot->inuse++;
+ if(sk->prot->highestinuse < sk->prot->inuse)
+ sk->prot->highestinuse = sk->prot->inuse;
SOCKHASH_UNLOCK_WRITE();
}
static void udp_v4_unhash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
-
- num &= (UDP_HTABLE_SIZE - 1);
- skp = &udp_hash[num];
-
- SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
- }
- SOCKHASH_UNLOCK_WRITE();
-}
-
-static void udp_v4_rehash(struct sock *sk)
-{
- struct sock **skp;
- int num = sk->num;
- int oldnum = sk->hashent;
-
- num &= (UDP_HTABLE_SIZE - 1);
- skp = &udp_hash[oldnum];
-
SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
+ if (sk->pprev) {
+ if (sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ sk->prot->inuse--;
}
- sk->next = udp_hash[num];
- udp_hash[num] = sk;
- sk->hashent = num;
SOCKHASH_UNLOCK_WRITE();
}
@@ -653,7 +591,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
if (msg->msg_name) {
struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;
if (msg->msg_namelen < sizeof(*usin))
- return(-EINVAL);
+ return -EINVAL;
if (usin->sin_family != AF_INET)
return -EINVAL;
@@ -788,7 +726,6 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
unsigned long amount;
- if (sk->state == TCP_LISTEN) return(-EINVAL);
amount = sock_wspace(sk);
return put_user(amount, (int *)arg);
}
@@ -798,8 +735,6 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
struct sk_buff *skb;
unsigned long amount;
- if (sk->state == TCP_LISTEN)
- return(-EINVAL);
amount = 0;
/* N.B. Is this interrupt safe??
-> Yes. Interrupts do not remove skbs. --ANK (980725)
@@ -817,7 +752,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
}
default:
- return(-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
}
return(0);
}
@@ -841,8 +776,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
/*
* Check any passed addresses
*/
- if (addr_len)
- *addr_len=sizeof(*sin);
+ if (addr_len)
+ *addr_len=sizeof(*sin);
if (flags & MSG_ERRQUEUE)
return ip_recv_error(sk, msg, len);
@@ -945,7 +880,7 @@ int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (addr_len < sizeof(*usin))
- return(-EINVAL);
+ return -EINVAL;
/*
* 1003.1g - break association.
@@ -961,7 +896,7 @@ int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
}
if (usin->sin_family && usin->sin_family != AF_INET)
- return(-EAFNOSUPPORT);
+ return -EAFNOSUPPORT;
dst_release(xchg(&sk->dst_cache, NULL));
@@ -1226,9 +1161,69 @@ csum_error:
return(0);
}
+static void get_udp_sock(struct sock *sp, char *tmpbuf, int i)
+{
+ unsigned int dest, src;
+ __u16 destp, srcp;
+ int timer_active;
+ unsigned long timer_expires;
+
+ dest = sp->daddr;
+ src = sp->rcv_saddr;
+ destp = ntohs(sp->dport);
+ srcp = ntohs(sp->sport);
+ timer_active = (sp->timer.prev != NULL) ? 2 : 0;
+ timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
+ sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
+ i, src, srcp, dest, destp, sp->state,
+ atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
+ timer_active, timer_expires-jiffies, 0,
+ sp->socket->inode->i_uid, timer_active ? sp->timeout : 0,
+ sp->socket ? sp->socket->inode->i_ino : 0);
+}
+
+int udp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len = 0, num = 0, i;
+ off_t pos = 0;
+ off_t begin;
+ char tmpbuf[129];
+
+ if (offset < 128)
+ len += sprintf(buffer, "%-127s\n",
+ " sl local_address rem_address st tx_queue "
+ "rx_queue tr tm->when retrnsmt uid timeout inode");
+ pos = 128;
+ SOCKHASH_LOCK_READ();
+ for (i = 0; i < UDP_HTABLE_SIZE; i++) {
+ struct sock *sk;
+
+ for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
+ if (sk->family != PF_INET)
+ continue;
+ pos += 128;
+ if (pos < offset)
+ continue;
+ get_udp_sock(sk, tmpbuf, i);
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+out:
+ SOCKHASH_UNLOCK_READ();
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
struct proto udp_prot = {
- (struct sock *)&udp_prot, /* sklist_next */
- (struct sock *)&udp_prot, /* sklist_prev */
udp_close, /* close */
udp_connect, /* connect */
NULL, /* accept */
@@ -1248,9 +1243,7 @@ struct proto udp_prot = {
udp_queue_rcv_skb, /* backlog_rcv */
udp_v4_hash, /* hash */
udp_v4_unhash, /* unhash */
- udp_v4_rehash, /* rehash */
- udp_good_socknum, /* good_socknum */
- udp_v4_verify_bind, /* verify_bind */
+ udp_v4_get_port, /* good_socknum */
128, /* max_header */
0, /* retransmits */
"UDP", /* name */
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index f7f50df86..f565921d3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -7,7 +7,7 @@
*
* Adapted from linux/net/ipv4/af_inet.c
*
- * $Id: af_inet6.c,v 1.44 1999/06/09 08:29:29 davem Exp $
+ * $Id: af_inet6.c,v 1.45 1999/07/02 11:26:38 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -157,7 +157,6 @@ static int inet6_create(struct socket *sock, int protocol)
*/
sk->sport = ntohs(sk->num);
sk->prot->hash(sk);
- add_to_prot_sklist(sk);
}
if (sk->prot->init) {
@@ -205,13 +204,13 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
addr_type = ipv6_addr_type(&addr->sin6_addr);
if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM)
- return(-EINVAL);
+ return -EINVAL;
/* Check if the address belongs to the host. */
if (addr_type == IPV6_ADDR_MAPPED) {
v4addr = addr->sin6_addr.s6_addr32[3];
if (inet_addr_type(v4addr) != RTN_LOCAL)
- return(-EADDRNOTAVAIL);
+ return -EADDRNOTAVAIL;
} else {
if (addr_type != IPV6_ADDR_ANY) {
/* ipv4 addr of the socket is invalid. Only the
@@ -220,7 +219,7 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
if (ipv6_chk_addr(&addr->sin6_addr, NULL, 0) == NULL)
- return(-EADDRNOTAVAIL);
+ return -EADDRNOTAVAIL;
}
}
}
@@ -236,21 +235,17 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
sizeof(struct in6_addr));
snum = ntohs(addr->sin6_port);
- if (snum == 0)
- snum = sk->prot->good_socknum();
- if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
- return(-EACCES);
+ if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+ return -EACCES;
/* Make sure we are allowed to bind here. */
- if(sk->prot->verify_bind(sk, snum))
+ if(sk->prot->get_port(sk, snum) != 0)
return -EADDRINUSE;
- sk->num = snum;
sk->sport = ntohs(sk->num);
sk->dport = 0;
sk->daddr = 0;
- sk->prot->rehash(sk);
- add_to_prot_sklist(sk);
+ sk->prot->hash(sk);
return(0);
}
@@ -318,7 +313,7 @@ static int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
sk = sock->sk;
if (peer) {
if (!tcp_connected(sk->state))
- return(-ENOTCONN);
+ return -ENOTCONN;
sin->sin6_port = sk->dport;
memcpy(&sin->sin6_addr, &sk->net_pinfo.af_inet6.daddr,
sizeof(struct in6_addr));
diff --git a/net/ipv6/ip6_fw.c b/net/ipv6/ip6_fw.c
index a6263d41c..bf63c8c0b 100644
--- a/net/ipv6/ip6_fw.c
+++ b/net/ipv6/ip6_fw.c
@@ -92,12 +92,11 @@ static __inline__ struct ip6_fw_rule * ip6_fwrule_alloc(void)
struct ip6_fw_rule *rl;
rl = kmalloc(sizeof(struct ip6_fw_rule), GFP_ATOMIC);
-
- memset(rl, 0, sizeof(struct ip6_fw_rule));
-
if (rl)
+ {
+ memset(rl, 0, sizeof(struct ip6_fw_rule));
rl->flowr.ops = &ip6_fw_ops;
-
+ }
return rl;
}
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index b83bdc34b..09845703b 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -7,7 +7,7 @@
* PROC file system. This is very similar to the IPv4 version,
* except it reports the sockets in the INET6 address family.
*
- * Version: $Id: proc.c,v 1.10 1999/05/27 00:38:14 davem Exp $
+ * Version: $Id: proc.c,v 1.11 1999/07/02 11:26:45 davem Exp $
*
* Authors: David S. Miller (davem@caip.rutgers.edu)
*
@@ -26,140 +26,6 @@
#include <net/transp_v6.h>
#include <net/ipv6.h>
-/* This is the main implementation workhorse of all these routines. */
-static int get__netinfo6(struct proto *pro, char *buffer, int format, char **start,
- off_t offset, int length)
-{
- struct sock *sp;
- struct tcp_opt *tp;
- int timer_active, timer_active1, timer_active2;
- unsigned long timer_expires;
- struct in6_addr *dest, *src;
- unsigned short destp, srcp;
- int len = 0, i = 0;
- off_t pos = 0;
- off_t begin;
- char tmpbuf[150];
-
- if(offset < 149)
- len += sprintf(buffer, "%-148s\n",
- " sl " /* 6 */
- "local_address " /* 38 */
- "remote_address " /* 38 */
- "st tx_queue rx_queue tr tm->when retrnsmt" /* 41 */
- " uid timeout inode"); /* 21 */
- /*----*/
- /*144 */
-
- pos = 149;
- SOCKHASH_LOCK_READ();
- sp = pro->sklist_next;
- while(sp != (struct sock *)pro) {
- struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sp;
- int tw_bucket = 0;
-
- pos += 149;
- if(pos < offset)
- goto next;
- tp = &(sp->tp_pinfo.af_tcp);
- if((format == 0) && (sp->state == TCP_TIME_WAIT)) {
- tw_bucket = 1;
- dest = &tw->v6_daddr;
- src = &tw->v6_rcv_saddr;
- } else {
- dest = &sp->net_pinfo.af_inet6.daddr;
- src = &sp->net_pinfo.af_inet6.rcv_saddr;
- }
- destp = ntohs(sp->dport);
- srcp = ntohs(sp->sport);
-
- if((format == 0) && (sp->state == TCP_TIME_WAIT)) {
- extern int tcp_tw_death_row_slot;
- int slot_dist;
-
- timer_active1 = timer_active2 = 0;
- timer_active = 3;
- slot_dist = tw->death_slot;
- if(slot_dist > tcp_tw_death_row_slot)
- slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
- else
- slot_dist = tcp_tw_death_row_slot - slot_dist;
- timer_expires = jiffies + (slot_dist * TCP_TWKILL_PERIOD);
- } else {
- timer_active1 = tp->retransmit_timer.prev != NULL;
- timer_active2 = sp->timer.prev != NULL;
- timer_active = 0;
- timer_expires = (unsigned) -1;
- }
- if(timer_active1 && tp->retransmit_timer.expires < timer_expires) {
- timer_active = timer_active1;
- timer_expires = tp->retransmit_timer.expires;
- }
- if(timer_active2 && sp->timer.expires < timer_expires) {
- timer_active = timer_active2;
- timer_expires = sp->timer.expires;
- }
- if(timer_active == 0)
- timer_expires = jiffies;
- sprintf(tmpbuf, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
- "%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
- i,
- src->s6_addr32[0], src->s6_addr32[1],
- src->s6_addr32[2], src->s6_addr32[3], srcp,
- dest->s6_addr32[0], dest->s6_addr32[1],
- dest->s6_addr32[2], dest->s6_addr32[3], destp,
- sp->state,
- (tw_bucket ?
- 0 :
- (format == 0) ?
- tp->write_seq-tp->snd_una :
- atomic_read(&sp->wmem_alloc)),
- (tw_bucket ?
- 0 :
- (format == 0) ?
- tp->rcv_nxt-tp->copied_seq :
- atomic_read(&sp->rmem_alloc)),
- timer_active, timer_expires-jiffies,
- (tw_bucket ? 0 : tp->retransmits),
- ((!tw_bucket && sp->socket) ?
- sp->socket->inode->i_uid : 0),
- (!tw_bucket && timer_active) ? sp->timeout : 0,
- ((!tw_bucket && sp->socket) ?
- sp->socket->inode->i_ino : 0));
-
- len += sprintf(buffer+len, "%-148s\n", tmpbuf);
- if(len >= length)
- break;
- next:
- sp = sp->sklist_next;
- i++;
- }
- SOCKHASH_UNLOCK_READ();
-
- begin = len - (pos - offset);
- *start = buffer + begin;
- len -= begin;
- if(len > length)
- len = length;
- return len;
-}
-
-/* These get exported and registered with procfs in af_inet6.c at init time. */
-int tcp6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- return get__netinfo6(&tcpv6_prot, buffer, 0, start, offset, length);
-}
-
-int udp6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- return get__netinfo6(&udpv6_prot, buffer, 1, start, offset, length);
-}
-
-int raw6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- return get__netinfo6(&rawv6_prot, buffer, 1, start, offset, length);
-}
-
int afinet6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
int len = 0;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 70394dc03..f6c0a42ac 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -7,7 +7,7 @@
*
* Adapted from linux/net/ipv4/raw.c
*
- * $Id: raw.c,v 1.26 1999/06/09 10:11:18 davem Exp $
+ * $Id: raw.c,v 1.27 1999/07/02 11:26:40 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -39,63 +39,33 @@
#include <net/rawv6.h>
-#include <asm/uaccess.h>
-
struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE];
static void raw_v6_hash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
+ struct sock **skp = &raw_v6_htable[sk->num & (RAWV6_HTABLE_SIZE - 1)];
- num &= (RAWV6_HTABLE_SIZE - 1);
- skp = &raw_v6_htable[num];
SOCKHASH_LOCK_WRITE();
- sk->next = *skp;
+ if ((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
*skp = sk;
- sk->hashent = num;
+ sk->pprev = skp;
+ sk->prot->inuse++;
+ if(sk->prot->highestinuse < sk->prot->inuse)
+ sk->prot->highestinuse = sk->prot->inuse;
SOCKHASH_UNLOCK_WRITE();
}
static void raw_v6_unhash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
-
- num &= (RAWV6_HTABLE_SIZE - 1);
- skp = &raw_v6_htable[num];
-
SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
- }
- SOCKHASH_UNLOCK_WRITE();
-}
-
-static void raw_v6_rehash(struct sock *sk)
-{
- struct sock **skp;
- int num = sk->num;
- int oldnum = sk->hashent;
-
- num &= (RAWV6_HTABLE_SIZE - 1);
- skp = &raw_v6_htable[oldnum];
-
- SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
+ if (sk->pprev) {
+ if (sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ sk->prot->inuse--;
}
- sk->next = raw_v6_htable[num];
- raw_v6_htable[num] = sk;
- sk->hashent = num;
SOCKHASH_UNLOCK_WRITE();
}
@@ -636,9 +606,80 @@ static int rawv6_init_sk(struct sock *sk)
return(0);
}
+static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i)
+{
+ struct in6_addr *dest, *src;
+ __u16 destp, srcp;
+ int timer_active;
+ unsigned long timer_expires;
+
+ dest = &sp->net_pinfo.af_inet6.daddr;
+ src = &sp->net_pinfo.af_inet6.rcv_saddr;
+ destp = ntohs(sp->dport);
+ srcp = ntohs(sp->sport);
+ timer_active = (sp->timer.prev != NULL) ? 2 : 0;
+ timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
+ sprintf(tmpbuf,
+ "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+ "%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
+ i,
+ src->s6_addr32[0], src->s6_addr32[1],
+ src->s6_addr32[2], src->s6_addr32[3], srcp,
+ dest->s6_addr32[0], dest->s6_addr32[1],
+ dest->s6_addr32[2], dest->s6_addr32[3], destp,
+ sp->state,
+ atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
+ timer_active, timer_expires-jiffies, 0,
+ sp->socket->inode->i_uid, timer_active ? sp->timeout : 0,
+ sp->socket ? sp->socket->inode->i_ino : 0);
+}
+
+int raw6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len = 0, num = 0, i;
+ off_t pos = 0;
+ off_t begin;
+ char tmpbuf[150];
+
+ if (offset < 149)
+ len += sprintf(buffer, "%-148s\n",
+ " sl " /* 6 */
+ "local_address " /* 38 */
+ "remote_address " /* 38 */
+ "st tx_queue rx_queue tr tm->when retrnsmt" /* 41 */
+ " uid timeout inode"); /* 21 */
+ /*----*/
+ /*144 */
+ pos = 149;
+ SOCKHASH_LOCK_READ();
+ for (i = 0; i < RAWV6_HTABLE_SIZE; i++) {
+ struct sock *sk;
+
+ for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) {
+ if (sk->family != PF_INET6)
+ continue;
+ pos += 149;
+ if (pos < offset)
+ continue;
+ get_raw6_sock(sk, tmpbuf, i);
+ len += sprintf(buffer+len, "%-148s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+out:
+ SOCKHASH_UNLOCK_READ();
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
struct proto rawv6_prot = {
- (struct sock *)&rawv6_prot, /* sklist_next */
- (struct sock *)&rawv6_prot, /* sklist_prev */
rawv6_close, /* close */
udpv6_connect, /* connect */
NULL, /* accept */
@@ -658,9 +699,7 @@ struct proto rawv6_prot = {
rawv6_rcv_skb, /* backlog_rcv */
raw_v6_hash, /* hash */
raw_v6_unhash, /* unhash */
- raw_v6_rehash, /* rehash */
- NULL, /* good_socknum */
- NULL, /* verify_bind */
+ NULL, /* get_port */
128, /* max_header */
0, /* retransmits */
"RAW", /* name */
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5f8ff914b..9e9a73585 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -37,7 +37,6 @@
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/tcp.h>
-#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <asm/uaccess.h>
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 2164e245e..4cb6a56e9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: tcp_ipv6.c,v 1.108 1999/06/09 08:29:43 davem Exp $
+ * $Id: tcp_ipv6.c,v 1.109 1999/07/02 11:26:41 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
@@ -84,101 +84,124 @@ static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
* But it doesn't matter, the recalculation is in the rarest path
* this function ever takes.
*/
-static int tcp_v6_verify_bind(struct sock *sk, unsigned short snum)
+static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
{
struct tcp_bind_bucket *tb;
- int result = 0;
SOCKHASH_LOCK_WRITE();
- for(tb = tcp_bhash[tcp_bhashfn(snum)];
- (tb && (tb->port != snum));
- tb = tb->next)
- ;
- if(tb && tb->owners) {
- /* Fast path for reuse ports, see include/net/tcp.h for a very
- * detailed description of why this works, and why it is worth
- * the effort at all. -DaveM
- */
- if((tb->flags & TCPB_FLAG_FASTREUSE) &&
- (sk->reuse != 0)) {
- goto go_like_smoke;
+ if (snum == 0) {
+ int rover = tcp_port_rover;
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int remaining = (high - low) + 1;
+
+ do { rover++;
+ if ((rover < low) || (rover > high))
+ rover = low;
+ tb = tcp_bhash[tcp_bhashfn(rover)];
+ for ( ; tb; tb = tb->next)
+ if (tb->port == rover)
+ goto next;
+ break;
+ next:
+ } while (--remaining > 0);
+ tcp_port_rover = rover;
+
+ /* Exhausted local port range during search? */
+ if (remaining <= 0)
+ goto fail;
+
+ /* OK, here is the one we will use. */
+ snum = rover;
+ tb = NULL;
+ } else {
+ for (tb = tcp_bhash[tcp_bhashfn(snum)];
+ tb != NULL;
+ tb = tb->next)
+ if (tb->port == snum)
+ break;
+ }
+ if (tb != NULL && tb->owners != NULL) {
+ if (tb->fastreuse != 0 && sk->reuse != 0) {
+ goto success;
} else {
- struct sock *sk2;
+ struct sock *sk2 = tb->owners;
int sk_reuse = sk->reuse;
int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
/* We must walk the whole port owner list in this case. -DaveM */
- for(sk2 = tb->owners; sk2; sk2 = sk2->bind_next) {
- if(sk->bound_dev_if == sk2->bound_dev_if) {
- if(!sk_reuse || !sk2->reuse || sk2->state == TCP_LISTEN) {
- if(addr_type == IPV6_ADDR_ANY ||
- !sk2->rcv_saddr ||
- !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
- &sk2->net_pinfo.af_inet6.rcv_saddr))
+ for( ; sk2 != NULL; sk2 = sk2->bind_next) {
+ if (sk->bound_dev_if == sk2->bound_dev_if) {
+ if (!sk_reuse ||
+ !sk2->reuse ||
+ sk2->state == TCP_LISTEN) {
+ if (!sk2->rcv_saddr ||
+ !addr_type == IPV6_ADDR_ANY ||
+ !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
+ &sk2->net_pinfo.af_inet6.rcv_saddr))
break;
}
}
}
- if(sk2 != NULL)
- result = 1;
+ /* If we found a conflict, fail. */
+ if (sk2 != NULL)
+ goto fail;
}
}
- if(result == 0) {
- if(tb == NULL) {
- if((tb = tcp_bucket_create(snum)) == NULL)
- result = 1;
- else if (sk->reuse && sk->state != TCP_LISTEN)
- tb->flags |= TCPB_FLAG_FASTREUSE;
- } else {
- /* It could be pending garbage collection, this
- * kills the race and prevents it from disappearing
- * out from under us by the time we use it. -DaveM
- */
- if(tb->owners == NULL) {
- if (!(tb->flags & TCPB_FLAG_LOCKED)) {
- tb->flags = (TCPB_FLAG_LOCKED |
- ((sk->reuse &&
- sk->state != TCP_LISTEN) ?
- TCPB_FLAG_FASTREUSE : 0));
- tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
- } else if (!(tb->flags & TCPB_FLAG_GOODSOCKNUM)) {
- /* Someone is in between the bind
- * and the actual connect or listen.
- * See if it was a legitimate reuse
- * and we are as well, else punt.
- */
- if (sk->reuse == 0 ||
- !(tb->flags & TCPB_FLAG_FASTREUSE))
- result = 1;
- } else
- tb->flags &= ~TCPB_FLAG_GOODSOCKNUM;
- }
- }
- }
-go_like_smoke:
+ if (tb == NULL &&
+ (tb = tcp_bucket_create(snum)) == NULL)
+ goto fail;
+ if (tb->owners == NULL) {
+ if (sk->reuse && sk->state != TCP_LISTEN)
+ tb->fastreuse = 1;
+ else
+ tb->fastreuse = 0;
+ } else if (tb->fastreuse &&
+ ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
+ tb->fastreuse = 0;
+
+success:
+ sk->num = snum;
+ if ((sk->bind_next = tb->owners) != NULL)
+ tb->owners->bind_pprev = &sk->bind_next;
+ tb->owners = sk;
+ sk->bind_pprev = &tb->owners;
+ sk->prev = (struct sock *) tb;
+
SOCKHASH_UNLOCK_WRITE();
- return result;
+ return 0;
+
+fail:
+ SOCKHASH_UNLOCK_WRITE();
+ return 1;
}
static void tcp_v6_hash(struct sock *sk)
{
- /* Well, I know that it is ugly...
- All this ->prot, ->af_specific etc. need LARGE cleanup --ANK
- */
- if (sk->tp_pinfo.af_tcp.af_specific == &ipv6_mapped) {
- tcp_prot.hash(sk);
- return;
- }
if(sk->state != TCP_CLOSE) {
struct sock **skp;
+ /* Well, I know that it is ugly...
+ * All this ->prot, ->af_specific etc. need LARGE cleanup --ANK
+ */
+ if (sk->tp_pinfo.af_tcp.af_specific == &ipv6_mapped) {
+ tcp_prot.hash(sk);
+ return;
+ }
+
+ if(sk->state == TCP_LISTEN)
+ skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
+ else
+ skp = &tcp_ehash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
+
SOCKHASH_LOCK_WRITE();
- skp = &tcp_ehash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
if((sk->next = *skp) != NULL)
(*skp)->pprev = &sk->next;
*skp = sk;
sk->pprev = skp;
- tcp_sk_bindify(sk);
+ sk->prot->inuse++;
+ if(sk->prot->highestinuse < sk->prot->inuse)
+ sk->prot->highestinuse = sk->prot->inuse;
SOCKHASH_UNLOCK_WRITE();
}
}
@@ -191,39 +214,9 @@ static void tcp_v6_unhash(struct sock *sk)
sk->next->pprev = sk->pprev;
*sk->pprev = sk->next;
sk->pprev = NULL;
- tcp_sk_unbindify(sk);
- tcp_reg_zap(sk);
- }
- SOCKHASH_UNLOCK_WRITE();
-}
-
-static void tcp_v6_rehash(struct sock *sk)
-{
- unsigned char state;
-
- SOCKHASH_LOCK_WRITE();
- state = sk->state;
- if(sk->pprev != NULL) {
- if(sk->next)
- sk->next->pprev = sk->pprev;
- *sk->pprev = sk->next;
- sk->pprev = NULL;
+ sk->prot->inuse--;
tcp_reg_zap(sk);
- }
- if(state != TCP_CLOSE) {
- struct sock **skp;
-
- if(state == TCP_LISTEN)
- skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
- else
- skp = &tcp_ehash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
-
- if((sk->next = *skp) != NULL)
- (*skp)->pprev = &sk->next;
- *skp = sk;
- sk->pprev = skp;
- if(state == TCP_LISTEN)
- tcp_sk_bindify(sk);
+ __tcp_put_port(sk);
}
SOCKHASH_UNLOCK_WRITE();
}
@@ -1063,8 +1056,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newsk->rcv_saddr= LOOPBACK4_IPV6;
newsk->prot->hash(newsk);
- add_to_prot_sklist(newsk);
-
+ tcp_inherit_port(sk, newsk);
sk->data_ready(sk, 0); /* Deliver SIGIO */
return newsk;
@@ -1666,18 +1658,214 @@ static int tcp_v6_destroy_sock(struct sock *sk)
/* Clean up a locked TCP bind bucket, this only happens if a
* port is allocated for a socket, but it never fully connects.
- * In which case we will find num to be non-zero and daddr to
- * be zero.
*/
- if(ipv6_addr_any(&(sk->net_pinfo.af_inet6.daddr)) && sk->num != 0)
- tcp_bucket_unlock(sk);
+ if(sk->prev != NULL)
+ tcp_put_port(sk);
return inet6_destroy_sock(sk);
}
+/* Proc filesystem TCPv6 sock list dumping. */
+static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf, int i)
+{
+ struct in6_addr *dest, *src;
+
+ src = &req->af.v6_req.loc_addr;
+ dest = &req->af.v6_req.rmt_addr;
+ sprintf(tmpbuf,
+ "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+ "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d",
+ i,
+ src->s6_addr32[0], src->s6_addr32[1],
+ src->s6_addr32[2], src->s6_addr32[3],
+ ntohs(sk->sport),
+ dest->s6_addr32[0], dest->s6_addr32[1],
+ dest->s6_addr32[2], dest->s6_addr32[3],
+ ntohs(req->rmt_port),
+ TCP_SYN_RECV,
+ 0,0, /* could print option size, but that is af dependent. */
+ 1, /* timers active (only the expire timer) */
+ (unsigned long)(req->expires - jiffies),
+ req->retrans,
+ sk->socket ? sk->socket->inode->i_uid : 0,
+ 0, /* non standard timer */
+ 0 /* open_requests have no inode */
+ );
+}
+
+static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i)
+{
+ struct in6_addr *dest, *src;
+ __u16 destp, srcp;
+ int timer_active, timer_active1, timer_active2;
+ unsigned long timer_expires;
+ struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
+
+ dest = &sp->net_pinfo.af_inet6.daddr;
+ src = &sp->net_pinfo.af_inet6.rcv_saddr;
+ destp = ntohs(sp->dport);
+ srcp = ntohs(sp->sport);
+ timer_active1 = tp->retransmit_timer.prev != NULL;
+ timer_active2 = sp->timer.prev != NULL;
+ timer_active = 0;
+ timer_expires = (unsigned) -1;
+ if (timer_active1 && tp->retransmit_timer.expires < timer_expires) {
+ timer_active = 1;
+ timer_expires = tp->retransmit_timer.expires;
+ }
+ if (timer_active2 && sp->timer.expires < timer_expires) {
+ timer_active = 2;
+ timer_expires = sp->timer.expires;
+ }
+ if(timer_active == 0)
+ timer_expires = jiffies;
+
+ sprintf(tmpbuf,
+ "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+ "%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
+ i,
+ src->s6_addr32[0], src->s6_addr32[1],
+ src->s6_addr32[2], src->s6_addr32[3], srcp,
+ dest->s6_addr32[0], dest->s6_addr32[1],
+ dest->s6_addr32[2], dest->s6_addr32[3], destp,
+ sp->state,
+ tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
+ timer_active, timer_expires-jiffies,
+ tp->retransmits,
+ sp->socket ? sp->socket->inode->i_uid : 0,
+ timer_active ? sp->timeout : 0,
+ sp->socket ? sp->socket->inode->i_ino : 0);
+}
+
+static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+{
+ extern int tcp_tw_death_row_slot;
+ struct in6_addr *dest, *src;
+ __u16 destp, srcp;
+ int slot_dist;
+
+ dest = &tw->v6_daddr;
+ src = &tw->v6_rcv_saddr;
+ destp = ntohs(tw->dport);
+ srcp = ntohs(tw->sport);
+
+ slot_dist = tw->death_slot;
+ if(slot_dist > tcp_tw_death_row_slot)
+ slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
+ else
+ slot_dist = tcp_tw_death_row_slot - slot_dist;
+
+ sprintf(tmpbuf,
+ "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+ "%02X %08X:%08X %02X:%08X %08X %5d %8d %d",
+ i,
+ src->s6_addr32[0], src->s6_addr32[1],
+ src->s6_addr32[2], src->s6_addr32[3], srcp,
+ dest->s6_addr32[0], dest->s6_addr32[1],
+ dest->s6_addr32[2], dest->s6_addr32[3], destp,
+ TCP_TIME_WAIT, 0, 0,
+ 3, slot_dist * TCP_TWKILL_PERIOD, 0, 0, 0, 0);
+}
+
+int tcp6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len = 0, num = 0, i;
+ off_t begin, pos = 0;
+ char tmpbuf[150];
+
+ if(offset < 149)
+ len += sprintf(buffer, "%-148s\n",
+ " sl " /* 6 */
+ "local_address " /* 38 */
+ "remote_address " /* 38 */
+ "st tx_queue rx_queue tr tm->when retrnsmt" /* 41 */
+ " uid timeout inode"); /* 21 */
+ /*----*/
+ /*144 */
+
+ pos = 149;
+ SOCKHASH_LOCK_READ();
+
+ /* First, walk listening socket table. */
+ for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
+ struct sock *sk = tcp_listening_hash[i];
+
+ for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) {
+ struct open_request *req;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (sk->family != PF_INET6)
+ continue;
+ pos += 149;
+ if (pos >= offset) {
+ get_tcp6_sock(sk, tmpbuf, num);
+ len += sprintf(buffer+len, "%-148s\n", tmpbuf);
+ if (len >= length)
+ goto out;
+ }
+ for (req = tp->syn_wait_queue; req; req = req->dl_next, num++) {
+ if (req->sk)
+ continue;
+ pos += 149;
+ if (pos < offset)
+ continue;
+ get_openreq6(sk, req, tmpbuf, num);
+ len += sprintf(buffer+len, "%-148s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+ }
+
+ /* Next, walk established hash chain. */
+ for (i = 0; i < (tcp_ehash_size >> 1); i++) {
+ struct sock *sk;
+
+ for(sk = tcp_ehash[i]; sk; sk = sk->next, num++) {
+ if (sk->family != PF_INET6)
+ continue;
+ pos += 149;
+ if (pos < offset)
+ continue;
+ get_tcp6_sock(sk, tmpbuf, num);
+ len += sprintf(buffer+len, "%-148s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+
+ /* Finally, walk time wait buckets. */
+ for (i = (tcp_ehash_size>>1); i < tcp_ehash_size; i++) {
+ struct tcp_tw_bucket *tw;
+ for (tw = (struct tcp_tw_bucket *)tcp_ehash[i];
+ tw != NULL;
+ tw = (struct tcp_tw_bucket *)tw->next, num++) {
+ if (tw->family != PF_INET6)
+ continue;
+ pos += 149;
+ if (pos < offset)
+ continue;
+ get_timewait6_sock(tw, tmpbuf, num);
+ len += sprintf(buffer+len, "%-148s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+
+out:
+ SOCKHASH_UNLOCK_READ();
+
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
struct proto tcpv6_prot = {
- (struct sock *)&tcpv6_prot, /* sklist_next */
- (struct sock *)&tcpv6_prot, /* sklist_prev */
tcp_close, /* close */
tcp_v6_connect, /* connect */
tcp_accept, /* accept */
@@ -1697,9 +1885,7 @@ struct proto tcpv6_prot = {
tcp_v6_do_rcv, /* backlog_rcv */
tcp_v6_hash, /* hash */
tcp_v6_unhash, /* unhash */
- tcp_v6_rehash, /* rehash */
- tcp_good_socknum, /* good_socknum */
- tcp_v6_verify_bind, /* verify_bind */
+ tcp_v6_get_port, /* get_port */
128, /* max_header */
0, /* retransmits */
"TCPv6", /* name */
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index da020d8fb..b3045c694 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -7,7 +7,7 @@
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp.c,v 1.42 1999/06/09 10:11:24 davem Exp $
+ * $Id: udp.c,v 1.43 1999/07/02 11:26:44 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -49,101 +49,102 @@ struct udp_mib udp_stats_in6;
/* Grrr, addr_type already calculated by caller, but I don't want
* to add some silly "cookie" argument to this method just for that.
*/
-static int udp_v6_verify_bind(struct sock *sk, unsigned short snum)
+static int udp_v6_get_port(struct sock *sk, unsigned short snum)
{
- struct sock *sk2;
- int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
- int retval = 0, sk_reuse = sk->reuse;
-
- SOCKHASH_LOCK_READ();
- for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) {
- if((sk2->num == snum) && (sk2 != sk)) {
- unsigned char state = sk2->state;
- int sk2_reuse = sk2->reuse;
-
- /* Two sockets can be bound to the same port if they're
- * bound to different interfaces.
- */
-
- if(sk2->bound_dev_if != sk->bound_dev_if)
- continue;
-
- if(addr_type == IPV6_ADDR_ANY || (!sk2->rcv_saddr)) {
- if((!sk2_reuse) ||
- (!sk_reuse) ||
- (state == TCP_LISTEN)) {
- retval = 1;
- break;
- }
- } else if(!ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
- &sk2->net_pinfo.af_inet6.rcv_saddr)) {
- if((!sk_reuse) ||
- (!sk2_reuse) ||
- (state == TCP_LISTEN)) {
- retval = 1;
- break;
- }
+ SOCKHASH_LOCK_WRITE();
+ if (snum == 0) {
+ int best_size_so_far, best, result, i;
+
+ if (udp_port_rover > sysctl_local_port_range[1] ||
+ udp_port_rover < sysctl_local_port_range[0])
+ udp_port_rover = sysctl_local_port_range[0];
+ best_size_so_far = 32767;
+ best = result = udp_port_rover;
+ for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
+ struct sock *sk;
+ int size;
+
+ sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+ if (!sk) {
+ if (result > sysctl_local_port_range[1])
+ result = sysctl_local_port_range[0] +
+ ((result - sysctl_local_port_range[0]) &
+ (UDP_HTABLE_SIZE - 1));
+ goto gotit;
}
+ size = 0;
+ do {
+ if (++size >= best_size_so_far)
+ goto next;
+ } while ((sk = sk->next) != NULL);
+ best_size_so_far = size;
+ best = result;
+ next:
+ }
+ result = best;
+ for(;; result += UDP_HTABLE_SIZE) {
+ if (result > sysctl_local_port_range[1])
+ result = sysctl_local_port_range[0]
+ + ((result - sysctl_local_port_range[0]) &
+ (UDP_HTABLE_SIZE - 1));
+ if (!udp_lport_inuse(result))
+ break;
+ }
+gotit:
+ udp_port_rover = snum = result;
+ } else {
+ struct sock *sk2;
+ int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
+
+ for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+ sk2 != NULL;
+ sk2 = sk2->next) {
+ if (sk2->num == snum &&
+ sk2 != sk &&
+ sk2->bound_dev_if == sk->bound_dev_if &&
+ (!sk2->rcv_saddr ||
+ addr_type == IPV6_ADDR_ANY ||
+ !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
+ &sk2->net_pinfo.af_inet6.rcv_saddr)) &&
+ (!sk2->reuse || !sk->reuse))
+ goto fail;
}
}
- SOCKHASH_UNLOCK_READ();
- return retval;
-}
-
-static void udp_v6_hash(struct sock *sk)
-{
- struct sock **skp;
- int num = sk->num;
- num &= (UDP_HTABLE_SIZE - 1);
- skp = &udp_hash[num];
+ sk->num = snum;
+ SOCKHASH_UNLOCK_WRITE();
+ return 0;
- SOCKHASH_LOCK_WRITE();
- sk->next = *skp;
- *skp = sk;
- sk->hashent = num;
+fail:
SOCKHASH_UNLOCK_WRITE();
+ return 1;
}
-static void udp_v6_unhash(struct sock *sk)
+static void udp_v6_hash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
-
- num &= (UDP_HTABLE_SIZE - 1);
- skp = &udp_hash[num];
+ struct sock **skp = &udp_hash[sk->num & (UDP_HTABLE_SIZE - 1)];
SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
- }
+ if ((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+ sk->prot->inuse++;
+ if(sk->prot->highestinuse < sk->prot->inuse)
+ sk->prot->highestinuse = sk->prot->inuse;
SOCKHASH_UNLOCK_WRITE();
}
-static void udp_v6_rehash(struct sock *sk)
+static void udp_v6_unhash(struct sock *sk)
{
- struct sock **skp;
- int num = sk->num;
- int oldnum = sk->hashent;
-
- num &= (UDP_HTABLE_SIZE - 1);
- skp = &udp_hash[oldnum];
-
SOCKHASH_LOCK_WRITE();
- while(*skp != NULL) {
- if(*skp == sk) {
- *skp = sk->next;
- break;
- }
- skp = &((*skp)->next);
+ if (sk->pprev) {
+ if (sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ sk->prot->inuse--;
}
- sk->next = udp_hash[num];
- udp_hash[num] = sk;
- sk->hashent = num;
SOCKHASH_UNLOCK_WRITE();
}
@@ -216,10 +217,10 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
}
if (addr_len < sizeof(*usin))
- return(-EINVAL);
+ return -EINVAL;
if (usin->sin6_family && usin->sin6_family != AF_INET6)
- return(-EAFNOSUPPORT);
+ return -EAFNOSUPPORT;
fl.fl6_flowlabel = 0;
if (np->sndflow) {
@@ -764,7 +765,7 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
return -EMSGSIZE;
if (msg->msg_flags & ~(MSG_DONTROUTE|MSG_DONTWAIT))
- return(-EINVAL);
+ return -EINVAL;
fl.fl6_flowlabel = 0;
@@ -773,13 +774,13 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
return udp_sendmsg(sk, msg, ulen);
if (addr_len < sizeof(*sin6))
- return(-EINVAL);
+ return -EINVAL;
if (sin6->sin6_family && sin6->sin6_family != AF_INET6)
- return(-EINVAL);
+ return -EINVAL;
if (sin6->sin6_port == 0)
- return(-EINVAL);
+ return -EINVAL;
udh.uh.dest = sin6->sin6_port;
daddr = &sin6->sin6_addr;
@@ -800,7 +801,7 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
daddr = &sk->net_pinfo.af_inet6.daddr;
} else {
if (sk->state != TCP_ESTABLISHED)
- return(-ENOTCONN);
+ return -ENOTCONN;
udh.uh.dest = sk->dport;
daddr = &sk->net_pinfo.af_inet6.daddr;
@@ -885,10 +886,80 @@ static struct inet6_protocol udpv6_protocol =
"UDPv6" /* name */
};
+static void get_udp6_sock(struct sock *sp, char *tmpbuf, int i)
+{
+ struct in6_addr *dest, *src;
+ __u16 destp, srcp;
+ int timer_active;
+ unsigned long timer_expires;
+
+ dest = &sp->net_pinfo.af_inet6.daddr;
+ src = &sp->net_pinfo.af_inet6.rcv_saddr;
+ destp = ntohs(sp->dport);
+ srcp = ntohs(sp->sport);
+ timer_active = (sp->timer.prev != NULL) ? 2 : 0;
+ timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
+ sprintf(tmpbuf,
+ "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+ "%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
+ i,
+ src->s6_addr32[0], src->s6_addr32[1],
+ src->s6_addr32[2], src->s6_addr32[3], srcp,
+ dest->s6_addr32[0], dest->s6_addr32[1],
+ dest->s6_addr32[2], dest->s6_addr32[3], destp,
+ sp->state,
+ atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
+ timer_active, timer_expires-jiffies, 0,
+ sp->socket->inode->i_uid, timer_active ? sp->timeout : 0,
+ sp->socket ? sp->socket->inode->i_ino : 0);
+}
+
+int udp6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len = 0, num = 0, i;
+ off_t pos = 0;
+ off_t begin;
+ char tmpbuf[150];
+
+ if (offset < 149)
+ len += sprintf(buffer, "%-148s\n",
+ " sl " /* 6 */
+ "local_address " /* 38 */
+ "remote_address " /* 38 */
+ "st tx_queue rx_queue tr tm->when retrnsmt" /* 41 */
+ " uid timeout inode"); /* 21 */
+ /*----*/
+ /*144 */
+ pos = 149;
+ SOCKHASH_LOCK_READ();
+ for (i = 0; i < UDP_HTABLE_SIZE; i++) {
+ struct sock *sk;
+
+ for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
+ if (sk->family != PF_INET6)
+ continue;
+ pos += 149;
+ if (pos < offset)
+ continue;
+ get_udp6_sock(sk, tmpbuf, i);
+ len += sprintf(buffer+len, "%-148s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+out:
+ SOCKHASH_UNLOCK_READ();
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
struct proto udpv6_prot = {
- (struct sock *)&udpv6_prot, /* sklist_next */
- (struct sock *)&udpv6_prot, /* sklist_prev */
udpv6_close, /* close */
udpv6_connect, /* connect */
NULL, /* accept */
@@ -908,9 +979,7 @@ struct proto udpv6_prot = {
udpv6_queue_rcv_skb, /* backlog_rcv */
udp_v6_hash, /* hash */
udp_v6_unhash, /* unhash */
- udp_v6_rehash, /* rehash */
- udp_good_socknum, /* good_socknum */
- udp_v6_verify_bind, /* verify_bind */
+ udp_v6_get_port, /* get_port */
128, /* max_header */
0, /* retransmits */
"UDP", /* name */
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 929278b68..b6ccfa711 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -794,7 +794,8 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
if(call_fw_firewall(PF_IPX, skb->dev, ipx, NULL, &skb) == FW_ACCEPT)
{
skb2=skb_clone(skb, GFP_ATOMIC);
- ipxrtr_route_skb(skb2);
+ if(skb2)
+ ipxrtr_route_skb(skb2);
}
}
}
diff --git a/net/irda/compressors/irda_deflate.c b/net/irda/compressors/irda_deflate.c
index a78f372eb..bfb921277 100644
--- a/net/irda/compressors/irda_deflate.c
+++ b/net/irda/compressors/irda_deflate.c
@@ -54,7 +54,6 @@
#include <linux/malloc.h>
#include <linux/vmalloc.h>
#include <linux/errno.h>
-#include <linux/sched.h> /* to get the struct task_struct */
#include <linux/string.h> /* used in new tty drivers */
#include <linux/signal.h> /* used in new tty drivers */
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index ab7354e1d..cab4a11af 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -218,6 +218,8 @@ __initfunc(int irda_init(void))
misc_register( &irda.dev);
irda.in_use = FALSE;
+
+ init_waitqueue_head(&irda.wait_queue);
/*
* Initialize modules that got compiled into the kernel
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index a7732d76d..1cff39fa1 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -63,7 +63,6 @@
#include <linux/proc_fs.h>
#include <net/ip.h>
#include <net/arp.h>
-#include <linux/if_arp.h>
#include <linux/init.h>
int nr_ndevs = 4;
@@ -1311,6 +1310,11 @@ __initfunc(void nr_proto_init(struct net_proto *pro))
for (i = 0; i < nr_ndevs; i++) {
dev_nr[i].name = kmalloc(20, GFP_KERNEL);
+ if(dev_nr[i].name==NULL)
+ {
+ printk(KERN_ERR "Netrom: unable to register devices.\n");
+ break;
+ }
sprintf(dev_nr[i].name, "nr%d", i);
dev_nr[i].init = nr_init;
register_netdev(&dev_nr[i]);
diff --git a/net/netsyms.c b/net/netsyms.c
index 9fee8a822..f057c792b 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -25,6 +25,7 @@
#include <linux/hippidevice.h>
#endif
#include <net/pkt_sched.h>
+#include <net/scm.h>
#ifdef CONFIG_BRIDGE
#include <net/br.h>
@@ -32,7 +33,6 @@
#ifdef CONFIG_INET
#include <linux/ip.h>
-#include <linux/etherdevice.h>
#include <net/protocol.h>
#include <net/arp.h>
#include <net/ip.h>
@@ -40,9 +40,7 @@
#include <net/tcp.h>
#include <net/icmp.h>
#include <net/route.h>
-#include <net/scm.h>
#include <net/inet_common.h>
-#include <net/pkt_sched.h>
#include <linux/inet.h>
#include <linux/mroute.h>
#include <linux/igmp.h>
@@ -56,18 +54,18 @@ extern __u32 sysctl_rmem_max;
#include <linux/icmpv6.h>
#include <net/ipv6.h>
#include <net/ndisc.h>
-#include <net/dst.h>
#include <net/transp_v6.h>
extern int tcp_tw_death_row_slot;
+extern int sysctl_local_port_range[2];
+extern int tcp_port_rover;
+extern int udp_port_rover;
#endif
#endif
#include <linux/rtnetlink.h>
-#include <net/scm.h>
-
#if defined(CONFIG_ULTRA) || defined(CONFIG_WD80x3) || \
defined(CONFIG_EL2) || defined(CONFIG_NE2000) || \
defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
@@ -90,10 +88,6 @@ extern void destroy_8023_client(struct datalink_proto *);
#ifdef CONFIG_ATALK_MODULE
#include <net/sock.h>
-#include <net/dst.h>
-#include <net/checksum.h>
-#include <linux/etherdevice.h>
-#include <net/pkt_sched.h>
#endif
#ifdef CONFIG_SYSCTL
@@ -281,13 +275,11 @@ EXPORT_SYMBOL(inet_sendmsg);
EXPORT_SYMBOL(inet_recvmsg);
/* Socket demultiplexing. */
-EXPORT_SYMBOL(tcp_good_socknum);
EXPORT_SYMBOL(tcp_ehash);
EXPORT_SYMBOL(tcp_ehash_size);
EXPORT_SYMBOL(tcp_listening_hash);
EXPORT_SYMBOL(tcp_bhash);
EXPORT_SYMBOL(tcp_bhash_size);
-EXPORT_SYMBOL(udp_good_socknum);
EXPORT_SYMBOL(udp_hash);
EXPORT_SYMBOL(destroy_sock);
@@ -328,7 +320,9 @@ EXPORT_SYMBOL(tcp_v4_send_check);
EXPORT_SYMBOL(tcp_v4_conn_request);
EXPORT_SYMBOL(tcp_create_openreq_child);
EXPORT_SYMBOL(tcp_bucket_create);
-EXPORT_SYMBOL(tcp_bucket_unlock);
+EXPORT_SYMBOL(__tcp_put_port);
+EXPORT_SYMBOL(tcp_put_port);
+EXPORT_SYMBOL(tcp_inherit_port);
EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
EXPORT_SYMBOL(tcp_v4_do_rcv);
EXPORT_SYMBOL(tcp_v4_connect);
@@ -344,6 +338,9 @@ EXPORT_SYMBOL(tcp_transmit_skb);
EXPORT_SYMBOL(tcp_connect);
EXPORT_SYMBOL(tcp_make_synack);
EXPORT_SYMBOL(tcp_tw_death_row_slot);
+EXPORT_SYMBOL(sysctl_local_port_range);
+EXPORT_SYMBOL(tcp_port_rover);
+EXPORT_SYMBOL(udp_port_rover);
EXPORT_SYMBOL(tcp_sync_mss);
EXPORT_SYMBOL(net_statistics);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 1c27a4724..acba67395 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -54,7 +54,6 @@
#include <linux/proc_fs.h>
#include <net/ip.h>
#include <net/arp.h>
-#include <linux/if_arp.h>
#include <linux/init.h>
int rose_ndevs = 10;
@@ -1509,6 +1508,11 @@ __initfunc(void rose_proto_init(struct net_proto *pro))
for (i = 0; i < rose_ndevs; i++) {
dev_rose[i].name = kmalloc(20, GFP_KERNEL);
+ if(dev_rose[i].name == NULL)
+ {
+ printk(KERN_ERR "Rose: unable to register ROSE devices.\n");
+ break;
+ }
sprintf(dev_rose[i].name, "rose%d", i);
dev_rose[i].init = rose_init;
register_netdev(&dev_rose[i]);
diff --git a/net/socket.c b/net/socket.c
index 9a34b7580..2594dbfe8 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1443,7 +1443,7 @@ void __init sock_init(void)
{
int i;
- printk(KERN_INFO "Linux NET4.0 for Linux 2.2\n");
+ printk(KERN_INFO "Linux NET4.0 for Linux 2.3\n");
printk(KERN_INFO "Based upon Swansea University Computer Society NET3.039\n");
/*
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 0f2922dfd..87c0aedc1 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -362,10 +362,7 @@ xprt_close(struct rpc_xprt *xprt)
sk->state_change = xprt->old_state_change;
sk->write_space = xprt->old_write_space;
- if (xprt->file)
- fput(xprt->file);
- else
- sock_release(xprt->sock);
+ sock_release(xprt->sock);
/*
* TCP doesnt require the rpciod now - other things may
* but rpciod handles that not us.
@@ -1430,39 +1427,6 @@ xprt_setup(struct socket *sock, int proto,
}
/*
- * Create and initialize an RPC client given an open file.
- * This is obsolete now.
- */
-#if 0
-struct rpc_xprt *
-xprt_create(struct file *file, struct sockaddr_in *ap, struct rpc_timeout *to)
-{
- struct rpc_xprt *xprt;
- struct socket *sock;
- int proto;
-
- if (!file) {
- printk("RPC: file == NULL in xprt_create!\n");
- return NULL;
- }
-
- sock = &file->f_inode->u.socket_i;
- if (sock->ops->family != PF_INET) {
- printk(KERN_WARNING "RPC: only INET sockets supported\n");
- return NULL;
- }
-
- proto = (sock->type == SOCK_DGRAM)? IPPROTO_UDP : IPPROTO_TCP;
- if ((xprt = xprt_setup(sock, proto, ap, to)) != NULL) {
- xprt->file = file;
- atomic_inc(&file->f_count);
- }
-
- return xprt;
-}
-#endif
-
-/*
* Bind to a reserved port
*/
static inline int
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 3d0f25fc9..900e8942b 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -87,7 +87,6 @@
#include <linux/un.h>
#include <linux/fcntl.h>
#include <linux/termios.h>
-#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/in.h>
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index fa5a21fe1..ef24fec95 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -199,7 +199,7 @@ void unix_gc(void)
* in flight we are in use.
*/
if(s->socket && s->socket->file &&
- atomic_read(&s->socket->file->f_count) > s->protinfo.af_unix.inflight)
+ file_count(s->socket->file) > s->protinfo.af_unix.inflight)
maybe_unmark_and_push(s);
}
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
index d8bd1e33d..1cafd9aeb 100644
--- a/net/wanrouter/wanproc.c
+++ b/net/wanrouter/wanproc.c
@@ -123,13 +123,16 @@ static struct inode_operations router_inode =
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
- NULL, /* follow link */
NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* get_block */
+ NULL, /* flushpage */
NULL, /* truncate */
- router_proc_perms
+ router_proc_perms, /* permission */
+ NULL, /* smap */
+ NULL /* revalidate */
};
/*
@@ -165,15 +168,18 @@ static struct inode_operations wandev_inode =
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* get_block */
+ NULL, /* flushpage */
NULL, /* truncate */
- router_proc_perms
+ router_proc_perms, /* permission */
+ NULL, /* smap */
+ NULL /* revalidate */
};
/*
- * Proc filesystem derectory entries.
+ * Proc filesystem directory entries.
*/
/*
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index a4f070023..e65c1e86f 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -46,7 +46,6 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/proc_fs.h>
-#include <linux/if_arp.h>
#include <linux/init.h>
#include <net/x25.h>
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index bcbf31b0d..5db6a58a5 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -43,7 +43,6 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/proc_fs.h>
-#include <linux/if_arp.h>
#include <linux/firewall.h>
#include <net/x25.h>