diff options
Diffstat (limited to 'net')
49 files changed, 316 insertions, 285 deletions
diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 93ad59a28ef..31d98b57e1d 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -39,25 +39,19 @@ static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep); static void sigd_put_skb(struct sk_buff *skb) { #ifdef WAIT_FOR_DEMON - static unsigned long silence; DECLARE_WAITQUEUE(wait,current); add_wait_queue(&sigd_sleep,&wait); while (!sigd) { set_current_state(TASK_UNINTERRUPTIBLE); - if (time_after(jiffies, silence) || silence == 0) { - printk(KERN_INFO "atmsvc: waiting for signaling demon " - "...\n"); - silence = (jiffies+30*HZ)|1; - } + DPRINTK("atmsvc: waiting for signaling demon...\n"); schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&sigd_sleep,&wait); #else if (!sigd) { - if (net_ratelimit()) - printk(KERN_WARNING "atmsvc: no signaling demon\n"); + DPRINTK("atmsvc: no signaling demon\n"); kfree_skb(skb); return; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 7fa3a5a9971..f36b35edd60 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -81,26 +81,27 @@ static void port_carrier_check(void *arg) { struct net_device *dev = arg; struct net_bridge_port *p; + struct net_bridge *br; rtnl_lock(); p = dev->br_port; if (!p) goto done; - - if (netif_carrier_ok(p->dev)) { - u32 cost = port_cost(p->dev); - - spin_lock_bh(&p->br->lock); - if (p->state == BR_STATE_DISABLED) { - p->path_cost = cost; - br_stp_enable_port(p); + br = p->br; + + if (netif_carrier_ok(dev)) + p->path_cost = port_cost(dev); + + if (br->dev->flags & IFF_UP) { + spin_lock_bh(&br->lock); + if (netif_carrier_ok(dev)) { + if (p->state == BR_STATE_DISABLED) + br_stp_enable_port(p); + } else { + if (p->state != BR_STATE_DISABLED) + br_stp_disable_port(p); } - spin_unlock_bh(&p->br->lock); - } else { - spin_lock_bh(&p->br->lock); - if (p->state != BR_STATE_DISABLED) - br_stp_disable_port(p); - spin_unlock_bh(&p->br->lock); + spin_unlock_bh(&br->lock); } done: rtnl_unlock(); @@ -168,6 +169,7 @@ static void del_nbp(struct net_bridge_port *p) rcu_assign_pointer(dev->br_port, NULL); + kobject_uevent(&p->kobj, KOBJ_REMOVE); kobject_del(&p->kobj); call_rcu(&p->rcu, destroy_nbp_rcu); @@ -276,8 +278,9 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, br_init_port(p); p->state = BR_STATE_DISABLED; INIT_WORK(&p->carrier_check, port_carrier_check, dev); - kobject_init(&p->kobj); + br_stp_port_timer_init(p); + kobject_init(&p->kobj); kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); p->kobj.ktype = &brport_ktype; p->kobj.parent = &(dev->class_dev.kobj); diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 6bb0c7eb1ef..e060aad8624 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -90,6 +90,7 @@ static struct rtable __fake_rtable = { .dev = &__fake_net_device, .path = &__fake_rtable.u.dst, .metrics = {[RTAX_MTU - 1] = 1500}, + .flags = DST_NOXFRM, } }, .rt_flags = 0, diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index cc047f7fb6e..23dea1422c9 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -39,8 +39,6 @@ void br_init_port(struct net_bridge_port *p) p->state = BR_STATE_BLOCKING; p->topology_change_ack = 0; p->config_pending = 0; - - br_stp_port_timer_init(p); } /* called under bridge lock */ @@ -67,7 +65,7 @@ void br_stp_disable_bridge(struct net_bridge *br) { struct net_bridge_port *p; - spin_lock(&br->lock); + spin_lock_bh(&br->lock); list_for_each_entry(p, &br->port_list, list) { if (p->state != BR_STATE_DISABLED) br_stp_disable_port(p); @@ -76,7 +74,7 @@ void br_stp_disable_bridge(struct net_bridge *br) br->topology_change = 0; br->topology_change_detected = 0; - spin_unlock(&br->lock); + spin_unlock_bh(&br->lock); del_timer_sync(&br->hello_timer); del_timer_sync(&br->topology_change_timer); diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile index 8bf6d9f6e9d..905087e0d48 100644 --- a/net/bridge/netfilter/Makefile +++ b/net/bridge/netfilter/Makefile @@ -29,4 +29,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o # watchers obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o -obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_ulog.o +obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 0128fbbe232..288ff1d4ccc 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -166,7 +166,12 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, li.u.log.level = info->loglevel; li.u.log.logflags = info->bitmask; - nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, info->prefix); + if (info->bitmask & EBT_LOG_NFLOG) + nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, + info->prefix); + else + ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, + info->prefix); } static struct ebt_watcher log = diff --git a/net/core/request_sock.c b/net/core/request_sock.c index b8203de5ff0..98f0fc923f9 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -52,7 +52,6 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); rwlock_init(&queue->syn_wait_lock); queue->rskq_accept_head = queue->rskq_accept_head = NULL; - queue->rskq_defer_accept = 0; lopt->nr_table_entries = nr_table_entries; write_lock_bh(&queue->syn_wait_lock); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6766f118f07..2144952d1c6 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -411,6 +411,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) C(pkt_type); C(ip_summed); C(priority); +#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) + C(ipvs_property); +#endif C(protocol); n->destructor = NULL; #ifdef CONFIG_NETFILTER @@ -422,13 +425,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) C(nfct_reasm); nf_conntrack_get_reasm(skb->nfct_reasm); #endif -#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) - C(ipvs_property); -#endif -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - C(nfct_reasm); - nf_conntrack_get_reasm(skb->nfct_reasm); -#endif #ifdef CONFIG_BRIDGE_NETFILTER C(nf_bridge); nf_bridge_get(skb->nf_bridge); diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index aa68e0ab274..35d1d347541 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -2,7 +2,7 @@ * net/dccp/ccids/ccid3.c * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. - * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> + * Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com> * * An implementation of the DCCP protocol * @@ -1033,9 +1033,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) p_prev = hcrx->ccid3hcrx_p; /* Calculate loss event rate */ - if (!list_empty(&hcrx->ccid3hcrx_li_hist)) + if (!list_empty(&hcrx->ccid3hcrx_li_hist)) { + u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); + /* Scaling up by 1000000 as fixed decimal */ - hcrx->ccid3hcrx_p = 1000000 / dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); + if (i_mean != 0) + hcrx->ccid3hcrx_p = 1000000 / i_mean; + } if (hcrx->ccid3hcrx_p > p_prev) { ccid3_hc_rx_send_feedback(sk); diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 9890fd97e53..c971f14712e 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -95,6 +95,12 @@ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, saddr = dev->dev_addr; memcpy(eth->h_source,saddr,dev->addr_len); + if(daddr) + { + memcpy(eth->h_dest,daddr,dev->addr_len); + return ETH_HLEN; + } + /* * Anyway, the loopback-device should never use this function... */ @@ -105,12 +111,6 @@ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, return ETH_HLEN; } - if(daddr) - { - memcpy(eth->h_dest,daddr,dev->addr_len); - return ETH_HLEN; - } - return -ETH_HLEN; } diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 960aa78cdb9..b410ab8bcf7 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -1301,7 +1301,7 @@ static void update_network(struct ieee80211_network *dst, /* dst->last_associate is not overwritten */ } -static inline int is_beacon(int fc) +static inline int is_beacon(__le16 fc) { return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); } @@ -1348,9 +1348,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device escape_essid(info_element->data, info_element->len), MAC_ARG(beacon->header.addr3), - is_beacon(le16_to_cpu - (beacon->header. - frame_ctl)) ? + is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE"); return; } @@ -1400,9 +1398,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device escape_essid(network.ssid, network.ssid_len), MAC_ARG(network.bssid), - is_beacon(le16_to_cpu - (beacon->header. - frame_ctl)) ? + is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE"); #endif memcpy(target, &network, sizeof(*target)); @@ -1412,16 +1408,14 @@ static void ieee80211_process_probe_response(struct ieee80211_device escape_essid(target->ssid, target->ssid_len), MAC_ARG(target->bssid), - is_beacon(le16_to_cpu - (beacon->header. - frame_ctl)) ? + is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE"); update_network(target, &network); } spin_unlock_irqrestore(&ieee->lock, flags); - if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) { + if (is_beacon(beacon->header.frame_ctl)) { if (ieee->handle_beacon != NULL) ieee->handle_beacon(dev, beacon, &network); } else { diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 73bfcae8af9..09590f35608 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -12,13 +12,6 @@ #include <net/protocol.h> #include <net/udp.h> -/* decapsulation data for use when post-processing */ -struct esp_decap_data { - xfrm_address_t saddr; - __u16 sport; - __u8 proto; -}; - static int esp_output(struct xfrm_state *x, struct sk_buff *skb) { int err; @@ -150,6 +143,10 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; int nfrags; int encap_len = 0; + u8 nexthdr[2]; + struct scatterlist *sg; + u8 workbuf[60]; + int padlen; if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) goto out; @@ -185,122 +182,82 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc if (esp->conf.ivlen) crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); - { - u8 nexthdr[2]; - struct scatterlist *sg = &esp->sgbuf[0]; - u8 workbuf[60]; - int padlen; - - if (unlikely(nfrags > ESP_NUM_FAST_SG)) { - sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); - if (!sg) - goto out; - } - skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); - crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); - if (unlikely(sg != &esp->sgbuf[0])) - kfree(sg); - - if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) - BUG(); + sg = &esp->sgbuf[0]; - padlen = nexthdr[0]; - if (padlen+2 >= elen) + if (unlikely(nfrags > ESP_NUM_FAST_SG)) { + sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); + if (!sg) goto out; - - /* ... check padding bits here. Silly. :-) */ - - if (x->encap && decap && decap->decap_type) { - struct esp_decap_data *encap_data; - struct udphdr *uh = (struct udphdr *) (iph+1); - - encap_data = (struct esp_decap_data *) (decap->decap_data); - encap_data->proto = 0; - - switch (decap->decap_type) { - case UDP_ENCAP_ESPINUDP: - case UDP_ENCAP_ESPINUDP_NON_IKE: - encap_data->proto = AF_INET; - encap_data->saddr.a4 = iph->saddr; - encap_data->sport = uh->source; - encap_len = (void*)esph - (void*)uh; - break; - - default: - goto out; - } - } - - iph->protocol = nexthdr[1]; - pskb_trim(skb, skb->len - alen - padlen - 2); - memcpy(workbuf, skb->nh.raw, iph->ihl*4); - skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen); - skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen; - memcpy(skb->nh.raw, workbuf, iph->ihl*4); - skb->nh.iph->tot_len = htons(skb->len); } + skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); + crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); + if (unlikely(sg != &esp->sgbuf[0])) + kfree(sg); - return 0; + if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) + BUG(); -out: - return -EINVAL; -} + padlen = nexthdr[0]; + if (padlen+2 >= elen) + goto out; -static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) -{ - - if (x->encap) { - struct xfrm_encap_tmpl *encap; - struct esp_decap_data *decap_data; + /* ... check padding bits here. Silly. :-) */ - encap = x->encap; - decap_data = (struct esp_decap_data *)(decap->decap_data); + if (x->encap) { + struct xfrm_encap_tmpl *encap = x->encap; + struct udphdr *uh; - /* first, make sure that the decap type == the encap type */ if (encap->encap_type != decap->decap_type) - return -EINVAL; + goto out; - switch (encap->encap_type) { - default: - case UDP_ENCAP_ESPINUDP: - case UDP_ENCAP_ESPINUDP_NON_IKE: - /* - * 1) if the NAT-T peer's IP or port changed then - * advertize the change to the keying daemon. - * This is an inbound SA, so just compare - * SRC ports. - */ - if (decap_data->proto == AF_INET && - (decap_data->saddr.a4 != x->props.saddr.a4 || - decap_data->sport != encap->encap_sport)) { - xfrm_address_t ipaddr; - - ipaddr.a4 = decap_data->saddr.a4; - km_new_mapping(x, &ipaddr, decap_data->sport); - - /* XXX: perhaps add an extra - * policy check here, to see - * if we should allow or - * reject a packet from a - * different source - * address/port. - */ - } - - /* - * 2) ignore UDP/TCP checksums in case - * of NAT-T in Transport Mode, or - * perform other post-processing fixes - * as per * draft-ietf-ipsec-udp-encaps-06, - * section 3.1.2 + uh = (struct udphdr *)(iph + 1); + encap_len = (void*)esph - (void*)uh; + + /* + * 1) if the NAT-T peer's IP or port changed then + * advertize the change to the keying daemon. + * This is an inbound SA, so just compare + * SRC ports. + */ + if (iph->saddr != x->props.saddr.a4 || + uh->source != encap->encap_sport) { + xfrm_address_t ipaddr; + + ipaddr.a4 = iph->saddr; + km_new_mapping(x, &ipaddr, uh->source); + + /* XXX: perhaps add an extra + * policy check here, to see + * if we should allow or + * reject a packet from a + * different source + * address/port. */ - if (!x->props.mode) - skb->ip_summed = CHECKSUM_UNNECESSARY; - - break; } + + /* + * 2) ignore UDP/TCP checksums in case + * of NAT-T in Transport Mode, or + * perform other post-processing fixes + * as per draft-ietf-ipsec-udp-encaps-06, + * section 3.1.2 + */ + if (!x->props.mode) + skb->ip_summed = CHECKSUM_UNNECESSARY; } + + iph->protocol = nexthdr[1]; + pskb_trim(skb, skb->len - alen - padlen - 2); + memcpy(workbuf, skb->nh.raw, iph->ihl*4); + skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen); + skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen; + memcpy(skb->nh.raw, workbuf, iph->ihl*4); + skb->nh.iph->tot_len = htons(skb->len); + return 0; + +out: + return -EINVAL; } static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) @@ -458,7 +415,6 @@ static struct xfrm_type esp_type = .destructor = esp_destroy, .get_max_size = esp4_get_max_size, .input = esp_input, - .post_input = esp_post_input, .output = esp_output }; @@ -470,15 +426,6 @@ static struct net_protocol esp4_protocol = { static int __init esp4_init(void) { - struct xfrm_decap_state decap; - - if (sizeof(struct esp_decap_data) > - sizeof(decap.decap_data)) { - extern void decap_data_too_small(void); - - decap_data_too_small(); - } - if (xfrm_register_type(&esp_type, AF_INET) < 0) { printk(KERN_INFO "ip esp init: can't add xfrm type\n"); return -EAGAIN; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index abe23923e4e..9981dcd68f1 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -830,7 +830,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->h.raw = skb->nh.raw; skb->nh.raw = skb_push(skb, gre_hlen); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); + IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | + IPSKB_REROUTED); dst_release(skb->dst); skb->dst = &rt->u.dst; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3324fbfe528..8ee4d016740 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -207,8 +207,10 @@ static inline int ip_finish_output(struct sk_buff *skb) { #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) /* Policy lookup after SNAT yielded a new policy */ - if (skb->dst->xfrm != NULL) - return xfrm4_output_finish(skb); + if (skb->dst->xfrm != NULL) { + IPCB(skb)->flags |= IPSKB_REROUTED; + return dst_output(skb); + } #endif if (skb->len > dst_mtu(skb->dst) && !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) @@ -271,8 +273,9 @@ int ip_mc_output(struct sk_buff *skb) newskb->dev, ip_dev_loopback_xmit); } - return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, - ip_finish_output); + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, + ip_finish_output, + !(IPCB(skb)->flags & IPSKB_REROUTED)); } int ip_output(struct sk_buff *skb) @@ -284,8 +287,9 @@ int ip_output(struct sk_buff *skb) skb->dev = dev; skb->protocol = htons(ETH_P_IP); - return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, - ip_finish_output); + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, + ip_finish_output, + !(IPCB(skb)->flags & IPSKB_REROUTED)); } int ip_queue_xmit(struct sk_buff *skb, int ipfragok) @@ -843,10 +847,11 @@ int ip_append_data(struct sock *sk, if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && (rt->u.dst.dev->features & NETIF_F_UFO)) { - if(ip_ufo_append_data(sk, getfrag, from, length, hh_len, - fragheaderlen, transhdrlen, mtu, flags)) + err = ip_ufo_append_data(sk, getfrag, from, length, hh_len, + fragheaderlen, transhdrlen, mtu, + flags); + if (err) goto error; - return 0; } diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index e5cbe72c6b8..03d13742a4b 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -622,7 +622,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->h.raw = skb->nh.raw; skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); + IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | + IPSKB_REROUTED); dst_release(skb->dst); skb->dst = &rt->u.dst; diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 52a3d7c5790..ed42cdc57cd 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -78,6 +78,47 @@ int ip_route_me_harder(struct sk_buff **pskb) } EXPORT_SYMBOL(ip_route_me_harder); +#ifdef CONFIG_XFRM +int ip_xfrm_me_harder(struct sk_buff **pskb) +{ + struct flowi fl; + unsigned int hh_len; + struct dst_entry *dst; + + if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) + return 0; + if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0) + return -1; + + dst = (*pskb)->dst; + if (dst->xfrm) + dst = ((struct xfrm_dst *)dst)->route; + dst_hold(dst); + + if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0) + return -1; + + dst_release((*pskb)->dst); + (*pskb)->dst = dst; + + /* Change in oif may mean change in hh_len. */ + hh_len = (*pskb)->dst->dev->hard_header_len; + if (skb_headroom(*pskb) < hh_len) { + struct sk_buff *nskb; + + nskb = skb_realloc_headroom(*pskb, hh_len); + if (!nskb) + return -1; + if ((*pskb)->sk) + skb_set_owner_w(nskb, (*pskb)->sk); + kfree_skb(*pskb); + *pskb = nskb; + } + return 0; +} +EXPORT_SYMBOL(ip_xfrm_me_harder); +#endif + void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); EXPORT_SYMBOL(ip_nat_decode_session); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index dd1048be8a0..7d7ab94a7a2 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -771,7 +771,7 @@ static int get_entries(const struct arpt_get_entries *entries, struct arpt_table *t; t = xt_find_table_lock(NF_ARP, entries->name); - if (t || !IS_ERR(t)) { + if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", private->number); diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c1a61462507..1741d555ad0 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, } *inside; struct ip_conntrack_tuple inner, target; int hdrlen = (*pskb)->nh.iph->ihl * 4; + unsigned long statusbit; if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) return 0; @@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, /* Change outer to look the reply to an incoming packet * (proto 0 means don't invert per-proto part). */ + if (manip == IP_NAT_MANIP_SRC) + statusbit = IPS_SRC_NAT; + else + statusbit = IPS_DST_NAT; - /* Obviously, we need to NAT destination IP, but source IP - should be NAT'ed only if it is from a NAT'd host. + /* Invert if this is reply dir. */ + if (dir == IP_CT_DIR_REPLY) + statusbit ^= IPS_NAT_MASK; - Explanation: some people use NAT for anonymizing. Also, - CERT recommends dropping all packets from private IP - addresses (although ICMP errors from internal links with - such addresses are not too uncommon, as Alan Cox points - out) */ - if (manip != IP_NAT_MANIP_SRC - || ((*pskb)->nh.iph->saddr == ct->tuplehash[dir].tuple.src.ip)) { + if (ct->status & statusbit) { invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); if (!manip_pkt(0, pskb, 0, &target, manip)) return 0; diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 92c54999a19..ab1f88fa21e 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -200,20 +200,14 @@ ip_nat_in(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; unsigned int ret; + u_int32_t daddr = (*pskb)->nh.iph->daddr; ret = ip_nat_fn(hooknum, pskb, in, out, okfn); if (ret != NF_DROP && ret != NF_STOLEN - && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - - if (ct->tuplehash[dir].tuple.dst.ip != - ct->tuplehash[!dir].tuple.src.ip) { - dst_release((*pskb)->dst); - (*pskb)->dst = NULL; - } + && daddr != (*pskb)->nh.iph->daddr) { + dst_release((*pskb)->dst); + (*pskb)->dst = NULL; } return ret; } @@ -235,19 +229,19 @@ ip_nat_out(unsigned int hooknum, return NF_ACCEPT; ret = ip_nat_fn(hooknum, pskb, in, out, okfn); +#ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); if (ct->tuplehash[dir].tuple.src.ip != ct->tuplehash[!dir].tuple.dst.ip -#ifdef CONFIG_XFRM || ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all -#endif ) - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; + return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; } +#endif return ret; } @@ -276,7 +270,7 @@ ip_nat_local_fn(unsigned int hooknum, ct->tuplehash[!dir].tuple.src.ip #ifdef CONFIG_XFRM || ct->tuplehash[dir].tuple.dst.u.all != - ct->tuplehash[dir].tuple.src.u.all + ct->tuplehash[!dir].tuple.src.u.all #endif ) return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 36339eb39e1..08f80e2ea2a 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -524,7 +524,7 @@ ipq_rcv_skb(struct sk_buff *skb) write_unlock_bh(&queue_lock); status = ipq_receive_peer(NLMSG_DATA(nlh), type, - skblen - NLMSG_LENGTH(0)); + nlmsglen - NLMSG_LENGTH(0)); if (status < 0) RCV_SKB_FAIL(status); diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 6606ddb66a2..cc27545ff97 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -425,7 +425,12 @@ ipt_log_target(struct sk_buff **pskb, li.u.log.level = loginfo->level; li.u.log.logflags = loginfo->logflags; - nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix); + if (loginfo->logflags & IPT_LOG_NFLOG) + nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, + loginfo->prefix); + else + ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, + loginfo->prefix); return IPT_CONTINUE; } diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 167619f638c..6c8624a5493 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -529,15 +529,10 @@ static int init_or_cleanup(int init) goto cleanup_localinops; } #endif - - /* For use by REJECT target */ - ip_ct_attach = __nf_conntrack_attach; - return ret; cleanup: synchronize_net(); - ip_ct_attach = NULL; #ifdef CONFIG_SYSCTL unregister_sysctl_table(nf_ct_ipv4_sysctl_header); cleanup_localinops: diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d82c242ea70..fca5fe0cf94 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -835,7 +835,7 @@ static int rt_garbage_collect(void) int r; rthp = rt_remove_balanced_route( - &rt_hash_table[i].chain, + &rt_hash_table[k].chain, rth, &r); goal -= r; diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index 63cf7e54084..e0e9d1383c7 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c @@ -125,7 +125,7 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, /* Update AIMD parameters */ if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) { while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && - ca->ai < HSTCP_AIMD_MAX) + ca->ai < HSTCP_AIMD_MAX - 1) ca->ai++; } else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) { while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a7623ead39a..9f498a6c889 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1036,6 +1036,10 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ limit = min(send_win, cong_win); + /* If a full-sized TSO skb can be sent, do it. */ + if (limit >= 65536) + return 0; + if (sysctl_tcp_tso_win_divisor) { u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index d4df0ddd424..32ad229b4fe 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -152,10 +152,16 @@ error_nolock: goto out_exit; } -int xfrm4_output_finish(struct sk_buff *skb) +static int xfrm4_output_finish(struct sk_buff *skb) { int err; +#ifdef CONFIG_NETFILTER + if (!skb->dst->xfrm) { + IPCB(skb)->flags |= IPSKB_REROUTED; + return dst_output(skb); + } +#endif while (likely((err = xfrm4_output_one(skb)) == 0)) { nf_reset(skb); @@ -178,6 +184,7 @@ int xfrm4_output_finish(struct sk_buff *skb) int xfrm4_output(struct sk_buff *skb) { - return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, - xfrm4_output_finish); + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, + xfrm4_output_finish, + !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 45f7ae58f2c..f285bbf296e 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -35,6 +35,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/ xdst->u.rt.fl.fl4_dst == fl->fl4_dst && xdst->u.rt.fl.fl4_src == fl->fl4_src && + xdst->u.rt.fl.fl4_tos == fl->fl4_tos && xfrm_bundle_ok(xdst, fl, AF_INET)) { dst_clone(dst); break; @@ -61,7 +62,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int .nl_u = { .ip4_u = { .saddr = local, - .daddr = remote + .daddr = remote, + .tos = fl->fl4_tos } } }; @@ -230,6 +232,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl) fl->proto = iph->protocol; fl->fl4_dst = iph->daddr; fl->fl4_src = iph->saddr; + fl->fl4_tos = iph->tos; } static inline int xfrm4_garbage_collect(void) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b7d8822c1be..19727d94196 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -822,7 +822,7 @@ struct ipv6_saddr_score { int addr_type; unsigned int attrs; int matchlen; - unsigned int scope; + int scope; unsigned int rule; }; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index c7932cb420a..84963749ab7 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -279,7 +279,7 @@ static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc goto out; memcpy(tmp_hdr, skb->nh.raw, hdr_len); if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len)) - goto out; + goto free_out; skb->nh.ipv6h->priority = 0; skb->nh.ipv6h->flow_lbl[0] = 0; skb->nh.ipv6h->flow_lbl[1] = 0; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index fcf883183ce..21eb725e885 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -42,6 +42,7 @@ #include <linux/net.h> #include <linux/skbuff.h> #include <linux/init.h> +#include <linux/netfilter.h> #ifdef CONFIG_SYSCTL #include <linux/sysctl.h> @@ -255,6 +256,7 @@ out: struct icmpv6_msg { struct sk_buff *skb; int offset; + uint8_t type; }; static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) @@ -266,6 +268,8 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset, to, len, csum); skb->csum = csum_block_add(skb->csum, csum, odd); + if (!(msg->type & ICMPV6_INFOMSG_MASK)) + nf_ct_attach(skb, org_skb); return 0; } @@ -403,6 +407,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, msg.skb = skb; msg.offset = skb->nh.raw - skb->data; + msg.type = type; len = skb->len - msg.offset; len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr)); @@ -500,6 +505,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) msg.skb = skb; msg.offset = 0; + msg.type = ICMPV6_ECHO_REPLY; err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl, diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 4154f3a8b6c..bb8ffb8a14c 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -87,7 +87,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, struct inet_timewait_sock **twp) { struct inet_hashinfo *hinfo = death_row->hashinfo; - const struct inet_sock *inet = inet_sk(sk); + struct inet_sock *inet = inet_sk(sk); const struct ipv6_pinfo *np = inet6_sk(sk); const struct in6_addr *daddr = &np->rcv_saddr; const struct in6_addr *saddr = &np->daddr; @@ -129,6 +129,10 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, } unique: + /* Must record num and sport now. Otherwise we will see + * in hash table socket with a funny identity. */ + inet->num = lport; + inet->sport = htons(lport); BUG_TRAP(sk_unhashed(sk)); __sk_add_node(sk, &head->chain); sk->sk_hash = hash; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index efa3e72cfcf..5bf70b1442e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -494,6 +494,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) struct net_device *dev; struct sk_buff *frag; struct rt6_info *rt = (struct rt6_info*)skb->dst; + struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; struct ipv6hdr *tmp_hdr; struct frag_hdr *fh; unsigned int mtu, hlen, left, len; @@ -505,7 +506,12 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) hlen = ip6_find_1stfragopt(skb, &prevhdr); nexthdr = *prevhdr; - mtu = dst_mtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr); + mtu = dst_mtu(&rt->u.dst); + if (np && np->frag_size < mtu) { + if (np->frag_size) + mtu = np->frag_size; + } + mtu -= hlen + sizeof(struct frag_hdr); if (skb_shinfo(skb)->frag_list) { int first_len = skb_pagelen(skb); @@ -882,7 +888,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, inet->cork.fl = *fl; np->cork.hop_limit = hlimit; np->cork.tclass = tclass; - inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path); + mtu = dst_mtu(rt->u.dst.path); + if (np && np->frag_size < mtu) { + if (np->frag_size) + mtu = np->frag_size; + } + inet->cork.fragsize = mtu; if (dst_allfrag(rt->u.dst.path)) inet->cork.flags |= IPCORK_ALLFRAG; inet->cork.length = 0; @@ -933,10 +944,11 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && (rt->u.dst.dev->features & NETIF_F_UFO)) { - if(ip6_ufo_append_data(sk, getfrag, from, length, hh_len, - fragheaderlen, transhdrlen, mtu, flags)) + err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, + fragheaderlen, transhdrlen, mtu, + flags); + if (err) goto error; - return 0; } diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 92ead3cf956..48597538db3 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -458,7 +458,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, mtu = IPV6_MIN_MTU; t->dev->mtu = mtu; - if ((len = sizeof (*ipv6h) + ipv6h->payload_len) > mtu) { + if ((len = sizeof (*ipv6h) + ntohs(ipv6h->payload_len)) > mtu) { rel_type = ICMPV6_PKT_TOOBIG; rel_code = 0; rel_info = mtu; @@ -884,6 +884,7 @@ ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) t->parms.encap_limit = p->encap_limit; t->parms.flowinfo = p->flowinfo; t->parms.link = p->link; + ip6_tnl_dst_reset(t); ip6ip6_tnl_link_config(t); return 0; } diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 5027bbe6415..af0635084df 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -522,7 +522,7 @@ ipq_rcv_skb(struct sk_buff *skb) write_unlock_bh(&queue_lock); status = ipq_receive_peer(NLMSG_DATA(nlh), type, - skblen - NLMSG_LENGTH(0)); + nlmsglen - NLMSG_LENGTH(0)); if (status < 0) RCV_SKB_FAIL(status); diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 77c725832de..6b930efa9fb 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -436,7 +436,12 @@ ip6t_log_target(struct sk_buff **pskb, li.u.log.level = loginfo->level; li.u.log.logflags = loginfo->logflags; - nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix); + if (loginfo->logflags & IP6T_LOG_NFLOG) + nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, + loginfo->prefix); + else + ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, + loginfo->prefix); return IP6T_CONTINUE; } diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index c745717b4ce..0e6d1d4bbd5 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -160,6 +160,8 @@ static void send_reset(struct sk_buff *oldskb) csum_partial((char *)tcph, sizeof(struct tcphdr), 0)); + nf_ct_attach(nskb, oldskb); + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev, dst_output); } diff --git a/net/key/af_key.c b/net/key/af_key.c index ae86d237a45..b2d4d1dd211 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1423,7 +1423,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, if (err < 0) { x->km.state = XFRM_STATE_DEAD; - xfrm_state_put(x); + __xfrm_state_put(x); goto out; } diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 0e550127fa7..a8e5544da93 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -126,7 +126,7 @@ config NETFILTER_XT_TARGET_CONNMARK tristate '"CONNMARK" target support' depends on NETFILTER_XTABLES depends on IP_NF_MANGLE || IP6_NF_MANGLE - depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK) help This option adds a `CONNMARK' target, which allows one to manipulate the connection mark value. Similar to the MARK target, but @@ -187,7 +187,7 @@ config NETFILTER_XT_MATCH_COMMENT config NETFILTER_XT_MATCH_CONNBYTES tristate '"connbytes" per-connection counter match support' depends on NETFILTER_XTABLES - depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT + depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK) help This option adds a `connbytes' match, which allows you to match the number of bytes and/or packets for each direction within a connection. @@ -198,7 +198,7 @@ config NETFILTER_XT_MATCH_CONNBYTES config NETFILTER_XT_MATCH_CONNMARK tristate '"connmark" connection mark match support' depends on NETFILTER_XTABLES - depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK) help This option adds a `connmark' match, which allows you to match the connection mark value previously set for the session by `CONNMARK'. diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0ce337a1d97..d622ddf08bb 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1556,6 +1556,8 @@ void nf_conntrack_cleanup(void) { int i; + ip_ct_attach = NULL; + /* This makes sure all current packets have passed through netfilter framework. Roll on, two-stage module delete... */ @@ -1715,6 +1717,9 @@ int __init nf_conntrack_init(void) nf_ct_l3protos[i] = &nf_conntrack_generic_l3proto; write_unlock_bh(&nf_conntrack_lock); + /* For use by REJECT target */ + ip_ct_attach = __nf_conntrack_attach; + /* Set up fake conntrack: - to never be deleted, not in any hashes */ atomic_set(&nf_conntrack_untracked.ct_general.use, 1); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index df99138c3b3..6492ed66fb3 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -864,7 +864,9 @@ static int csum6(const struct sk_buff *skb, unsigned int dataoff) { return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, skb->len - dataoff, IPPROTO_TCP, - skb->ip_summed == CHECKSUM_HW ? skb->csum + skb->ip_summed == CHECKSUM_HW + ? csum_sub(skb->csum, + skb_checksum(skb, 0, dataoff, 0)) : skb_checksum(skb, dataoff, skb->len - dataoff, 0)); } diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 4264dd079a1..831d206344e 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -161,7 +161,9 @@ static int csum6(const struct sk_buff *skb, unsigned int dataoff) { return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, skb->len - dataoff, IPPROTO_UDP, - skb->ip_summed == CHECKSUM_HW ? skb->csum + skb->ip_summed == CHECKSUM_HW + ? csum_sub(skb->csum, + skb_checksum(skb, 0, dataoff, 0)) : skb_checksum(skb, dataoff, skb->len - dataoff, 0)); } diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index d3a4f30a7f2..d9f0d7ef103 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -6,6 +6,7 @@ #include <linux/skbuff.h> #include <linux/netfilter.h> #include <linux/seq_file.h> +#include <linux/rcupdate.h> #include <net/protocol.h> #include "nf_internals.h" @@ -16,7 +17,7 @@ * for queueing and must reinject all packets it receives, no matter what. */ static struct nf_queue_handler *queue_handler[NPROTO]; -static struct nf_queue_rerouter *queue_rerouter; +static struct nf_queue_rerouter *queue_rerouter[NPROTO]; static DEFINE_RWLOCK(queue_handler_lock); @@ -64,7 +65,7 @@ int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer) return -EINVAL; write_lock_bh(&queue_handler_lock); - memcpy(&queue_rerouter[pf], rer, sizeof(queue_rerouter[pf])); + rcu_assign_pointer(queue_rerouter[pf], rer); write_unlock_bh(&queue_handler_lock); return 0; @@ -77,8 +78,9 @@ int nf_unregister_queue_rerouter(int pf) return -EINVAL; write_lock_bh(&queue_handler_lock); - memset(&queue_rerouter[pf], 0, sizeof(queue_rerouter[pf])); + rcu_assign_pointer(queue_rerouter[pf], NULL); write_unlock_bh(&queue_handler_lock); + synchronize_rcu(); return 0; } EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); @@ -114,16 +116,17 @@ int nf_queue(struct sk_buff **skb, struct net_device *physindev = NULL; struct net_device *physoutdev = NULL; #endif + struct nf_queue_rerouter *rerouter; /* QUEUE == DROP if noone is waiting, to be safe. */ read_lock(&queue_handler_lock); - if (!queue_handler[pf] || !queue_handler[pf]->outfn) { + if (!queue_handler[pf]) { read_unlock(&queue_handler_lock); kfree_skb(*skb); return 1; } - info = kmalloc(sizeof(*info)+queue_rerouter[pf].rer_size, GFP_ATOMIC); + info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC); if (!info) { if (net_ratelimit()) printk(KERN_ERR "OOM queueing packet %p\n", @@ -155,15 +158,13 @@ int nf_queue(struct sk_buff **skb, if (physoutdev) dev_hold(physoutdev); } #endif - if (queue_rerouter[pf].save) - queue_rerouter[pf].save(*skb, info); + rerouter = rcu_dereference(queue_rerouter[pf]); + if (rerouter) + rerouter->save(*skb, info); status = queue_handler[pf]->outfn(*skb, info, queuenum, queue_handler[pf]->data); - if (status >= 0 && queue_rerouter[pf].reroute) - status = queue_rerouter[pf].reroute(skb, info); - read_unlock(&queue_handler_lock); if (status < 0) { @@ -189,6 +190,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, { struct list_head *elem = &info->elem->list; struct list_head *i; + struct nf_queue_rerouter *rerouter; rcu_read_lock(); @@ -212,7 +214,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, break; } - if (elem == &nf_hooks[info->pf][info->hook]) { + if (i == &nf_hooks[info->pf][info->hook]) { /* The module which sent it to userspace is gone. */ NFDEBUG("%s: module disappeared, dropping packet.\n", __FUNCTION__); @@ -226,6 +228,12 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, } if (verdict == NF_ACCEPT) { + rerouter = rcu_dereference(queue_rerouter[info->pf]); + if (rerouter && rerouter->reroute(&skb, info) < 0) + verdict = NF_DROP; + } + + if (verdict == NF_ACCEPT) { next_hook: verdict = nf_iterate(&nf_hooks[info->pf][info->hook], &skb, info->hook, @@ -322,22 +330,12 @@ int __init netfilter_queue_init(void) { #ifdef CONFIG_PROC_FS struct proc_dir_entry *pde; -#endif - queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter), - GFP_KERNEL); - if (!queue_rerouter) - return -ENOMEM; -#ifdef CONFIG_PROC_FS pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter); - if (!pde) { - kfree(queue_rerouter); + if (!pde) return -1; - } pde->proc_fops = &nfqueue_file_ops; #endif - memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter)); - return 0; } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index cac38b2e147..2cf5fb8322c 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -928,8 +928,12 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, if (nfqa[NFQA_CFG_PARAMS-1]) { struct nfqnl_msg_config_params *params; - params = NFA_DATA(nfqa[NFQA_CFG_PARAMS-1]); + if (!queue) { + ret = -ENOENT; + goto out_put; + } + params = NFA_DATA(nfqa[NFQA_CFG_PARAMS-1]); nfqnl_set_mode(queue, params->copy_mode, ntohl(params->copy_range)); } diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 6b9772d9587..59dc7d14060 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1194,6 +1194,9 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, msg->msg_namelen = sizeof(*addr); } + if (nlk->flags & NETLINK_RECV_PKTINFO) + netlink_cmsg_recv_pktinfo(msg, skb); + if (NULL == siocb->scm) { memset(&scm, 0, sizeof(scm)); siocb->scm = &scm; @@ -1205,8 +1208,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, netlink_dump(sk); scm_recv(sock, msg, siocb->scm, flags); - if (nlk->flags & NETLINK_RECV_PKTINFO) - netlink_cmsg_recv_pktinfo(msg, skb); out: netlink_rcv_wake(sk); diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 792ce59940e..2ffa11c6e8d 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -707,7 +707,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, rtattr_failure: nlmsg_failure: - skb_trim(skb, b - skb->data); + kfree_skb(skb); return -1; } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1b5989b1b67..c323cc6a28b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -547,7 +547,7 @@ static struct sock * unix_create1(struct socket *sock) struct sock *sk = NULL; struct unix_sock *u; - if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files) + if (atomic_read(&unix_nr_socks) >= 2*get_max_files()) goto out; sk = sk_alloc(PF_UNIX, GFP_KERNEL, &unix_proto, 1); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 98ec53bd3ac..ae62054a9fc 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -782,7 +782,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, int nx = 0; int err; u32 genid; - u16 family = dst_orig->ops->family; + u16 family; u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); u32 sk_sid = security_sk_sid(sk, fl, dir); restart: @@ -796,13 +796,14 @@ restart: if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) return 0; - policy = flow_cache_lookup(fl, sk_sid, family, dir, - xfrm_policy_lookup); + policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family, + dir, xfrm_policy_lookup); } if (!policy) return 0; + family = dst_orig->ops->family; policy->curlft.use_time = (unsigned long)xtime.tv_sec; switch (policy->action) { @@ -885,8 +886,6 @@ restart: * We can't enlist stable bundles either. */ write_unlock_bh(&policy->lock); - - xfrm_pol_put(policy); if (dst) dst_free(dst); @@ -997,13 +996,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, struct sec_decap_state *xvec = &(skb->sp->x[i]); if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) return 0; - - /* If there is a post_input processor, try running it */ - if (xvec->xvec->type->post_input && - (xvec->xvec->type->post_input)(xvec->xvec, - &(xvec->decap), - skb) != 0) - return 0; } } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index e12d0be5f97..c656cbaf35e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -220,14 +220,14 @@ static int __xfrm_state_delete(struct xfrm_state *x) x->km.state = XFRM_STATE_DEAD; spin_lock(&xfrm_state_lock); list_del(&x->bydst); - atomic_dec(&x->refcnt); + __xfrm_state_put(x); if (x->id.spi) { list_del(&x->byspi); - atomic_dec(&x->refcnt); + __xfrm_state_put(x); } spin_unlock(&xfrm_state_lock); if (del_timer(&x->timer)) - atomic_dec(&x->refcnt); + __xfrm_state_put(x); /* The number two in this test is the reference * mentioned in the comment below plus the reference @@ -243,7 +243,7 @@ static int __xfrm_state_delete(struct xfrm_state *x) * The xfrm_state_alloc call gives a reference, and that * is what we are dropping here. */ - atomic_dec(&x->refcnt); + __xfrm_state_put(x); err = 0; } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ac87a09ba83..7de17559249 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -345,7 +345,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) if (err < 0) { x->km.state = XFRM_STATE_DEAD; - xfrm_state_put(x); + __xfrm_state_put(x); goto out; } |