diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
commit | b9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch) | |
tree | 42d07b0c7246ae2536a702e7c5de9e2732341116 /net/ipv4 | |
parent | 7406b0a326f2d70ade2671c37d1beef62249db97 (diff) |
Merge with 2.3.99-pre6.
Diffstat (limited to 'net/ipv4')
28 files changed, 396 insertions, 309 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index d3fc0e38f..40aa7cd3a 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.109 2000/03/25 01:55:10 davem Exp $ + * Version: $Id: af_inet.c,v 1.110 2000/04/25 04:13:34 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -893,45 +893,43 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } struct proto_ops inet_stream_ops = { - PF_INET, - - inet_release, - inet_bind, - inet_stream_connect, - sock_no_socketpair, - inet_accept, - inet_getname, - tcp_poll, - inet_ioctl, - inet_listen, - inet_shutdown, - inet_setsockopt, - inet_getsockopt, - sock_no_fcntl, - inet_sendmsg, - inet_recvmsg, - sock_no_mmap + family: PF_INET, + + release: inet_release, + bind: inet_bind, + connect: inet_stream_connect, + socketpair: sock_no_socketpair, + accept: inet_accept, + getname: inet_getname, + poll: tcp_poll, + ioctl: inet_ioctl, + listen: inet_listen, + shutdown: inet_shutdown, + setsockopt: inet_setsockopt, + getsockopt: inet_getsockopt, + sendmsg: inet_sendmsg, + recvmsg: inet_recvmsg, + mmap: sock_no_mmap }; struct proto_ops inet_dgram_ops = { - PF_INET, - - inet_release, - inet_bind, - inet_dgram_connect, - sock_no_socketpair, - sock_no_accept, - inet_getname, - datagram_poll, - inet_ioctl, - sock_no_listen, - inet_shutdown, - inet_setsockopt, - inet_getsockopt, - sock_no_fcntl, - inet_sendmsg, - inet_recvmsg, - sock_no_mmap + family: PF_INET, + + release: inet_release, + bind: inet_bind, + connect: inet_dgram_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: inet_getname, + poll: datagram_poll, + ioctl: inet_ioctl, + listen: sock_no_listen, + shutdown: inet_shutdown, + setsockopt: inet_setsockopt, + getsockopt: inet_getsockopt, + sendmsg: inet_sendmsg, + recvmsg: inet_recvmsg, + mmap: sock_no_mmap, }; struct net_proto_family inet_family_ops = { diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 588cdf030..9def6b16b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1,6 +1,6 @@ /* linux/net/inet/arp.c * - * Version: $Id: arp.c,v 1.84 2000/01/18 08:24:14 davem Exp $ + * Version: $Id: arp.c,v 1.86 2000/04/26 09:36:36 davem Exp $ * * Copyright (C) 1994 by Florian La Roche * @@ -1021,7 +1021,6 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) char hbuffer[HBUFFERLEN]; int i,j,k; const char hexbuf[] = "0123456789ABCDEF"; - char abuf[16]; size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n"); @@ -1060,15 +1059,21 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) } #endif - size = sprintf(buffer+len, - "%-17s0x%-10x0x%-10x%s", - in_ntoa2(*(u32*)n->primary_key, abuf), - hatype, - arp_state_to_flags(n), - hbuffer); - size += sprintf(buffer+len+size, - " %-17s %s\n", - "*", dev->name); + { + char tbuf[16]; + sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key)); + + size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s", + tbuf, + hatype, + arp_state_to_flags(n), + hbuffer); + + size += sprintf(buffer+len+size, + " %-8s %s\n", + "*", dev->name); + } + read_unlock(&n->lock); len += size; @@ -1091,8 +1096,8 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) int hatype = dev ? dev->type : 0; size = sprintf(buffer+len, - "%-17s0x%-10x0x%-10x%s", - in_ntoa2(*(u32*)n->key, abuf), + "%u.%u.%u.%u0x%-10x0x%-10x%s", + NIPQUAD(*(u32*)n->key), hatype, ATF_PUBL|ATF_PERM, "00:00:00:00:00:00"); diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 5ee1bfd78..03095f1a2 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -5,7 +5,7 @@ * * IPv4 Forwarding Information Base: policy rules. * - * Version: $Id: fib_rules.c,v 1.14 1999/08/31 07:03:29 davem Exp $ + * Version: $Id: fib_rules.c,v 1.15 2000/04/15 01:48:10 davem Exp $ * * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * @@ -298,7 +298,8 @@ int fib_lookup(const struct rt_key *key, struct fib_result *res) u32 daddr = key->dst; u32 saddr = key->src; -FRprintk("Lookup: %08x <- %08x ", key->dst, key->src); +FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", + NIPQUAD(key->dst), NIPQUAD(key->src)); read_lock(&fib_rules_lock); for (r = fib_rules; r; r=r->r_next) { if (((saddr^r->r_src) & r->r_srcmask) || diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 7c462ac08..f15d94388 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -3,7 +3,7 @@ * * Alan Cox, <alan@redhat.com> * - * Version: $Id: icmp.c,v 1.67 2000/03/25 01:55:11 davem Exp $ + * Version: $Id: icmp.c,v 1.69 2000/04/15 01:48:10 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -521,9 +521,12 @@ void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) } if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0)) goto out; - ip_build_xmit(sk, icmp_glue_bits, icmp_param, - icmp_param->data_len+sizeof(struct icmphdr), - &ipc, rt, MSG_DONTWAIT); + if (icmpv4_xrlim_allow(rt, icmp_param->icmph.type, + icmp_param->icmph.code)) { + ip_build_xmit(sk, icmp_glue_bits, icmp_param, + icmp_param->data_len+sizeof(struct icmphdr), + &ipc, rt, MSG_DONTWAIT); + } ip_rt_put(rt); out: icmp_xmit_unlock_bh(); @@ -720,7 +723,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len) case ICMP_FRAG_NEEDED: if (ipv4_config.no_pmtu_disc) { if (net_ratelimit()) - printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n", + printk(KERN_INFO "ICMP: %u.%u.%u.%u: fragmentation needed and DF set.\n", NIPQUAD(iph->daddr)); } else { unsigned short new_mtu; @@ -732,7 +735,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len) break; case ICMP_SR_FAILED: if (net_ratelimit()) - printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr)); + printk(KERN_INFO "ICMP: %u.%u.%u.%u: Source Route Failed.\n", NIPQUAD(iph->daddr)); break; default: break; @@ -762,7 +765,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len) if (inet_addr_type(iph->daddr) == RTN_BROADCAST) { if (net_ratelimit()) - printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n", + printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP error to a broadcast.\n", NIPQUAD(skb->nh.iph->saddr)); return; } @@ -983,9 +986,8 @@ static void icmp_address_reply(struct icmphdr *icmph, struct sk_buff *skb, int l break; } if (!ifa && net_ratelimit()) { - char b1[16], b2[16]; - printk(KERN_INFO "Wrong address mask %s from %s/%s\n", - in_ntoa2(mask, b1), in_ntoa2(rt->rt_src, b2), dev->name); + printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from %s/%u.%u.%u.%u\n", + NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src)); } } read_unlock(&in_dev->lock); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 852a4fb2c..70f8cfb90 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -5,7 +5,7 @@ * * The IP fragmentation functionality. * - * Version: $Id: ip_fragment.c,v 1.47 2000/02/09 21:11:33 davem Exp $ + * Version: $Id: ip_fragment.c,v 1.49 2000/04/15 01:48:10 davem Exp $ * * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG> * Alan Cox <Alan.Cox@linux.org> @@ -387,9 +387,14 @@ static struct sk_buff *ip_glue(struct ipq *qp) */ skb->security = qp->fragments->skb->security; +#ifdef CONFIG_NETFILTER + /* Connection association is same as fragment (if any). */ + skb->nfct = qp->fragments->skb->nfct; + nf_conntrack_get(skb->nfct); #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = qp->fragments->skb->nf_debug; #endif +#endif /* Done with all fragments. Fixup the new IP header. */ iph = skb->nh.iph; @@ -594,7 +599,7 @@ out: */ out_oversize: if (net_ratelimit()) - printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n", + printk(KERN_INFO "Oversized packet received from %u.%u.%u.%u\n", NIPQUAD(iph->saddr)); /* the skb isn't in a fragment, so fall through to free it */ out_freeskb: diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 0c755dbcd..700bb24f7 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) module. * - * Version: $Id: ip_input.c,v 1.46 2000/02/22 23:54:26 davem Exp $ + * Version: $Id: ip_input.c,v 1.48 2000/04/15 01:48:10 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -162,7 +162,13 @@ int ip_call_ra_chain(struct sk_buff *skb) read_lock(&ip_ra_lock); for (ra = ip_ra_chain; ra; ra = ra->next) { struct sock *sk = ra->sk; - if (sk && sk->num == protocol) { + + /* If socket is bound to an interface, only report + * the packet if it came from that interface. + */ + if (sk && sk->num == protocol + && ((sk->bound_dev_if == 0) + || (sk->bound_dev_if == skb->dev->ifindex))) { if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { skb = ip_defrag(skb); if (skb == NULL) { @@ -349,7 +355,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb) if (in_dev) { if (!IN_DEV_SOURCE_ROUTE(in_dev)) { if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) - printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n", + printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n", NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); in_dev_put(in_dev); goto drop; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 454e81fea..cd51bcef3 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1,5 +1,5 @@ /* - * $Id: ipconfig.c,v 1.27 2000/02/21 15:51:41 davem Exp $ + * $Id: ipconfig.c,v 1.30 2000/04/15 01:48:10 davem Exp $ * * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied * information to configure own IP address and routes. @@ -77,7 +77,7 @@ u8 root_server_path[256] __initdata = { 0, }; /* Path to mount as root */ #define CONFIG_IP_PNP_DYNAMIC -static int ic_proto_enabled __initdata = 0 /* Protocols enabled */ +int ic_proto_enabled __initdata = 0 /* Protocols enabled */ #ifdef CONFIG_IP_PNP_BOOTP | IC_BOOTP #endif @@ -227,17 +227,20 @@ static int __init ic_setup_if(void) strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name); set_sockaddr(sin, ic_myaddr, 0); if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err); + printk(KERN_ERR "IP-Config: Unable to set interface address (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } set_sockaddr(sin, ic_netmask, 0); if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err); + printk(KERN_ERR "IP-Config: Unable to set interface netmask (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err); + printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } return 0; @@ -261,7 +264,8 @@ static int __init ic_setup_routes(void) set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0); rm.rt_flags = RTF_UP | RTF_GATEWAY; if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) { - printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err); + printk(KERN_ERR "IP-Config: Cannot add default route (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } } @@ -294,10 +298,11 @@ static int __init ic_defaults(void) else if (IN_CLASSC(ntohl(ic_myaddr))) ic_netmask = htonl(IN_CLASSC_NET); else { - printk(KERN_ERR "IP-Config: Unable to guess netmask for address %08x\n", ic_myaddr); + printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n", + NIPQUAD(ic_myaddr)); return -1; } - printk("IP-Config: Guessing netmask %s\n", in_ntoa(ic_netmask)); + printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask)); } return 0; @@ -807,10 +812,10 @@ static int __init ic_dynamic(void) if (!ic_got_reply) return -1; - printk("IP-Config: Got %s answer from %s, ", + printk("IP-Config: Got %s answer from %u.%u.%u.%u, ", (ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP", - in_ntoa(ic_servaddr)); - printk("my address is %s\n", in_ntoa(ic_myaddr)); + NIPQUAD(ic_servaddr)); + printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr)); return 0; } @@ -986,7 +991,7 @@ static int __init ip_auto_config_setup(char *addrs) num++; } - return 0; + return 1; } static int __init nfsaddrs_config_setup(char *addrs) diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 197c2e3b4..fdfd747e2 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -343,6 +343,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, size_t hash, repl_hash; struct ip_conntrack_expect *expected; enum ip_conntrack_info ctinfo; + unsigned long extra_jiffies; int i; if (!invert_tuple(&repl_tuple, tuple, protocol)) { @@ -366,19 +367,24 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, repl_hash = hash_conntrack(&repl_tuple); memset(conntrack, 0, sizeof(struct ip_conntrack)); - atomic_set(&conntrack->ct_general.use, 1); + atomic_set(&conntrack->ct_general.use, 2); conntrack->ct_general.destroy = destroy_conntrack; conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple; conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack; conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple; conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack; - for(i=0; i < IP_CT_NUMBER; i++) + for (i=0; i < IP_CT_NUMBER; i++) conntrack->infos[i].master = &conntrack->ct_general; - if (!protocol->new(conntrack, skb->nh.iph, skb->len)) { + extra_jiffies = protocol->new(conntrack, skb->nh.iph, skb->len); + if (!extra_jiffies) { kmem_cache_free(ip_conntrack_cachep, conntrack); return 1; } + conntrack->timeout.data = (unsigned long)conntrack; + conntrack->timeout.function = death_by_timeout; + conntrack->timeout.expires = jiffies + extra_jiffies; + add_timer(&conntrack->timeout); /* Sew in at head of hash list. */ WRITE_LOCK(&ip_conntrack_lock); @@ -421,7 +427,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, } static void -resolve_normal_ct(struct sk_buff *skb) +resolve_normal_ct(struct sk_buff *skb, int create) { struct ip_conntrack_tuple tuple; struct ip_conntrack_tuple_hash *h; @@ -436,7 +442,7 @@ resolve_normal_ct(struct sk_buff *skb) do { /* look for tuple match */ h = ip_conntrack_find_get(&tuple, NULL); - if (!h && init_conntrack(&tuple, proto, skb)) + if (!h && (!create || init_conntrack(&tuple, proto, skb))) return; } while (!h); @@ -464,13 +470,15 @@ resolve_normal_ct(struct sk_buff *skb) } /* Return conntrack and conntrack_info a given skb */ -struct ip_conntrack * -ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo) +static struct ip_conntrack * +__ip_conntrack_get(struct sk_buff *skb, + enum ip_conntrack_info *ctinfo, + int create) { if (!skb->nfct) { /* It may be an icmp error... */ if (!icmp_error_track(skb)) - resolve_normal_ct(skb); + resolve_normal_ct(skb, create); } if (skb->nfct) { @@ -485,6 +493,12 @@ ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo) return NULL; } +struct ip_conntrack * +ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo) +{ + return __ip_conntrack_get(skb, ctinfo, 0); +} + /* Netfilter hook itself. */ unsigned int ip_conntrack_in(unsigned int hooknum, struct sk_buff **pskb, @@ -512,13 +526,13 @@ unsigned int ip_conntrack_in(unsigned int hooknum, return NF_STOLEN; } - ct = ip_conntrack_get(*pskb, &ctinfo); - if (!ct) + ct = __ip_conntrack_get(*pskb, &ctinfo, 1); + if (!ct) { /* Not valid part of a connection */ return NF_ACCEPT; + } proto = find_proto((*pskb)->nh.iph->protocol); - /* If this is new, this is first time timer will be set */ ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo); if (ret == -1) { @@ -645,24 +659,16 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) MOD_DEC_USE_COUNT; } -/* Refresh conntrack for this many jiffies: if noone calls this, - conntrack will vanish with current skb. */ +/* Refresh conntrack for this many jiffies. */ void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies) { + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + WRITE_LOCK(&ip_conntrack_lock); - /* If this hasn't had a timer before, it's still being set up */ - if (ct->timeout.data == 0) { - ct->timeout.data = (unsigned long)ct; - ct->timeout.function = death_by_timeout; + /* Need del_timer for race avoidance (may already be dying). */ + if (del_timer(&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies; - atomic_inc(&ct->ct_general.use); add_timer(&ct->timeout); - } else { - /* Need del_timer for race avoidance (may already be dying). */ - if (del_timer(&ct->timeout)) { - ct->timeout.expires = jiffies + extra_jiffies; - add_timer(&ct->timeout); - } } WRITE_UNLOCK(&ip_conntrack_lock); } diff --git a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c index 77a491e34..6e2bcbcec 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c @@ -48,9 +48,10 @@ static int established(struct ip_conntrack *conntrack, } /* Called when a new connection for this protocol found. */ -static int new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len) +static unsigned long +new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len) { - return 1; + return GENERIC_TIMEOUT; } struct ip_conntrack_protocol ip_conntrack_generic_protocol diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index cbbc1ab8c..17e126119 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c @@ -86,8 +86,8 @@ static int icmp_packet(struct ip_conntrack *ct, } /* Called when a new connection for this protocol found. */ -static int icmp_new(struct ip_conntrack *conntrack, - struct iphdr *iph, size_t len) +static unsigned long icmp_new(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len) { static u_int8_t valid_new[] = { [ICMP_ECHO] = 1, @@ -103,7 +103,7 @@ static int icmp_new(struct ip_conntrack *conntrack, DUMP_TUPLE(&conntrack->tuplehash[0].tuple); return 0; } - return 1; + return ICMP_TIMEOUT; } struct ip_conntrack_protocol ip_conntrack_protocol_icmp diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 893248943..997a917bc 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -189,14 +189,13 @@ static int tcp_packet(struct ip_conntrack *conntrack, conntrack->proto.tcp_state = newconntrack; WRITE_UNLOCK(&tcp_lock); - /* Refresh: need write lock to write to conntrack. */ ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]); return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ -static int tcp_new(struct ip_conntrack *conntrack, - struct iphdr *iph, size_t len) +static unsigned long tcp_new(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len) { enum tcp_conntrack newconntrack; struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl); @@ -210,11 +209,10 @@ static int tcp_new(struct ip_conntrack *conntrack, if (newconntrack == TCP_CONNTRACK_MAX) { DEBUGP("ip_conntrack_tcp: invalid new deleting.\n"); return 0; - } else { - conntrack->proto.tcp_state = newconntrack; - ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]); } - return 1; + + conntrack->proto.tcp_state = newconntrack; + return tcp_timeouts[conntrack->proto.tcp_state]; } struct ip_conntrack_protocol ip_conntrack_protocol_tcp diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c index 79ec82151..521bd7654 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c @@ -54,10 +54,10 @@ static int udp_packet(struct ip_conntrack *conntrack, } /* Called when a new connection for this protocol found. */ -static int udp_new(struct ip_conntrack *conntrack, - struct iphdr *iph, size_t len) +static unsigned long udp_new(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len) { - return 1; + return UDP_TIMEOUT; } struct ip_conntrack_protocol ip_conntrack_protocol_udp diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 9030d9d41..3219f4c85 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -169,8 +169,6 @@ static unsigned int ip_refrag(unsigned int hooknum, interface. We degfragment them at LOCAL_OUT, however, so we have to refragment them here. */ if ((*pskb)->len > rt->u.dst.pmtu) { - DEBUGP("ip_conntrack: refragm %p (size %u) to %u (okfn %p)\n", - *pskb, (*pskb)->len, rt->u.dst.pmtu, okfn); /* No hook can be after us, so this should be OK. */ ip_fragment(*pskb, okfn); return NF_STOLEN; @@ -178,13 +176,29 @@ static unsigned int ip_refrag(unsigned int hooknum, return NF_ACCEPT; } +static unsigned int ip_conntrack_local(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { + if (net_ratelimit()) + printk("ipt_hook: happy cracking.\n"); + return NF_ACCEPT; + } + return ip_conntrack_in(hooknum, pskb, in, out, okfn); +} + /* Connection tracking may drop packets, but never alters them, so make it the first hook. */ static struct nf_hook_ops ip_conntrack_in_ops = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_CONNTRACK }; static struct nf_hook_ops ip_conntrack_local_out_ops -= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_LOCAL_OUT, += { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_CONNTRACK }; /* Refragmenter; last chance. */ static struct nf_hook_ops ip_conntrack_out_ops diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index bfcc435c2..0c582b867 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -130,6 +130,11 @@ ip_nat_out(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) + return NF_ACCEPT; + /* We can hit fragment here; forwarded packets get defragmented by connection tracking coming in, then fragmented (grr) by the forward code. @@ -150,6 +155,21 @@ ip_nat_out(unsigned int hooknum, return ip_nat_fn(hooknum, pskb, in, out, okfn); } +static unsigned int +ip_nat_local_fn(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) + return NF_ACCEPT; + + return ip_nat_fn(hooknum, pskb, in, out, okfn); +} + /* We must be after connection tracking and before packet filtering. */ /* Before packet filtering, change destination */ @@ -160,7 +180,7 @@ static struct nf_hook_ops ip_nat_out_ops = { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC}; /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_local_out_ops -= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST }; += { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST }; /* Protocol registration. */ int ip_nat_protocol_register(struct ip_nat_protocol *proto) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 80e43d977..72b47568b 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -509,7 +509,7 @@ static int ipq_get_info(char *buffer, char **start, off_t offset, int length) "Peer pid : %d\n" "Peer died : %d\n" "Peer copy mode : %d\n" - "Peer copy range : %d\n" + "Peer copy range : %Zu\n" "Queue length : %d\n" "Queue max. length : %d\n" "Queue flushing : %d\n" diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 66f47c386..73424cef8 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -39,7 +39,7 @@ #define IP_NF_ASSERT(x) \ do { \ if (!(x)) \ - printk("IPT_ASSERT: %s:%s:%u\n", \ + printk("IP_NF_ASSERT: %s:%s:%u\n", \ __FUNCTION__, __FILE__, __LINE__); \ } while(0) #else @@ -683,7 +683,6 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, target = find_target_lock(t->u.name, &ret, &ipt_mutex); if (!target) { duprintf("check_entry: `%s' not found\n", t->u.name); - up(&ipt_mutex); return ret; } if (target->me) @@ -1283,17 +1282,16 @@ ipt_register_target(struct ipt_target *target) { int ret; + MOD_INC_USE_COUNT; ret = down_interruptible(&ipt_mutex); if (ret != 0) return ret; - if (list_named_insert(&ipt_target, target)) { - MOD_INC_USE_COUNT; - ret = 0; - } else { + if (!list_named_insert(&ipt_target, target)) { duprintf("ipt_register_target: `%s' already in list!\n", target->name); ret = -EINVAL; + MOD_DEC_USE_COUNT; } up(&ipt_mutex); return ret; @@ -1313,16 +1311,18 @@ ipt_register_match(struct ipt_match *match) { int ret; + MOD_INC_USE_COUNT; ret = down_interruptible(&ipt_mutex); - if (ret != 0) + if (ret != 0) { + MOD_DEC_USE_COUNT; return ret; - + } if (list_named_insert(&ipt_match, match)) { - MOD_INC_USE_COUNT; ret = 0; } else { duprintf("ipt_register_match: `%s' already in list!\n", match->name); + MOD_DEC_USE_COUNT; ret = -EINVAL; } up(&ipt_mutex); @@ -1346,10 +1346,12 @@ int ipt_register_table(struct ipt_table *table) static struct ipt_table_info bootstrap = { 0, 0, { 0 }, { 0 }, { }, { } }; + MOD_INC_USE_COUNT; newinfo = vmalloc(sizeof(struct ipt_table_info) + SMP_ALIGN(table->table->size) * smp_num_cpus); if (!newinfo) { ret = -ENOMEM; + MOD_DEC_USE_COUNT; return ret; } memcpy(newinfo->entries, table->table->entries, table->table->size); @@ -1361,12 +1363,14 @@ int ipt_register_table(struct ipt_table *table) table->table->underflow); if (ret != 0) { vfree(newinfo); + MOD_DEC_USE_COUNT; return ret; } ret = down_interruptible(&ipt_mutex); if (ret != 0) { vfree(newinfo); + MOD_DEC_USE_COUNT; return ret; } @@ -1386,7 +1390,6 @@ int ipt_register_table(struct ipt_table *table) table->lock = RW_LOCK_UNLOCKED; list_prepend(&ipt_tables, table); - MOD_INC_USE_COUNT; unlock: up(&ipt_mutex); @@ -1394,6 +1397,7 @@ int ipt_register_table(struct ipt_table *table) free_unlock: vfree(newinfo); + MOD_DEC_USE_COUNT; goto unlock; } diff --git a/net/ipv4/netfilter/ipchains_core.c b/net/ipv4/netfilter/ipchains_core.c index 419b0382c..e22898512 100644 --- a/net/ipv4/netfilter/ipchains_core.c +++ b/net/ipv4/netfilter/ipchains_core.c @@ -419,18 +419,10 @@ static void dump_packet(const struct iphdr *ip, printk("%d ",f->ipfw.fw_redirpt); } - printk("%s PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu" + printk("%s PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu" " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", - ifname, ip->protocol, - (ntohl(ip->saddr)>>24)&0xFF, - (ntohl(ip->saddr)>>16)&0xFF, - (ntohl(ip->saddr)>>8)&0xFF, - (ntohl(ip->saddr))&0xFF, - src_port, - (ntohl(ip->daddr)>>24)&0xFF, - (ntohl(ip->daddr)>>16)&0xFF, - (ntohl(ip->daddr)>>8)&0xFF, - (ntohl(ip->daddr))&0xFF, + ifname, ip->protocol, NIPQUAD(ip->saddr), + src_port, NIPQUAD(ip->daddr), dst_port, ntohs(ip->tot_len), ip->tos, ntohs(ip->id), ntohs(ip->frag_off), ip->ttl); diff --git a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c index a1f4e16cf..904e7c824 100644 --- a/net/ipv4/netfilter/ipfwadm_core.c +++ b/net/ipv4/netfilter/ipfwadm_core.c @@ -17,7 +17,7 @@ * license in recognition of the original copyright. * -- Alan Cox. * - * $Id: ipfwadm_core.c,v 1.1 2000/03/17 14:42:00 davem Exp $ + * $Id: ipfwadm_core.c,v 1.2 2000/04/15 01:48:10 davem Exp $ * * Ported from BSD to Linux, * Alan Cox 22/Nov/1994. @@ -143,10 +143,7 @@ #define dprintf4(a1,a2,a3,a4) #endif -#define print_ip(a) printk("%d.%d.%d.%d",(ntohl(a)>>24)&0xFF,\ - (ntohl(a)>>16)&0xFF,\ - (ntohl(a)>>8)&0xFF,\ - (ntohl(a))&0xFF); +#define print_ip(a) printk("%u.%u.%u.%u", NIPQUAD(a)); #ifdef DEBUG_IP_FIREWALL #define dprint_ip(a) print_ip(a) diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 4675a94b8..395b1b301 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -38,14 +38,7 @@ static void dump_packet(const struct ipt_log_info *info, * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */ /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */ printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ", - (ntohl(iph->saddr)>>24)&0xFF, - (ntohl(iph->saddr)>>16)&0xFF, - (ntohl(iph->saddr)>>8)&0xFF, - (ntohl(iph->saddr))&0xFF, - (ntohl(iph->daddr)>>24)&0xFF, - (ntohl(iph->daddr)>>16)&0xFF, - (ntohl(iph->daddr)>>8)&0xFF, - (ntohl(iph->daddr))&0xFF); + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", @@ -210,11 +203,7 @@ static void dump_packet(const struct ipt_log_info *info, break; case ICMP_REDIRECT: /* Max length: 24 "GATEWAY=255.255.255.255 " */ - printk("GATEWAY=%u.%u.%u.%u ", - (ntohl(icmph->un.gateway)>>24)&0xFF, - (ntohl(icmph->un.gateway)>>16)&0xFF, - (ntohl(icmph->un.gateway)>>8)&0xFF, - (ntohl(icmph->un.gateway))&0xFF); + printk("GATEWAY=%u.%u.%u.%u ", NIPQUAD(icmph->un.gateway)); /* Fall through */ case ICMP_DEST_UNREACH: case ICMP_SOURCE_QUENCH: diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index d6a7c57f5..4d94a4cc0 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.41 2000/01/21 23:45:57 davem Exp $ + * Version: $Id: proc.c,v 1.42 2000/04/16 01:11:37 davem Exp $ * * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de> @@ -56,7 +56,7 @@ static int fold_prot_inuse(struct proto *proto) int cpu; for (cpu=0; cpu<smp_num_cpus; cpu++) - res += proto->stats[cpu].inuse; + res += proto->stats[cpu_logical_map(cpu)].inuse; return res; } @@ -99,8 +99,10 @@ static unsigned long fold_field(unsigned long *begin, int sz, int nr) sz /= sizeof(unsigned long); - for (i=0; i<2*smp_num_cpus; i++) - res += begin[i*sz + nr]; + for (i=0; i<smp_num_cpus; i++) { + res += begin[2*cpu_logical_map(i)*sz + nr]; + res += begin[(2*cpu_logical_map(i)+1)*sz + nr]; + } return res; } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e9aa1952a..a7555b6b5 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.48 2000/01/18 08:24:15 davem Exp $ + * Version: $Id: raw.c,v 1.49 2000/04/25 04:13:34 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -644,26 +644,20 @@ out: } struct proto raw_prot = { - raw_close, /* close */ - udp_connect, /* connect */ - udp_disconnect, /* disconnect */ - NULL, /* accept */ + name: "RAW", + close: raw_close, + connect: udp_connect, + disconnect: udp_disconnect, #ifdef CONFIG_IP_MROUTE - ipmr_ioctl, /* ioctl */ -#else - NULL, /* ioctl */ + ioctl: ipmr_ioctl, #endif - raw_init, /* init */ - NULL, /* destroy */ - NULL, /* shutdown */ - raw_setsockopt, /* setsockopt */ - raw_getsockopt, /* getsockopt */ - raw_sendmsg, /* sendmsg */ - raw_recvmsg, /* recvmsg */ - raw_bind, /* bind */ - raw_rcv_skb, /* backlog_rcv */ - raw_v4_hash, /* hash */ - raw_v4_unhash, /* unhash */ - NULL, /* get_port */ - "RAW", /* name */ + init: raw_init, + setsockopt: raw_setsockopt, + getsockopt: raw_getsockopt, + sendmsg: raw_sendmsg, + recvmsg: raw_recvmsg, + bind: raw_bind, + backlog_rcv: raw_rcv_skb, + hash: raw_v4_hash, + unhash: raw_v4_unhash, }; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index afab828fb..ec254e313 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -5,7 +5,7 @@ * * ROUTE - implementation of the IP router. * - * Version: $Id: route.c,v 1.83 2000/03/23 05:34:13 davem Exp $ + * Version: $Id: route.c,v 1.86 2000/04/24 07:03:14 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -616,9 +616,9 @@ restart: #if RT_CACHE_DEBUG >= 2 if (rt->u.rt_next) { struct rtable * trt; - printk("rt_cache @%02x: %08x", hash, rt->rt_dst); + printk("rt_cache @%02x: %u.%u.%u.%u", hash, NIPQUAD(rt->rt_dst)); for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next) - printk(" . %08x", trt->rt_dst); + printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst)); printk("\n"); } #endif @@ -816,10 +816,10 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, reject_redirect: #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) - printk(KERN_INFO "Redirect from %X/%s to %X ignored." - "Path = %X -> %X, tos %02x\n", - ntohl(old_gw), dev->name, ntohl(new_gw), - ntohl(saddr), ntohl(daddr), tos); + printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about %u.%u.%u.%u ignored.\n" + " Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, tos %02x\n", + NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw), + NIPQUAD(saddr), NIPQUAD(daddr), tos); #endif in_dev_put(in_dev); } @@ -836,7 +836,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) { unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos); #if RT_CACHE_DEBUG >= 1 - printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos); + printk(KERN_DEBUG "ip_rt_advice: redirect to %u.%u.%u.%u/%02x dropped\n", + NIPQUAD(rt->rt_dst), rt->key.tos); #endif rt_del(hash, rt); return NULL; @@ -896,8 +897,10 @@ void ip_rt_send_redirect(struct sk_buff *skb) #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit()) - printk(KERN_WARNING "host %08x/if%d ignores redirects for %08x to %08x.\n", - rt->rt_src, rt->rt_iif, rt->rt_dst, rt->rt_gateway); + printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores redirects for " + "%u.%u.%u.%u to %u.%u.%u.%u.\n", + NIPQUAD(rt->rt_src), rt->rt_iif, + NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway)); #endif } out: @@ -1061,8 +1064,9 @@ static void ipv4_link_failure(struct sk_buff *skb) static int ip_rt_bug(struct sk_buff *skb) { - printk(KERN_DEBUG "ip_rt_bug: %08x -> %08x, %s\n", skb->nh.iph->saddr, - skb->nh.iph->daddr, skb->dev ? skb->dev->name : "?"); + printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n", + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr), + skb->dev ? skb->dev->name : "?"); kfree_skb(skb); return 0; } @@ -1499,7 +1503,8 @@ no_route: martian_destination: #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) - printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name); + printk(KERN_WARNING "martian destination %u.%u.%u.%u from %u.%u.%u.%u, dev %s\n", + NIPQUAD(daddr), NIPQUAD(saddr), dev->name); #endif e_inval: err = -EINVAL; @@ -1513,16 +1518,20 @@ martian_source: #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) { /* - * RFC1812 recommenadtion, if source is martian, + * RFC1812 recommendation, if source is martian, * the only hint is MAC header. */ - printk(KERN_WARNING "martian source %08x for %08x, dev %s\n", saddr, daddr, dev->name); + printk(KERN_WARNING "martian source %u.%u.%u.%u from %u.%u.%u.%u, on dev %s\n", + NIPQUAD(daddr), NIPQUAD(saddr), dev->name); if (dev->hard_header_len) { int i; unsigned char *p = skb->mac.raw; - printk(KERN_WARNING "ll header:"); - for (i=0; i<dev->hard_header_len; i++, p++) - printk(" %02x", *p); + printk(KERN_WARNING "ll header: "); + for (i=0; i<dev->hard_header_len; i++, p++) { + printk("%02x", *p); + if(i<(dev->hard_header_len-1)) + printk(":"); + } printk("\n"); } } @@ -2218,15 +2227,20 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset, memcpy(dst, src, length); -#ifdef __SMP__ - if (smp_num_cpus > 1) { +#ifdef CONFIG_SMP + if (smp_num_cpus > 1 || cpu_logical_map(0) != 0) { int i; int cnt = length/4; - for (i=1; i<smp_num_cpus; i++) { + for (i=0; i<smp_num_cpus; i++) { + int cpu = cpu_logical_map(i); int k; - src += (256/4)*sizeof(struct ip_rt_acct); + if (cpu == 0) + continue; + + src = (u32*)(((u8*)ip_rt_acct) + offset + + cpu*256*sizeof(struct ip_rt_acct)); for (k=0; k<cnt; k++) dst[k] += src[k]; @@ -2245,7 +2259,7 @@ void __init ip_rt_init(void) #ifdef CONFIG_NET_CLS_ROUTE for (order=0; - (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*smp_num_cpus; order++) + (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*NR_CPUS; order++) /* NOTHING */; ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order); if (!ip_rt_acct) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 098d91ba1..c4343b707 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.166 2000/03/25 01:55:11 davem Exp $ + * Version: $Id: tcp.c,v 1.169 2000/04/20 14:41:16 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -583,9 +583,13 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) answ = 0; else if (sk->urginline || !tp->urg_data || before(tp->urg_seq,tp->copied_seq) || - !before(tp->urg_seq,tp->rcv_nxt)) + !before(tp->urg_seq,tp->rcv_nxt)) { answ = tp->rcv_nxt - tp->copied_seq; - else + + /* Subtract 1, if FIN is in queue. */ + if (answ && !skb_queue_empty(&sk->receive_queue)) + answ -= ((struct sk_buff*)sk->receive_queue.prev)->h.th->fin; + } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); break; @@ -618,7 +622,7 @@ int tcp_listen_start(struct sock *sk) sk->max_ack_backlog = 0; sk->ack_backlog = 0; - tp->accept_queue = NULL; + tp->accept_queue = tp->accept_queue_tail = NULL; tp->syn_wait_lock = RW_LOCK_UNLOCKED; lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL); @@ -677,7 +681,7 @@ static void tcp_listen_stop (struct sock *sk) write_lock_bh(&tp->syn_wait_lock); tp->listen_opt =NULL; write_unlock_bh(&tp->syn_wait_lock); - tp->accept_queue = NULL; + tp->accept_queue = tp->accept_queue_tail = NULL; if (lopt->qlen) { for (i=0; i<TCP_SYNQ_HSIZE; i++) { @@ -951,10 +955,14 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size) tmp += copy; queue_it = 0; } - skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL); - /* If we didn't get any memory, we need to sleep. */ - if (skb == NULL) { + if (tcp_memory_free(sk)) { + skb = alloc_skb(tmp, GFP_KERNEL); + if (skb == NULL) + goto do_oom; + skb_set_owner_w(skb, sk); + } else { + /* If we didn't get any memory, we need to sleep. */ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); set_bit(SOCK_NOSPACE, &sk->socket->flags); @@ -1029,6 +1037,9 @@ do_shutdown: err = -EPIPE; } goto out; +do_oom: + err = copied ? : -ENOBUFS; + goto out; do_interrupted: if(copied) err = copied; @@ -2027,7 +2038,8 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err) } req = tp->accept_queue; - tp->accept_queue = req->dl_next; + if ((tp->accept_queue = req->dl_next) == NULL) + tp->accept_queue_tail = NULL; newsk = req->sk; tcp_acceptq_removed(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3ba12bc52..f062cb2fb 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.191 2000/03/25 01:55:13 davem Exp $ + * Version: $Id: tcp_input.c,v 1.193 2000/04/20 14:41:16 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1618,6 +1618,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) tp->fin_seq = TCP_SKB_CB(skb)->end_seq; tp->ack.pending = 1; + tp->ack.quick = 0; sk->shutdown |= RCV_SHUTDOWN; @@ -1670,9 +1671,9 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) /* Do not send POLL_HUP for half duplex close. */ if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE) - sock_wake_async(sk->socket, 1, POLL_HUP); + sk_wake_async(sk, 1, POLL_HUP); else - sock_wake_async(sk->socket, 1, POLL_IN); + sk_wake_async(sk, 1, POLL_IN); } } @@ -2207,7 +2208,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) kill_proc(sk->proc, SIGURG, 1); else kill_pg(-sk->proc, SIGURG, 1); - sock_wake_async(sk->socket, 3, POLL_PRI); + sk_wake_async(sk, 3, POLL_PRI); } /* We may be adding urgent data when the last byte read was @@ -2783,7 +2784,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, newtp->fin_seq = req->rcv_isn; newtp->urg_data = 0; newtp->listen_opt = NULL; - newtp->accept_queue = NULL; + newtp->accept_queue = newtp->accept_queue_tail = NULL; /* Deinitialize syn_wait_lock to trap illegal accesses. */ memset(&newtp->syn_wait_lock, 0, sizeof(newtp->syn_wait_lock)); @@ -3162,7 +3163,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, if(!sk->dead) { sk->state_change(sk); - sock_wake_async(sk->socket, 0, POLL_OUT); + sk_wake_async(sk, 0, POLL_OUT); } if (tp->write_pending) { @@ -3444,7 +3445,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, */ if (!sk->dead) { sk->state_change(sk); - sock_wake_async(sk->socket,0,POLL_OUT); + sk_wake_async(sk,0,POLL_OUT); } tp->snd_una = TCP_SKB_CB(skb)->ack_seq; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3c9f4e82b..5facec2c8 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.205 2000/03/26 09:16:08 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.207 2000/04/25 04:13:34 davem Exp $ * * IPv4 specific functions * @@ -1384,7 +1384,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) peer->v4daddr == saddr) { if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL && (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) { - NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %08x/%u\n", peer->tcp_ts, req->ts_recent, saddr, ntohs(skb->h.th->source))); + NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %u.%u.%u.%u/%u\n", \ + peer->tcp_ts, req->ts_recent, NIPQUAD(saddr), ntohs(skb->h.th->source))); NET_INC_STATS_BH(PAWSPassiveRejected); dst_release(dst); goto drop_and_free; @@ -1402,7 +1403,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) * to destinations, already remembered * to the moment of synflood. */ - NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "TCP: drop open request from %08x/%u\n", saddr, ntohs(skb->h.th->source))); + NETDEBUG(if (net_ratelimit()) \ + printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \ + NIPQUAD(saddr), ntohs(skb->h.th->source))); TCP_INC_STATS_BH(TcpAttemptFails); dst_release(dst); goto drop_and_free; @@ -2169,24 +2172,23 @@ out_no_bh: } struct proto tcp_prot = { - tcp_close, /* close */ - tcp_v4_connect, /* connect */ - tcp_disconnect, /* disconnect */ - tcp_accept, /* accept */ - tcp_ioctl, /* ioctl */ - tcp_v4_init_sock, /* init */ - tcp_v4_destroy_sock, /* destroy */ - tcp_shutdown, /* shutdown */ - tcp_setsockopt, /* setsockopt */ - tcp_getsockopt, /* getsockopt */ - tcp_sendmsg, /* sendmsg */ - tcp_recvmsg, /* recvmsg */ - NULL, /* bind */ - tcp_v4_do_rcv, /* backlog_rcv */ - tcp_v4_hash, /* hash */ - tcp_unhash, /* unhash */ - tcp_v4_get_port, /* get_port */ - "TCP", /* name */ + name: "TCP", + close: tcp_close, + connect: tcp_v4_connect, + disconnect: tcp_disconnect, + accept: tcp_accept, + ioctl: tcp_ioctl, + init: tcp_v4_init_sock, + destroy: tcp_v4_destroy_sock, + shutdown: tcp_shutdown, + setsockopt: tcp_setsockopt, + getsockopt: tcp_getsockopt, + sendmsg: tcp_sendmsg, + recvmsg: tcp_recvmsg, + backlog_rcv: tcp_v4_do_rcv, + hash: tcp_v4_hash, + unhash: tcp_unhash, + get_port: tcp_v4_get_port, }; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 600140764..0fdb6b3f8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.123 2000/03/25 01:52:05 davem Exp $ + * Version: $Id: tcp_output.c,v 1.124 2000/04/08 07:21:24 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1121,27 +1121,22 @@ void tcp_send_delayed_ack(struct sock *sk) timeout = jiffies + ato; /* Use new timeout only if there wasn't a older one earlier. */ - spin_lock_bh(&sk->timer_lock); - if (!tp->delack_timer.prev || !del_timer(&tp->delack_timer)) { - sock_hold(sk); - tp->delack_timer.expires = timeout; - } else { + if (timer_pending(&tp->delack_timer)) { + unsigned long old_timeout = tp->delack_timer.expires; + /* If delack timer was blocked or is about to expire, * send ACK now. */ - if (tp->ack.blocked || time_before_eq(tp->delack_timer.expires, jiffies+(ato>>2))) { - spin_unlock_bh(&sk->timer_lock); - + if (tp->ack.blocked || time_before_eq(old_timeout, jiffies+(ato>>2))) { tcp_send_ack(sk); - __sock_put(sk); return; } - if (time_before(timeout, tp->delack_timer.expires)) - tp->delack_timer.expires = timeout; + if (!time_before(timeout, old_timeout)) + timeout = old_timeout; } - add_timer(&tp->delack_timer); - spin_unlock_bh(&sk->timer_lock); + if (!mod_timer(&tp->delack_timer, timeout)) + sock_hold(sk); #ifdef TCP_FORMAL_WINDOW /* Explanation. Header prediction path does not handle diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 6b3695c3e..9e9887707 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.74 2000/02/14 20:56:30 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.75 2000/04/08 07:21:25 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -49,8 +49,6 @@ void tcp_init_xmit_timers(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; - spin_lock_init(&sk->timer_lock); - init_timer(&tp->retransmit_timer); tp->retransmit_timer.function=&tcp_retransmit_timer; tp->retransmit_timer.data = (unsigned long) sk; @@ -76,7 +74,6 @@ void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; - spin_lock_bh(&sk->timer_lock); switch (what) { case TCP_TIME_RETRANS: /* When seting the transmit timer the probe timer @@ -84,50 +81,44 @@ void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when) * The delayed ack timer can be set if we are changing the * retransmit timer when removing acked frames. */ - if(tp->probe_timer.prev && del_timer(&tp->probe_timer)) + if (timer_pending(&tp->probe_timer) && del_timer(&tp->probe_timer)) __sock_put(sk); - if (!tp->retransmit_timer.prev || !del_timer(&tp->retransmit_timer)) - sock_hold(sk); if (when > TCP_RTO_MAX) { printk(KERN_DEBUG "reset_xmit_timer sk=%p when=0x%lx, caller=%p\n", sk, when, NET_CALLER(sk)); when = TCP_RTO_MAX; } - mod_timer(&tp->retransmit_timer, jiffies+when); + if (!mod_timer(&tp->retransmit_timer, jiffies+when)) + sock_hold(sk); break; case TCP_TIME_DACK: - if (!tp->delack_timer.prev || !del_timer(&tp->delack_timer)) + if (!mod_timer(&tp->delack_timer, jiffies+when)) sock_hold(sk); - mod_timer(&tp->delack_timer, jiffies+when); break; case TCP_TIME_PROBE0: - if (!tp->probe_timer.prev || !del_timer(&tp->probe_timer)) + if (!mod_timer(&tp->probe_timer, jiffies+when)) sock_hold(sk); - mod_timer(&tp->probe_timer, jiffies+when); - break; + break; default: printk(KERN_DEBUG "bug: unknown timer value\n"); }; - spin_unlock_bh(&sk->timer_lock); } void tcp_clear_xmit_timers(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; - spin_lock_bh(&sk->timer_lock); - if(tp->retransmit_timer.prev && del_timer(&tp->retransmit_timer)) + if(timer_pending(&tp->retransmit_timer) && del_timer(&tp->retransmit_timer)) __sock_put(sk); - if(tp->delack_timer.prev && del_timer(&tp->delack_timer)) + if(timer_pending(&tp->delack_timer) && del_timer(&tp->delack_timer)) __sock_put(sk); tp->ack.blocked = 0; - if(tp->probe_timer.prev && del_timer(&tp->probe_timer)) + if(timer_pending(&tp->probe_timer) && del_timer(&tp->probe_timer)) __sock_put(sk); - if(sk->timer.prev && del_timer(&sk->timer)) + if(timer_pending(&sk->timer) && del_timer(&sk->timer)) __sock_put(sk); - spin_unlock_bh(&sk->timer_lock); } static void tcp_write_err(struct sock *sk) @@ -138,6 +129,35 @@ static void tcp_write_err(struct sock *sk) tcp_done(sk); } +/* Do not allow orphaned sockets to eat all our resources. + * This is direct violation of TCP specs, but it is required + * to prevent DoS attacks. It is called when a retransmission timeout + * or zero probe timeout occurs on orphaned socket. + * + * Criterium is still not confirmed experimentally and may change. + * We kill the socket, if: + * 1. If number of orphaned sockets exceeds an administratively configured + * limit. + * 2. Under pessimistic assumption that all the orphans eat memory not + * less than this one, total consumed memory exceeds all + * the available memory. + */ +static int tcp_out_of_resources(struct sock *sk, int do_reset) +{ + int orphans = atomic_read(&tcp_orphan_count); + + if (orphans >= sysctl_tcp_max_orphans || + ((orphans*atomic_read(&sk->wmem_alloc))>>PAGE_SHIFT) >= num_physpages) { + if (net_ratelimit()) + printk(KERN_INFO "Out of socket memory\n"); + if (do_reset) + tcp_send_active_reset(sk, GFP_ATOMIC); + tcp_done(sk); + return 1; + } + return 0; +} + /* A write timeout has occurred. Process the after effects. */ static int tcp_write_timeout(struct sock *sk) { @@ -172,9 +192,14 @@ static int tcp_write_timeout(struct sock *sk) dst_negative_advice(&sk->dst_cache); } + retry_until = sysctl_tcp_retries2; - if (sk->dead) + if (sk->dead) { + if (tcp_out_of_resources(sk, tp->retransmits < retry_until)) + return 1; + retry_until = sysctl_tcp_orphan_retries; + } } if (tp->retransmits >= retry_until) { @@ -257,7 +282,14 @@ static void tcp_probe_timer(unsigned long data) * with RFCs, only probe timer combines both retransmission timeout * and probe timeout in one bottle. --ANK */ - max_probes = sk->dead ? sysctl_tcp_orphan_retries : sysctl_tcp_retries2; + max_probes = sysctl_tcp_retries2; + + if (sk->dead) { + if (tcp_out_of_resources(sk, tp->probes_out <= max_probes)) + goto out_unlock; + + max_probes = sysctl_tcp_orphan_retries; + } if (tp->probes_out > max_probes) { tcp_write_err(sk); @@ -574,6 +606,8 @@ static void tcp_retransmit_timer(unsigned long data) tp->retransmits++; tp->rto = min(tp->rto << 1, TCP_RTO_MAX); tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto); + if (tp->retransmits > sysctl_tcp_retries1) + __sk_dst_reset(sk); TCP_CHECK_TIMER(sk); out_unlock: @@ -676,19 +710,14 @@ static void tcp_synack_timer(struct sock *sk) void tcp_delete_keepalive_timer (struct sock *sk) { - spin_lock_bh(&sk->timer_lock); - if (sk->timer.prev && del_timer (&sk->timer)) + if (timer_pending(&sk->timer) && del_timer (&sk->timer)) __sock_put(sk); - spin_unlock_bh(&sk->timer_lock); } void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len) { - spin_lock_bh(&sk->timer_lock); - if(!sk->timer.prev || !del_timer(&sk->timer)) + if (!mod_timer(&sk->timer, jiffies+len)) sock_hold(sk); - mod_timer(&sk->timer, jiffies+len); - spin_unlock_bh(&sk->timer_lock); } void tcp_set_keepalive(struct sock *sk, int val) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e188b4997..570e1de2b 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.80 2000/02/27 19:51:43 davem Exp $ + * Version: $Id: udp.c,v 1.81 2000/04/25 04:13:34 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1041,22 +1041,17 @@ out: } struct proto udp_prot = { - udp_close, /* close */ - udp_connect, /* connect */ - udp_disconnect, /* disconnect */ - NULL, /* accept */ - udp_ioctl, /* ioctl */ - NULL, /* init */ - NULL, /* destroy */ - NULL, /* shutdown */ - ip_setsockopt, /* setsockopt */ - ip_getsockopt, /* getsockopt */ - udp_sendmsg, /* sendmsg */ - udp_recvmsg, /* recvmsg */ - NULL, /* bind */ - udp_queue_rcv_skb, /* backlog_rcv */ - udp_v4_hash, /* hash */ - udp_v4_unhash, /* unhash */ - udp_v4_get_port, /* good_socknum */ - "UDP", /* name */ + name: "UDP", + close: udp_close, + connect: udp_connect, + disconnect: udp_disconnect, + ioctl: udp_ioctl, + setsockopt: ip_setsockopt, + getsockopt: ip_getsockopt, + sendmsg: udp_sendmsg, + recvmsg: udp_recvmsg, + backlog_rcv: udp_queue_rcv_skb, + hash: udp_v4_hash, + unhash: udp_v4_unhash, + get_port: udp_v4_get_port, }; |