summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
commit3917ac5846dd0f9ad1238166f90caab9912052e6 (patch)
tree1c298935def4f29edb39192365a65d73de999155 /net
parentaf2f803c8b2d469fe38e4a7ce952658dfcb6681a (diff)
o Merge with Linux 2.1.100.
o Cleanup the machine dependencies of floppy and rtc. The driver for the Dallas thingy in the Indy is still missing. o Handle allocation of zero'd pages correct for R4000SC / R4400SC. o Page colouring shit to match the virtual and physical colour of all mapped pages. This tends to produce extreme fragmentation problems, so it's deactivated for now. Users of R4000SC / R4400SC may re-enable the code in arch/mips/mm/init.c by removing the definition of CONF_GIVE_A_SHIT_ABOUT_COLOURS. Should get them somewhat further - but don't shake to hard ... o Fixed ptrace(2)-ing of syscalls, strace is now working again. o Fix the interrupt forwarding from the keyboard driver to the psaux driver, PS/2 mice are now working on the Indy. The fix is somewhat broken as it prevents generic kernels for Indy and machines which handle things different. o Things I can't remember.
Diffstat (limited to 'net')
-rw-r--r--net/appletalk/ddp.c6
-rw-r--r--net/core/dev.c10
-rw-r--r--net/core/scm.c17
-rw-r--r--net/core/sock.c4
-rw-r--r--net/ethernet/pe2.c3
-rw-r--r--net/ipv4/af_inet.c9
-rw-r--r--net/ipv4/devinet.c4
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/ip_fw.c153
-rw-r--r--net/ipv4/ip_sockglue.c9
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/tcp_input.c53
-rw-r--r--net/ipv4/tcp_ipv4.c38
-rw-r--r--net/ipv4/tcp_timer.c12
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/addrconf.c4
-rw-r--r--net/ipv6/af_inet6.c7
-rw-r--r--net/ipv6/exthdrs.c81
-rw-r--r--net/ipv6/icmp.c156
-rw-r--r--net/ipv6/ip6_input.c8
-rw-r--r--net/ipv6/ipv6_sockglue.c4
-rw-r--r--net/ipv6/mcast.c10
-rw-r--r--net/ipv6/ndisc.c3
-rw-r--r--net/ipv6/reassembly.c79
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/ipv6/tcp_ipv6.c23
-rw-r--r--net/netsyms.c2
-rw-r--r--net/packet/af_packet.c5
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/wanrouter/wanmain.c2
-rw-r--r--net/x25/af_x25.c2
31 files changed, 450 insertions, 264 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index c56adc148..b85835f47 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -719,7 +719,7 @@ int atif_ioctl(int cmd, void *arg)
switch(cmd)
{
case SIOCSIFADDR:
- if(!suser())
+ if(!capable(CAP_NET_ADMIN))
return (-EPERM);
if(sa->sat_family != AF_APPLETALK)
return (-EINVAL);
@@ -830,7 +830,7 @@ int atif_ioctl(int cmd, void *arg)
case SIOCATALKDIFADDR:
case SIOCDIFADDR:
- if(!suser())
+ if(!capable(CAP_NET_ADMIN))
return (-EPERM);
if(sa->sat_family != AF_APPLETALK)
return (-EINVAL);
@@ -1809,7 +1809,7 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
*/
case SIOCADDRT:
case SIOCDELRT:
- if(!suser())
+ if(!capable(CAP_NET_ADMIN))
return -EPERM;
return (atrtr_ioctl(cmd,(void *)arg));
diff --git a/net/core/dev.c b/net/core/dev.c
index 85312b12c..69315d948 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -321,7 +321,7 @@ struct device *dev_alloc(const char *name, int *err)
void dev_load(const char *name)
{
- if(!dev_get(name) && suser())
+ if(!dev_get(name) && capable(CAP_SYS_MODULE))
request_module(name);
}
@@ -1591,7 +1591,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
case SIOCDELMULTI:
case SIOCSIFHWBROADCAST:
case SIOCSIFTXQLEN:
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
dev_load(ifr.ifr_name);
rtnl_lock();
@@ -1764,6 +1764,9 @@ extern int baycom_init(void);
extern int lapbeth_init(void);
extern void arcnet_init(void);
extern void ip_auto_config(void);
+#ifdef CONFIG_8xx
+extern int cpm_enet_init(void);
+#endif /* CONFIG_8xx */
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry proc_net_dev = {
@@ -1846,6 +1849,9 @@ __initfunc(int net_dev_init(void))
#if defined(CONFIG_ARCNET)
arcnet_init();
#endif
+#if defined(CONFIG_8xx)
+ cpm_enet_init();
+#endif
/*
* SLHC if present needs attaching so other people see it
* even if not opened.
diff --git a/net/core/scm.c b/net/core/scm.c
index ac4aefda0..dd19cf5e0 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -45,19 +45,16 @@
static __inline__ int scm_check_creds(struct ucred *creds)
{
- /* N.B. The test for suser should follow the credential check */
- if (suser())
+ if ((creds->pid == current->pid || capable(CAP_SYS_ADMIN)) &&
+ ((creds->uid == current->uid || creds->uid == current->euid ||
+ creds->uid == current->suid) || capable(CAP_SETUID)) &&
+ ((creds->gid == current->gid || creds->gid == current->egid ||
+ creds->gid == current->sgid) || capable(CAP_SETGID))) {
return 0;
- if (creds->pid != current->pid ||
- (creds->uid != current->uid && creds->uid != current->euid &&
- creds->uid != current->suid) ||
- (creds->gid != current->gid && creds->gid != current->egid &&
- creds->gid != current->sgid))
- return -EPERM;
- return 0;
+ }
+ return -EPERM;
}
-
static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
{
int *fdp = (int*)CMSG_DATA(cmsg);
diff --git a/net/core/sock.c b/net/core/sock.c
index 30e5d3e77..428b4052c 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -185,7 +185,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
switch(optname)
{
case SO_DEBUG:
- if(val && !suser())
+ if(val && !capable(CAP_NET_ADMIN))
{
ret = -EACCES;
}
@@ -924,7 +924,7 @@ int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
*/
if (current->pgrp != -arg &&
current->pid != arg &&
- !suser()) return(-EPERM);
+ !capable(CAP_NET_ADMIN)) return(-EPERM);
sk->proc = arg;
return(0);
case F_GETOWN:
diff --git a/net/ethernet/pe2.c b/net/ethernet/pe2.c
index 812d35864..4915f0707 100644
--- a/net/ethernet/pe2.c
+++ b/net/ethernet/pe2.c
@@ -11,7 +11,8 @@ pEII_datalink_header(struct datalink_proto *dl,
struct device *dev = skb->dev;
skb->protocol = htons (ETH_P_IPX);
- dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
+ if(dev->hard_header)
+ dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
}
struct datalink_proto *
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index ce177c56b..a54ae8a95 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -374,7 +374,7 @@ static int inet_create(struct socket *sock, int protocol)
sock->ops = &inet_dgram_ops;
break;
case SOCK_RAW:
- if (!suser())
+ if (!capable(CAP_NET_RAW))
goto free_and_badperm;
if (!protocol)
goto free_and_noproto;
@@ -521,7 +521,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
#endif
if (snum == 0)
snum = sk->prot->good_socknum();
- if (snum < PROT_SOCK && !suser())
+ if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
return(-EACCES);
chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
@@ -529,7 +529,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) {
#ifdef CONFIG_IP_TRANSPARENT_PROXY
/* Superuser may bind to any address to allow transparent proxying. */
- if(chk_addr_ret != RTN_UNICAST || !suser())
+ if(chk_addr_ret != RTN_UNICAST || !capable(CAP_NET_ADMIN))
#endif
return -EADDRNOTAVAIL; /* Source address MUST be ours! */
}
@@ -868,7 +868,8 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
err = get_user(pid, (int *) arg);
if (err)
return err;
- if (current->pid != pid && current->pgrp != -pid && !suser())
+ if (current->pid != pid && current->pgrp != -pid &&
+ !capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
return(0);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 79eb9a1d4..47b5ef25c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -435,7 +435,7 @@ int devinet_ioctl(unsigned int cmd, void *arg)
break;
case SIOCSIFFLAGS:
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EACCES;
rtnl_lock();
exclusive = 1;
@@ -444,7 +444,7 @@ int devinet_ioctl(unsigned int cmd, void *arg)
case SIOCSIFBRDADDR: /* Set the broadcast address */
case SIOCSIFDSTADDR: /* Set the destination address */
case SIOCSIFNETMASK: /* Set the netmask for the interface */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EACCES;
if (sin->sin_family != AF_INET)
return -EINVAL;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 6350a6366..24f3052fe 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -253,7 +253,7 @@ int ip_rt_ioctl(unsigned int cmd, void *arg)
switch (cmd) {
case SIOCADDRT: /* Add a route */
case SIOCDELRT: /* Delete a route */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&r, arg, sizeof(struct rtentry)))
return -EFAULT;
diff --git a/net/ipv4/ip_fw.c b/net/ipv4/ip_fw.c
index b364f66de..745d07cb4 100644
--- a/net/ipv4/ip_fw.c
+++ b/net/ipv4/ip_fw.c
@@ -6,7 +6,7 @@
* license in recognition of the original copyright.
* -- Alan Cox.
*
- * $Id: ip_fw.c,v 1.4 1998/03/17 22:18:25 ralf Exp $
+ * $Id: ip_fw.c,v 1.35 1998/04/30 16:29:51 freitag Exp $
*
* Ported from BSD to Linux,
* Alan Cox 22/Nov/1994.
@@ -62,6 +62,7 @@
* Wouter Gadeyne : Fixed masquerading support of ftp PORT commands
*
* Juan Jose Ciarlante : Masquerading code moved to ip_masq.c
+ * Andi Kleen : Print frag_offsets and the ip flags properly.
*
* All the real work was done by .....
*
@@ -202,6 +203,90 @@ extern inline int port_match(unsigned short *portptr,int nports,unsigned short p
#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
+#ifdef CONFIG_IP_FIREWALL_VERBOSE
+
+/*
+ * VERY ugly piece of code which actually makes kernel printf for
+ * matching packets.
+ */
+
+static char *chain_name(struct ip_fw *chain, int mode)
+{
+ switch (mode) {
+ case IP_FW_MODE_ACCT_IN: return "acct in";
+ case IP_FW_MODE_ACCT_OUT: return "acct out";
+ default:
+ if (chain == ip_fw_fwd_chain)
+ return "fw-fwd";
+ else if (chain == ip_fw_in_chain)
+ return "fw-in";
+ else
+ return "fw-out";
+ }
+}
+
+static char *rule_name(struct ip_fw *f, int mode, char *buf)
+{
+ if (mode == IP_FW_MODE_ACCT_IN || mode == IP_FW_MODE_ACCT_OUT)
+ return "";
+
+ if(f->fw_flg&IP_FW_F_ACCEPT) {
+ if(f->fw_flg&IP_FW_F_REDIR) {
+ sprintf(buf, "acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
+ return buf;
+ } else if(f->fw_flg&IP_FW_F_MASQ)
+ return "acc/masq ";
+ else
+ return "acc ";
+ } else if(f->fw_flg&IP_FW_F_ICMPRPL) {
+ return "rej ";
+ } else {
+ return "deny ";
+ }
+}
+
+static void print_packet(struct iphdr *ip,
+ u16 src_port, u16 dst_port, u16 icmp_type,
+ char *chain, char *rule, char *devname)
+{
+ __u32 *opt = (__u32 *) (ip + 1);
+ int opti;
+ __u16 foff = ntohs(ip->frag_off);
+
+ printk(KERN_INFO "IP %s %s%s", chain, rule, devname);
+
+ switch(ip->protocol)
+ {
+ case IPPROTO_TCP:
+ printk(" TCP ");
+ break;
+ case IPPROTO_UDP:
+ printk(" UDP ");
+ break;
+ case IPPROTO_ICMP:
+ printk(" ICMP/%d ", icmp_type);
+ break;
+ default:
+ printk(" PROTO=%d ", ip->protocol);
+ break;
+ }
+ print_ip(ip->saddr);
+ if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
+ printk(":%hu", src_port);
+ printk(" ");
+ print_ip(ip->daddr);
+ if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
+ printk(":%hu", dst_port);
+ printk(" L=%hu S=0x%2.2hX I=%hu FO=0x%4.4hX T=%hu",
+ ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
+ foff & IP_OFFSET, ip->ttl);
+ if (foff & IP_DF) printk(" DF=1");
+ if (foff & IP_MF) printk(" MF=1");
+ for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
+ printk(" O=0x%8.8X", *opt++);
+ printk("\n");
+}
+#endif
/*
* Returns one of the generic firewall policies, like FW_ACCEPT.
@@ -483,68 +568,14 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, __u16 *redirport, struct ip_
}
#ifdef CONFIG_IP_FIREWALL_VERBOSE
- /*
- * VERY ugly piece of code which actually
- * makes kernel printf for matching packets...
- */
-
if (f->fw_flg & IP_FW_F_PRN)
{
- __u32 *opt = (__u32 *) (ip + 1);
- int opti;
-
- if(mode == IP_FW_MODE_ACCT_IN)
- printk(KERN_INFO "IP acct in ");
- else if(mode == IP_FW_MODE_ACCT_OUT)
- printk(KERN_INFO "IP acct out ");
- else {
- if(chain == ip_fw_fwd_chain)
- printk(KERN_INFO "IP fw-fwd ");
- else if(chain == ip_fw_in_chain)
- printk(KERN_INFO "IP fw-in ");
- else
- printk(KERN_INFO "IP fw-out ");
- if(f->fw_flg&IP_FW_F_ACCEPT) {
- if(f->fw_flg&IP_FW_F_REDIR)
- printk("acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
- else if(f->fw_flg&IP_FW_F_MASQ)
- printk("acc/masq ");
- else
- printk("acc ");
- } else if(f->fw_flg&IP_FW_F_ICMPRPL)
- printk("rej ");
- else
- printk("deny ");
- }
- printk(rif ? rif->name : "-");
- switch(ip->protocol)
- {
- case IPPROTO_TCP:
- printk(" TCP ");
- break;
- case IPPROTO_UDP:
- printk(" UDP ");
- break;
- case IPPROTO_ICMP:
- printk(" ICMP/%d ", icmp_type);
- break;
- default:
- printk(" PROTO=%d ", ip->protocol);
- break;
- }
- print_ip(ip->saddr);
- if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%hu", src_port);
- printk(" ");
- print_ip(ip->daddr);
- if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%hu", dst_port);
- printk(" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
- ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
- ip->frag_off, ip->ttl);
- for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
- printk(" O=0x%8.8X", *opt++);
- printk("\n");
+ char buf[16];
+
+ print_packet(ip, src_port, dst_port, icmp_type,
+ chain_name(chain, mode),
+ rule_name(f, mode, buf),
+ rif ? rif->name : "-");
}
#endif
if (mode != IP_FW_MODE_CHK) {
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 1b7f44e8f..b31a1d3a0 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -311,7 +311,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
/* Reject setting of unused bits */
if (val & ~(IPTOS_TOS_MASK|IPTOS_PREC_MASK))
return -EINVAL;
- if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && !suser())
+ if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP &&
+ !capable(CAP_NET_ADMIN))
return -EPERM;
if (sk->ip_tos != val) {
sk->ip_tos=val;
@@ -453,7 +454,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
case IP_FW_POLICY_OUT:
case IP_FW_POLICY_FWD:
case IP_FW_MASQ_TIMEOUTS:
- if(!suser())
+ if(!capable(CAP_NET_ADMIN))
return -EACCES;
if(optlen>sizeof(tmp_fw) || optlen<1)
return -EINVAL;
@@ -467,7 +468,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
case IP_FW_MASQ_ADD:
case IP_FW_MASQ_DEL:
case IP_FW_MASQ_FLUSH:
- if(!suser())
+ if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(optlen>sizeof(masq_ctl) || optlen<1)
return -EINVAL;
@@ -483,7 +484,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
case IP_ACCT_DELETE:
case IP_ACCT_FLUSH:
case IP_ACCT_ZERO:
- if(!suser())
+ if(!capable(CAP_NET_ADMIN))
return -EACCES;
if(optlen>sizeof(tmp_fw) || optlen<1)
return -EINVAL;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index baebab777..a73f12a49 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -398,7 +398,7 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) {
#ifdef CONFIG_IP_TRANSPARENT_PROXY
/* Superuser may bind to any address to allow transparent proxying. */
- if(chk_addr_ret != RTN_UNICAST || !suser())
+ if(chk_addr_ret != RTN_UNICAST || !capable(CAP_NET_ADMIN))
#endif
return -EADDRNOTAVAIL;
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index d5b0b15c6..7a0a40aeb 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.114 1998/04/28 06:42:22 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.116 1998/05/02 14:50:11 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -421,33 +421,6 @@ static __inline__ int tcp_fast_parse_options(struct sock *sk, struct tcphdr *th,
return 1;
}
-#if 0 /* Not working yet... -DaveM */
-static void tcp_compute_tsack(struct sock *sk, struct tcp_opt *tp)
-{
- struct sk_buff *skb = skb_peek(&sk->write_queue);
- __u32 tstamp = tp->rcv_tsecr;
- int fack_count = 0;
-
- while((skb != NULL) &&
- (skb != tp->send_head) &&
- (skb != (struct sk_buff *)&sk->write_queue)) {
- if(TCP_SKB_CB(skb)->when == tstamp) {
- __u8 sacked = TCP_SKB_CB(skb)->sacked;
-
- sacked |= TCPCB_SACKED_ACKED;
- if(sacked & TCPCB_SACKED_RETRANS)
- tp->retrans_out--;
- TCP_SKB_CB(skb)->sacked = sacked;
- }
- if(!before(TCP_SKB_CB(skb)->when, tstamp))
- fack_count++;
- skb = skb->next;
- }
- if(fack_count > tp->fackets_out)
- tp->fackets_out = fack_count;
-}
-#endif
-
#define FLAG_DATA 0x01 /* Incoming frame contained data. */
#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
#define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */
@@ -481,13 +454,6 @@ static void tcp_fast_retrans(struct sock *sk, u32 ack, int not_dup)
if (ack == tp->snd_una && tp->packets_out && (not_dup == 0)) {
/* This is the standard reno style fast retransmit branch. */
-#if 0 /* Not working yet... -DaveM */
- /* If not doing SACK, but doing timestamps, compute timestamp
- * based pseudo-SACKs when we see duplicate ACKs.
- */
- if(!tp->sack_ok && tp->saw_tstamp)
- tcp_compute_tsack(sk, tp);
-#endif
/* 1. When the third duplicate ack is received, set ssthresh
* to one half the current congestion window, but no less
* than two segments. Retransmit the missing segment.
@@ -611,6 +577,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __u32 ack,
while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) {
struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
+ __u8 sacked = scb->sacked;
/* If our packet is before the ack sequence we can
* discard it as it's confirmed to have arrived at
@@ -626,22 +593,12 @@ static int tcp_clean_rtx_queue(struct sock *sk, __u32 ack,
* connection startup slow start one packet too
* quickly. This is severely frowned upon behavior.
*/
+ if(sacked & TCPCB_SACKED_RETRANS && tp->retrans_out)
+ tp->retrans_out--;
if(!(scb->flags & TCPCB_FLAG_SYN)) {
- __u8 sacked = scb->sacked;
-
acked |= FLAG_DATA_ACKED;
- if(sacked & TCPCB_SACKED_RETRANS) {
+ if(sacked & TCPCB_SACKED_RETRANS)
acked |= FLAG_RETRANS_DATA_ACKED;
-
- /* XXX The race is, fast retrans frame -->
- * XXX retrans timeout sends older frame -->
- * XXX ACK arrives for fast retrans frame -->
- * XXX retrans_out goes negative --> splat.
- * XXX Please help me find a better way -DaveM
- */
- if(tp->retrans_out)
- tp->retrans_out--;
- }
if(tp->fackets_out)
tp->fackets_out--;
} else {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 08ca40a4b..328cc9389 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.142 1998/04/30 12:00:45 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.145 1998/05/02 12:47:13 davem Exp $
*
* IPv4 specific functions
*
@@ -48,7 +48,6 @@
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/stddef.h>
#include <linux/fcntl.h>
#include <linux/random.h>
#include <linux/init.h>
@@ -61,12 +60,15 @@
#include <asm/segment.h>
#include <linux/inet.h>
+#include <linux/stddef.h>
extern int sysctl_tcp_timestamps;
extern int sysctl_tcp_window_scaling;
extern int sysctl_tcp_sack;
extern int sysctl_tcp_syncookies;
extern int sysctl_ip_dynaddr;
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
/* Check TCP sequence numbers in ICMP packets. */
#define ICMP_MIN_LENGTH 8
@@ -166,17 +168,21 @@ struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
return tb;
}
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
/* Ensure that the bound bucket for the port exists.
* Return 0 on success.
*/
static __inline__ int tcp_bucket_check(unsigned short snum)
{
- if (tcp_bound_hash[tcp_bhashfn(snum)] == NULL &&
- tcp_bucket_create(snum) == NULL)
+ struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ for( ; (tb && (tb->port != snum)); tb = tb->next)
+ ;
+ if(tb == NULL && tcp_bucket_create(snum) == NULL)
return 1;
else
return 0;
}
+#endif
static int tcp_v4_verify_bind(struct sock *sk, unsigned short snum)
{
@@ -215,10 +221,21 @@ static int tcp_v4_verify_bind(struct sock *sk, unsigned short snum)
result = 1;
}
}
- if((result == 0) &&
- (tb == NULL) &&
- (tcp_bucket_create(snum) == NULL))
- result = 1;
+ if(result == 0) {
+ if(tb == NULL) {
+ if(tcp_bucket_create(snum) == NULL)
+ result = 1;
+ } 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 && !(tb->flags & TCPB_FLAG_LOCKED)) {
+ tb->flags = TCPB_FLAG_LOCKED;
+ tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
+ }
+ }
+ }
go_like_smoke:
SOCKHASH_UNLOCK();
return result;
@@ -1308,6 +1325,11 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (!newsk)
goto exit;
+ if (newsk->rcvbuf < (3 * newsk->mtu))
+ newsk->rcvbuf = min ((3 * newsk->mtu), sysctl_rmem_max);
+ if (newsk->sndbuf < (3 * newsk->mtu))
+ newsk->sndbuf = min ((3 * newsk->mtu), sysctl_wmem_max);
+
sk->tp_pinfo.af_tcp.syn_backlog--;
sk->ack_backlog++;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 9bf74f472..665a448bb 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.6 1998/03/17 22:18:35 ralf Exp $
+ * Version: $Id: tcp_timer.c,v 1.51 1998/05/02 15:19:26 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -448,26 +448,24 @@ void tcp_retransmit_timer(unsigned long data)
*/
if(tp->sack_ok) {
struct sk_buff *skb = skb_peek(&sk->write_queue);
- __u8 toclear = TCPCB_SACKED_ACKED;
- if(tp->retransmits == 0)
- toclear |= TCPCB_SACKED_RETRANS;
while((skb != NULL) &&
(skb != tp->send_head) &&
(skb != (struct sk_buff *)&sk->write_queue)) {
- TCP_SKB_CB(skb)->sacked &= ~(toclear);
+ TCP_SKB_CB(skb)->sacked &=
+ ~(TCPCB_SACKED_ACKED | TCPCB_SACKED_RETRANS);
skb = skb->next;
}
- tp->fackets_out = 0;
}
/* Retransmission. */
tp->retrans_head = NULL;
+ tp->fackets_out = 0;
+ tp->retrans_out = 0;
if (tp->retransmits == 0) {
/* remember window where we lost
* "one half of the current window but at least 2 segments"
*/
- tp->retrans_out = 0;
tp->snd_ssthresh = max(tp->snd_cwnd >> (1 + TCP_CWND_SHIFT), 2);
tp->snd_cwnd = (1 << TCP_CWND_SHIFT);
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index a580b0010..d42dcc3d4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -646,7 +646,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
#ifdef CONFIG_IP_TRANSPARENT_PROXY
if (msg->msg_flags&~(MSG_DONTROUTE|MSG_DONTWAIT|MSG_PROXY|MSG_NOSIGNAL))
return -EINVAL;
- if ((msg->msg_flags&MSG_PROXY) && !suser() )
+ if ((msg->msg_flags&MSG_PROXY) && !capable(CAP_NET_ADMIN))
return -EPERM;
#else
if (msg->msg_flags&~(MSG_DONTROUTE|MSG_DONTWAIT|MSG_NOSIGNAL))
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0241e0459..5571c04c7 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -894,7 +894,7 @@ int addrconf_add_ifaddr(void *arg)
struct in6_ifreq ireq;
int err;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
@@ -911,7 +911,7 @@ int addrconf_del_ifaddr(void *arg)
struct in6_ifreq ireq;
int err;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 902274ecb..c1b2e9d14 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -89,7 +89,7 @@ static int inet6_create(struct socket *sock, int protocol)
prot=&udpv6_prot;
sock->ops = &inet6_dgram_ops;
} else if(sock->type == SOCK_RAW) {
- if (!suser())
+ if (!capable(CAP_NET_RAW))
goto free_and_badperm;
if (!protocol)
goto free_and_noproto;
@@ -187,7 +187,7 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
snum = ntohs(addr->sin6_port);
if (snum == 0)
snum = sk->prot->good_socknum();
- if (snum < PROT_SOCK && !suser())
+ if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
return(-EACCES);
addr_type = ipv6_addr_type(&addr->sin6_addr);
@@ -291,7 +291,8 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return err;
/* see sock_no_fcntl */
- if (current->pid != pid && current->pgrp != -pid && !suser())
+ if (current->pid != pid && current->pgrp != -pid &&
+ !capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
return(0);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index af29057ec..0b826870f 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -4,8 +4,9 @@
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
+ * Andi Kleen <ak@muc.de>
*
- * $Id: exthdrs.c,v 1.5 1998/02/12 07:43:39 davem Exp $
+ * $Id: exthdrs.c,v 1.6 1998/04/30 16:24:20 freitag Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -34,6 +35,10 @@
#include <net/ip6_route.h>
#include <net/addrconf.h>
+#include <asm/uaccess.h>
+
+#define swap(a,b) do { typeof (a) tmp; tmp = (a); (a) = (b); (b) = (tmp); } while(0)
+
/*
* inbound
*/
@@ -135,7 +140,7 @@ int ipv6_routing_header(struct sk_buff **skb_ptr, struct device *dev,
*/
int ipv6opt_bld_rthdr(struct sk_buff *skb, struct ipv6_options *opt,
- struct in6_addr *addr, int proto)
+ struct in6_addr *addr)
{
struct rt0_hdr *phdr, *ihdr;
int hops;
@@ -153,8 +158,76 @@ int ipv6opt_bld_rthdr(struct sk_buff *skb, struct ipv6_options *opt,
ipv6_addr_copy(phdr->addr + (hops - 1), addr);
- phdr->rt_hdr.nexthdr = proto;
-
+ phdr->rt_hdr.nexthdr = proto;
return NEXTHDR_ROUTING;
}
#endif
+
+/*
+ * find out if nexthdr is an extension header or a protocol
+ */
+
+static __inline__ int ipv6_ext_hdr(u8 nexthdr)
+{
+ /*
+ * find out if nexthdr is an extension header or a protocol
+ */
+ return ( (nexthdr == NEXTHDR_HOP) ||
+ (nexthdr == NEXTHDR_ROUTING) ||
+ (nexthdr == NEXTHDR_FRAGMENT) ||
+ (nexthdr == NEXTHDR_ESP) ||
+ (nexthdr == NEXTHDR_AUTH) ||
+ (nexthdr == NEXTHDR_NONE) ||
+ (nexthdr == NEXTHDR_DEST) );
+
+}
+
+/*
+ * Skip any extension headers. This is used by the ICMP module.
+ *
+ * Note that strictly speaking this conflicts with RFC1883 4.0:
+ * ...The contents and semantics of each extension header determine whether
+ * or not to proceed to the next header. Therefore, extension headers must
+ * be processed strictly in the order they appear in the packet; a
+ * receiver must not, for example, scan through a packet looking for a
+ * particular kind of extension header and process that header prior to
+ * processing all preceding ones.
+ *
+ * We do exactly this. This is a protocol bug. We can't decide after a
+ * seeing an unknown discard-with-error flavour TLV option if it's a
+ * ICMP error message or not (errors should never be send in reply to
+ * ICMP error messages).
+ *
+ * But I see no other way to do this. This might need to be reexamined
+ * when Linux implements ESP (and maybe AUTH) headers.
+ */
+struct ipv6_opt_hdr *ipv6_skip_exthdr(struct ipv6_opt_hdr *hdr,
+ u8 *nexthdrp, int len)
+{
+ u8 nexthdr = *nexthdrp;
+
+ while (ipv6_ext_hdr(nexthdr)) {
+ int hdrlen;
+
+ if (nexthdr == NEXTHDR_NONE)
+ return NULL;
+ if (len < sizeof(struct ipv6_opt_hdr)) /* be anal today */
+ return NULL;
+
+ hdrlen = ipv6_optlen(hdr);
+ if (len < hdrlen)
+ return NULL;
+
+ nexthdr = hdr->nexthdr;
+ hdr = (struct ipv6_opt_hdr *) ((u8*)hdr + hdrlen);
+ len -= hdrlen;
+ }
+
+ /* Hack.. Do the same for AUTH headers? */
+ if (nexthdr == NEXTHDR_ESP)
+ return NULL;
+
+ *nexthdrp = nexthdr;
+ return hdr;
+}
+
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index f181aec52..104895936 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: icmp.c,v 1.15 1998/03/21 07:28:03 davem Exp $
+ * $Id: icmp.c,v 1.17 1998/05/01 10:31:41 davem Exp $
*
* Based on net/ipv4/icmp.c
*
@@ -21,6 +21,8 @@
* Changes:
*
* Andi Kleen : exception handling
+ * Andi Kleen add rate limits. never reply to a icmp.
+ * add more length checks and other fixes.
*/
#define __NO_VERSION__
@@ -51,6 +53,7 @@
#include <net/transp_v6.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
+#include <net/icmp.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -129,6 +132,62 @@ static int icmpv6_getfrag(const void *data, struct in6_addr *saddr,
return 0;
}
+
+/*
+ * Slightly more convenient version of icmpv6_send.
+ */
+void icmpv6_param_prob(struct sk_buff *skb, int code, void *pos)
+{
+ int offset = (u8*)pos - (u8*)skb->nh.ipv6h;
+
+ icmpv6_send(skb, ICMPV6_PARAMPROB, code, offset, skb->dev);
+ kfree_skb(skb);
+}
+
+static inline int is_icmp(struct ipv6hdr *hdr, int len)
+{
+ __u8 nexthdr = hdr->nexthdr;
+
+ if (!ipv6_skip_exthdr((struct ipv6_opt_hdr *)(hdr+1), &nexthdr, len))
+ return 0;
+ return nexthdr == IPPROTO_ICMP;
+}
+
+int sysctl_icmpv6_time = 1*HZ;
+
+/*
+ * Check the ICMP output rate limit
+ */
+static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+ struct flowi *fl)
+{
+#if 0
+ struct dst_entry *dst;
+ int allow = 0;
+#endif
+ /* Informational messages are not limited. */
+ if (type & 0x80)
+ return 1;
+
+#if 0 /* not yet, first fix routing COW */
+
+ /*
+ * Look up the output route.
+ * XXX: perhaps the expire for routing entries cloned by
+ * this lookup should be more aggressive (not longer than timeout).
+ */
+ dst = ip6_route_output(sk, fl, 1);
+ if (dst->error)
+ ipv6_statistics.Ip6OutNoRoutes++;
+ else
+ allow = xrlim_allow(dst, sysctl_icmpv6_time);
+ dst_release(dst);
+ return allow;
+#else
+ return 1;
+#endif
+}
+
/*
* an inline helper for the "simple" if statement below
* checks if parameter problem report is caused by an
@@ -214,6 +273,24 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
return;
}
+ /*
+ * Never answer to a ICMP packet.
+ */
+ if (is_icmp(hdr, (u8*)skb->tail - (u8*)hdr)) {
+ printk(KERN_DEBUG "icmpv6_send: no reply to icmp\n");
+ return;
+ }
+
+ fl.proto = IPPROTO_ICMPV6;
+ fl.nl_u.ip6_u.daddr = &hdr->saddr;
+ fl.nl_u.ip6_u.saddr = saddr;
+ fl.oif = iif;
+ fl.uli_u.icmpt.type = type;
+ fl.uli_u.icmpt.code = code;
+
+ if (!icmpv6_xrlim_allow(sk, type, &fl))
+ return;
+
/*
* ok. kick it. checksum will be provided by the
* getfrag_t callback.
@@ -248,13 +325,6 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
msg.len = len;
- fl.proto = IPPROTO_ICMPV6;
- fl.nl_u.ip6_u.daddr = &hdr->saddr;
- fl.nl_u.ip6_u.saddr = saddr;
- fl.oif = iif;
- fl.uli_u.icmpt.type = type;
- fl.uli_u.icmpt.code = code;
-
ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
MSG_DONTWAIT);
@@ -312,21 +382,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
dst_release(xchg(&sk->dst_cache, NULL));
}
-static __inline__ int ipv6_ext_hdr(u8 nexthdr)
-{
- /*
- * find out if nexthdr is an extension header or a protocol
- */
- return ( (nexthdr == NEXTHDR_HOP) ||
- (nexthdr == NEXTHDR_ROUTING) ||
- (nexthdr == NEXTHDR_FRAGMENT) ||
- (nexthdr == NEXTHDR_ESP) ||
- (nexthdr == NEXTHDR_AUTH) ||
- (nexthdr == NEXTHDR_NONE) ||
- (nexthdr == NEXTHDR_DEST) );
-
-}
-
static void icmpv6_notify(struct sk_buff *skb,
int type, int code, unsigned char *buff, int len,
struct in6_addr *saddr, struct in6_addr *daddr,
@@ -335,39 +390,22 @@ static void icmpv6_notify(struct sk_buff *skb,
struct ipv6hdr *hdr = (struct ipv6hdr *) buff;
struct inet6_protocol *ipprot;
struct sock *sk;
- char * pbuff;
+ struct ipv6_opt_hdr *pb;
__u32 info = 0;
int hash;
u8 nexthdr;
- /* now skip over extension headers */
-
nexthdr = hdr->nexthdr;
- pbuff = (char *) (hdr + 1);
+ pb = (struct ipv6_opt_hdr *) (hdr + 1);
len -= sizeof(struct ipv6hdr);
+ if (len < 0)
+ return;
- while (ipv6_ext_hdr(nexthdr)) {
- int hdrlen;
-
- if (nexthdr == NEXTHDR_NONE)
- return;
-
- nexthdr = *pbuff;
-
- /* Header length is size in 8-octet units, not
- * including the first 8 octets.
- */
- hdrlen = *(pbuff+1);
- hdrlen = (hdrlen + 1) << 3;
-
- if (hdrlen > len)
- return;
-
- /* Now this is right. */
- pbuff += hdrlen;
- len -= hdrlen;
- }
+ /* now skip over extension headers */
+ pb = ipv6_skip_exthdr(pb, &nexthdr, len);
+ if (!pb)
+ return;
hash = nexthdr & (MAX_INET_PROTOS - 1);
@@ -378,7 +416,7 @@ static void icmpv6_notify(struct sk_buff *skb,
continue;
if (ipprot->err_handler)
- ipprot->err_handler(skb, type, code, pbuff, info,
+ ipprot->err_handler(skb, type, code, (u8*)pb, info,
saddr, daddr, ipprot);
return;
}
@@ -391,7 +429,7 @@ static void icmpv6_notify(struct sk_buff *skb,
return;
while((sk = raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
- rawv6_err(sk, type, code, pbuff, saddr, daddr);
+ rawv6_err(sk, type, code, (char*)pb, saddr, daddr);
sk = sk->next;
}
}
@@ -514,7 +552,7 @@ discard_it:
return 0;
}
-__initfunc(void icmpv6_init(struct net_proto_family *ops))
+__initfunc(int icmpv6_init(struct net_proto_family *ops))
{
struct sock *sk;
int err;
@@ -528,11 +566,11 @@ __initfunc(void icmpv6_init(struct net_proto_family *ops))
icmpv6_socket->state = SS_UNCONNECTED;
icmpv6_socket->type=SOCK_RAW;
- if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0)
+ if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0) {
printk(KERN_DEBUG
"Failed to create the ICMP6 control socket.\n");
-
- MOD_DEC_USE_COUNT;
+ return 1;
+ }
sk = icmpv6_socket->sk;
sk->allocation = GFP_ATOMIC;
@@ -542,6 +580,16 @@ __initfunc(void icmpv6_init(struct net_proto_family *ops))
ndisc_init(ops);
igmp6_init(ops);
+ return 0;
+}
+
+void icmpv6_cleanup(void)
+{
+ inet6_del_protocol(&icmpv6_protocol);
+#if 0
+ ndisc_cleanup();
+#endif
+ igmp6_cleanup();
}
static struct icmp6_err {
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 71ad7e1a0..5f024dddb 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -6,7 +6,7 @@
* Pedro Roque <roque@di.fc.ul.pt>
* Ian P. Morris <I.P.Morris@soton.ac.uk>
*
- * $Id: ip6_input.c,v 1.8 1998/02/12 07:43:43 davem Exp $
+ * $Id: ip6_input.c,v 1.9 1998/04/30 16:24:24 freitag Exp $
*
* Based in linux/net/ipv4/ip_input.c
*
@@ -70,12 +70,6 @@ struct ipv6_tlvtype {
u8 len;
};
-struct ipv6_destopt_hdr {
- u8 nexthdr;
- u8 hdrlen;
-};
-
-
struct tlvtype_proc {
u8 type;
int (*func) (struct sk_buff *, struct device *dev, __u8 *ptr,
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 9bb2d4d3c..ebd3365cd 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -7,7 +7,7 @@
*
* Based on linux/net/ipv4/ip_sockglue.c
*
- * $Id: ipv6_sockglue.c,v 1.18 1998/03/20 09:12:18 davem Exp $
+ * $Id: ipv6_sockglue.c,v 1.19 1998/04/30 16:24:26 freitag Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -242,7 +242,7 @@ void ipv6_cleanup(void)
ipv6_sysctl_unregister();
#endif
ip6_route_cleanup();
- ndisc_cleanup();
+ icmpv6_cleanup();
addrconf_cleanup();
}
#endif
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 407698eb1..0e10dcf0b 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: mcast.c,v 1.14 1998/03/20 09:12:18 davem Exp $
+ * $Id: mcast.c,v 1.15 1998/04/30 16:24:28 freitag Exp $
*
* Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
*
@@ -619,8 +619,6 @@ __initfunc(void igmp6_init(struct net_proto_family *ops))
printk(KERN_DEBUG
"Failed to create the IGMP6 control socket.\n");
- MOD_DEC_USE_COUNT;
-
sk = igmp6_socket->sk;
sk->allocation = GFP_ATOMIC;
sk->num = 256; /* Don't receive any data */
@@ -632,3 +630,9 @@ __initfunc(void igmp6_init(struct net_proto_family *ops))
#endif
}
+void igmp6_cleanup(void)
+{
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("net/igmp6", 0);
+#endif
+}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 2e437f2de..e69d90332 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1152,9 +1152,6 @@ __initfunc(void ndisc_init(struct net_proto_family *ops))
printk(KERN_DEBUG
"Failed to create the NDISC control socket.\n");
- /* Eeeh... What is it? --ANK */
- MOD_DEC_USE_COUNT;
-
sk = ndisc_socket->sk;
sk->allocation = GFP_ATOMIC;
sk->net_pinfo.af_inet6.hop_limit = 255;
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 55fecc676..e78cf97a2 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: reassembly.c,v 1.9 1998/02/12 07:43:48 davem Exp $
+ * $Id: reassembly.c,v 1.10 1998/04/30 16:24:32 freitag Exp $
*
* Based on: net/ipv4/ip_fragment.c
*
@@ -15,6 +15,11 @@
* 2 of the License, or (at your option) any later version.
*/
+/*
+ * Fixes:
+ * Andi Kleen Make it work with multiple hosts.
+ * More RFC compliance.
+ */
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -39,8 +44,9 @@
static struct frag_queue ipv6_frag_queue = {
&ipv6_frag_queue, &ipv6_frag_queue,
- 0, {0}, NULL, NULL,
- 0
+ 0, {{{0}}}, {{{0}}},
+ {0}, NULL, NULL,
+ 0, 0, NULL
};
static void create_frag_entry(struct sk_buff *skb,
@@ -72,12 +78,11 @@ static int reasm_frag(struct frag_queue *fq, struct sk_buff **skb,
* one it's the kmalloc for a struct ipv6_frag.
* Feel free to try other alternatives...
*/
- reasm_queue(fq, *skb, fhdr);
-
if ((fhdr->frag_off & __constant_htons(0x0001)) == 0) {
fq->last_in = 1;
fq->nhptr = nhptr;
}
+ reasm_queue(fq, *skb, fhdr);
if (fq->last_in) {
if ((nh = reasm_frag_1(fq, skb)))
@@ -90,18 +95,27 @@ static int reasm_frag(struct frag_queue *fq, struct sk_buff **skb,
return 0;
}
-int ipv6_reassembly(struct sk_buff **skb, struct device *dev, __u8 *nhptr,
+int ipv6_reassembly(struct sk_buff **skbp, struct device *dev, __u8 *nhptr,
struct ipv6_options *opt)
{
- struct frag_hdr *fhdr = (struct frag_hdr *) ((*skb)->h.raw);
+ struct sk_buff *skb = *skbp;
+ struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw);
struct frag_queue *fq;
-
+ struct ipv6hdr *hdr;
+
+ if ((u8 *)(fhdr+1) > skb->tail) {
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
+ return 0;
+ }
+ hdr = skb->nh.ipv6h;
for (fq = ipv6_frag_queue.next; fq != &ipv6_frag_queue; fq = fq->next) {
- if (fq->id == fhdr->identification)
- return reasm_frag(fq, skb, nhptr,fhdr);
+ if (fq->id == fhdr->identification &&
+ !ipv6_addr_cmp(&hdr->saddr, &fq->saddr) &&
+ !ipv6_addr_cmp(&hdr->daddr, &fq->daddr))
+ return reasm_frag(fq, skbp, nhptr,fhdr);
}
- create_frag_entry(*skb, dev, nhptr, fhdr);
+ create_frag_entry(skb, dev, nhptr, fhdr);
return 0;
}
@@ -154,6 +168,7 @@ static void create_frag_entry(struct sk_buff *skb, struct device *dev,
struct frag_hdr *fhdr)
{
struct frag_queue *fq;
+ struct ipv6hdr *hdr;
fq = (struct frag_queue *) kmalloc(sizeof(struct frag_queue),
GFP_ATOMIC);
@@ -167,6 +182,10 @@ static void create_frag_entry(struct sk_buff *skb, struct device *dev,
fq->id = fhdr->identification;
+ hdr = skb->nh.ipv6h;
+ ipv6_addr_copy(&fq->saddr, &hdr->saddr);
+ ipv6_addr_copy(&fq->daddr, &hdr->daddr);
+
fq->dev = dev;
/* init_timer has been done by the memset */
@@ -193,14 +212,14 @@ static void create_frag_entry(struct sk_buff *skb, struct device *dev,
static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb,
- struct frag_hdr *fhdr)
+ struct frag_hdr *fhdr)
{
struct ipv6_frag *nfp, *fp, **bptr;
nfp = (struct ipv6_frag *) kmalloc(sizeof(struct ipv6_frag),
GFP_ATOMIC);
- if (nfp == NULL) {
+ if (nfp == NULL) {
kfree_skb(skb);
return;
}
@@ -209,6 +228,10 @@ static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb,
nfp->len = (ntohs(skb->nh.ipv6h->payload_len) -
((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
+ if ((u32)nfp->offset + (u32)nfp->len > 65536) {
+ icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off);
+ goto err;
+ }
nfp->skb = skb;
nfp->fhdr = fhdr;
@@ -224,19 +247,37 @@ static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb,
}
if (fp && fp->offset == nfp->offset) {
- if (fp->len != nfp->len) {
- /* this cannot happen */
+ if (nfp->len != fp->len) {
printk(KERN_DEBUG "reasm_queue: dup with wrong len\n");
}
/* duplicate. discard it. */
- kfree_skb(skb);
- kfree(nfp);
- return;
+ goto err;
}
*bptr = nfp;
nfp->next = fp;
+
+#ifdef STRICT_RFC
+ if (fhdr->frag_off & __constant_htons(0x0001)) {
+ /* Check if the fragment is rounded to 8 bytes.
+ * Required by the RFC.
+ */
+ if (nfp->len & 0x7) {
+ printk(KERN_DEBUG "fragment not rounded to 8bytes\n");
+
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
+ &skb->nh.ipv6h->payload_len);
+ goto err;
+ }
+ }
+#endif
+
+ return;
+
+err:
+ kfree(nfp);
+ kfree_skb(skb);
}
/*
@@ -303,6 +344,8 @@ static int reasm_frag_1(struct frag_queue *fq, struct sk_buff **skb_in)
/*
* FIXME: If we don't have a checksum we ought to be able
* to defragment and checksum in this pass. [AC]
+ * Note that we don't really know yet whether the protocol
+ * needs checksums at all. It might still be a good idea. -AK
*/
for(fp = fq->fragments; fp; ) {
struct ipv6_frag *back;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a71c9c0e5..3baa41007 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1379,7 +1379,7 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg)
switch(cmd) {
case SIOCADDRT: /* Add a route */
case SIOCDELRT: /* Delete a route */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = copy_from_user(&rtmsg, arg,
sizeof(struct in6_rtmsg));
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 721677fa6..0a4a95c7c 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.78 1998/04/16 16:29:22 freitag Exp $
+ * $Id: tcp_ipv6.c,v 1.80 1998/05/02 12:47:15 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
@@ -123,10 +123,21 @@ static int tcp_v6_verify_bind(struct sock *sk, unsigned short snum)
result = 1;
}
}
- if((result == 0) &&
- (tb == NULL) &&
- (tcp_bucket_create(snum) == NULL))
- result = 1;
+ if(result == 0) {
+ if(tb == NULL) {
+ if(tcp_bucket_create(snum) == NULL)
+ result = 1;
+ } 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 && !(tb->flags & TCPB_FLAG_LOCKED)) {
+ tb->flags = TCPB_FLAG_LOCKED;
+ tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
+ }
+ }
+ }
go_like_smoke:
SOCKHASH_UNLOCK();
return result;
@@ -731,7 +742,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
isn = tcp_v6_init_sequence(sk,skb);
/*
- * There are no SYN attacks on IPv6, yet...
+ * There are no SYN attacks on IPv6, yet...
*/
if (BACKLOG(sk) >= BACKLOGMAX(sk)) {
printk(KERN_DEBUG "droping syn ack:%d max:%d\n",
diff --git a/net/netsyms.c b/net/netsyms.c
index 5d380fbb6..52be53033 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -458,7 +458,7 @@ EXPORT_SYMBOL(qdisc_put_rtab);
EXPORT_SYMBOL(qdisc_new_estimator);
EXPORT_SYMBOL(qdisc_kill_estimator);
#endif
-#ifdef CONFIG_NET_POLICE
+#ifdef CONFIG_NET_CLS_POLICE
EXPORT_SYMBOL(tcf_police);
EXPORT_SYMBOL(tcf_police_locate);
EXPORT_SYMBOL(tcf_police_destroy);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 858ea0e73..f56b660c0 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -691,7 +691,7 @@ static int packet_create(struct socket *sock, int protocol)
struct sock *sk;
int err;
- if (!suser())
+ if (!capable(CAP_NET_RAW))
return -EPERM;
if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW
#ifdef CONFIG_SOCK_PACKET
@@ -1089,7 +1089,8 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
err = get_user(pid, (int *) arg);
if (err)
return err;
- if (current->pid != pid && current->pgrp != -pid && !suser())
+ if (current->pid != pid && current->pgrp != -pid &&
+ !capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
return(0);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 286a2aa68..494b9fa62 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1193,7 +1193,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCADDRT:
case SIOCDELRT:
case SIOCRSCLRRT:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
return rose_rt_ioctl(cmd, (void *)arg);
case SIOCRSGCAUSE: {
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 30e2c2034..b00d0ab2a 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -371,7 +371,7 @@ int wanrouter_ioctl(struct inode* inode, struct file* file,
struct proc_dir_entry* dent;
wan_device_t* wandev;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if ((cmd >> 8) != ROUTER_IOCTL)
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 163960409..514f64e1b 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -1096,7 +1096,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCADDRT:
case SIOCDELRT:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
return x25_route_ioctl(cmd, (void *)arg);
case SIOCX25GSUBSCRIP: