Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 23 Mar 2007 02:34:09 +0000 (19:34 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 23 Mar 2007 02:34:09 +0000 (19:34 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [NETFILTER]: nat: avoid rerouting packets if only XFRM policy key changed
  [NETFILTER]: nf_conntrack_netlink: add missing dependency on NF_NAT
  [NET]: fix up misplaced inlines.
  [SCTP]: Correctly reset ssthresh when restarting association
  [BRIDGE]: Fix fdb RCU race
  [NET]: Fix fib_rules dump race
  [XFRM]: ipsecv6 needs a space when printing audit record.
  [X25] x25_forward_call(): fix NULL dereferences
  [SCTP]: Reset some transport and association variables on restart
  [SCTP]: Increment error counters on user requested HBs.
  [SCTP]: Clean up stale data during association restart
  [IrDA]: Calling ppp_unregister_channel() from process context
  [IrDA]: irttp_dup spin_lock initialisation
  [IrDA]: Delay needed when uploading firmware chunks

25 files changed:
drivers/net/irda/irda-usb.c
include/net/sctp/structs.h
include/net/sctp/ulpqueue.h
net/bluetooth/hidp/core.c
net/bridge/br_fdb.c
net/bridge/br_netfilter.c
net/core/fib_rules.c
net/core/sock.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/nf_nat_standalone.c
net/ipv6/addrconf.c
net/ipv6/route.c
net/ipv6/xfrm6_tunnel.c
net/irda/irnet/irnet.h
net/irda/irnet/irnet_irda.c
net/irda/irttp.c
net/netfilter/Kconfig
net/sched/cls_route.c
net/sctp/associola.c
net/sctp/sm_statefuns.c
net/sctp/transport.c
net/sctp/ulpqueue.c
net/x25/x25_forward.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c

index 340ee99..1d510bd 100644 (file)
@@ -1057,6 +1057,8 @@ static int stir421x_fw_upload(struct irda_usb_cb *self,
 
                if (ret < 0)
                        break;
+
+               mdelay(10);
        }
 
        kfree(patch_block);
index 31a8e88..f431acf 100644 (file)
@@ -1002,6 +1002,7 @@ void sctp_transport_update_rto(struct sctp_transport *, __u32);
 void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
 void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
 unsigned long sctp_transport_timeout(struct sctp_transport *);
+void sctp_transport_reset(struct sctp_transport *);
 
 
 /* This is the structure we use to queue packets as they come into
index a43c878..ab26ab3 100644 (file)
@@ -59,6 +59,7 @@ struct sctp_ulpq {
 /* Prototypes. */
 struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *,
                                 struct sctp_association *);
+void sctp_ulpq_flush(struct sctp_ulpq *ulpq);
 void sctp_ulpq_free(struct sctp_ulpq *);
 
 /* Add a new DATA chunk for processing. */
index 4c914df..ecfe8da 100644 (file)
@@ -319,7 +319,7 @@ static int __hidp_send_ctrl_message(struct hidp_session *session,
        return 0;
 }
 
-static int inline hidp_send_ctrl_message(struct hidp_session *session,
+static inline int hidp_send_ctrl_message(struct hidp_session *session,
                        unsigned char hdr, unsigned char *data, int size)
 {
        int err;
index def2e40..8d566c1 100644 (file)
@@ -197,8 +197,8 @@ struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
 
        rcu_read_lock();
        fdb = __br_fdb_get(br, addr);
-       if (fdb)
-               atomic_inc(&fdb->use_count);
+       if (fdb && !atomic_inc_not_zero(&fdb->use_count))
+               fdb = NULL;
        rcu_read_unlock();
        return fdb;
 }
index 7712d76..5439a3c 100644 (file)
@@ -61,7 +61,7 @@ static int brnf_filter_vlan_tagged __read_mostly = 1;
 #define brnf_filter_vlan_tagged 1
 #endif
 
-static __be16 inline vlan_proto(const struct sk_buff *skb)
+static inline __be16 vlan_proto(const struct sk_buff *skb)
 {
        return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
 }
index 215f1bf..3aea4e8 100644 (file)
@@ -374,7 +374,7 @@ int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
                return -EAFNOSUPPORT;
 
        rcu_read_lock();
-       list_for_each_entry(rule, ops->rules_list, list) {
+       list_for_each_entry_rcu(rule, ops->rules_list, list) {
                if (idx < cb->args[0])
                        goto skip;
 
index 8d65d64..27c4f62 100644 (file)
@@ -808,7 +808,7 @@ lenout:
  *
  * (We also register the sk_lock with the lock validator.)
  */
-static void inline sock_lock_init(struct sock *sk)
+static inline void sock_lock_init(struct sock *sk)
 {
        sock_lock_init_class_and_name(sk,
                        af_family_slock_key_strings[sk->sk_family],
index adf25f9..6bcfdf6 100644 (file)
@@ -253,14 +253,17 @@ ip_nat_local_fn(unsigned int hooknum,
                enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
                if (ct->tuplehash[dir].tuple.dst.ip !=
-                   ct->tuplehash[!dir].tuple.src.ip
-#ifdef CONFIG_XFRM
-                   || ct->tuplehash[dir].tuple.dst.u.all !=
-                      ct->tuplehash[!dir].tuple.src.u.all
-#endif
-                   )
+                   ct->tuplehash[!dir].tuple.src.ip) {
                        if (ip_route_me_harder(pskb, RTN_UNSPEC))
                                ret = NF_DROP;
+               }
+#ifdef CONFIG_XFRM
+               else if (ct->tuplehash[dir].tuple.dst.u.all !=
+                        ct->tuplehash[!dir].tuple.src.u.all)
+                       if (ip_xfrm_me_harder(pskb))
+                               ret = NF_DROP;
+#endif
+
        }
        return ret;
 }
index e4d3ef1..15aa3db 100644 (file)
@@ -245,14 +245,16 @@ nf_nat_local_fn(unsigned int hooknum,
                enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
                if (ct->tuplehash[dir].tuple.dst.u3.ip !=
-                   ct->tuplehash[!dir].tuple.src.u3.ip
-#ifdef CONFIG_XFRM
-                   || ct->tuplehash[dir].tuple.dst.u.all !=
-                      ct->tuplehash[!dir].tuple.src.u.all
-#endif
-                   )
+                   ct->tuplehash[!dir].tuple.src.u3.ip) {
                        if (ip_route_me_harder(pskb, RTN_UNSPEC))
                                ret = NF_DROP;
+               }
+#ifdef CONFIG_XFRM
+               else if (ct->tuplehash[dir].tuple.dst.u.all !=
+                        ct->tuplehash[!dir].tuple.src.u.all)
+                       if (ip_xfrm_me_harder(pskb))
+                               ret = NF_DROP;
+#endif
        }
        return ret;
 }
index a7fee6b..1b61699 100644 (file)
@@ -804,7 +804,7 @@ struct ipv6_saddr_score {
 #define IPV6_SADDR_SCORE_LABEL         0x0020
 #define IPV6_SADDR_SCORE_PRIVACY       0x0040
 
-static int inline ipv6_saddr_preferred(int type)
+static inline int ipv6_saddr_preferred(int type)
 {
        if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|
                    IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED))
@@ -813,7 +813,7 @@ static int inline ipv6_saddr_preferred(int type)
 }
 
 /* static matching label */
-static int inline ipv6_saddr_label(const struct in6_addr *addr, int type)
+static inline int ipv6_saddr_label(const struct in6_addr *addr, int type)
 {
  /*
   *    prefix (longest match)  label
@@ -3318,7 +3318,7 @@ errout:
                rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
 }
 
-static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
+static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
                                __s32 *array, int bytes)
 {
        BUG_ON(bytes < (DEVCONF_MAX * 4));
index 0e1f4b2..a6b3117 100644 (file)
@@ -308,7 +308,7 @@ static inline void rt6_probe(struct rt6_info *rt)
 /*
  * Default Router Selection (RFC 2461 6.3.6)
  */
-static int inline rt6_check_dev(struct rt6_info *rt, int oif)
+static inline int rt6_check_dev(struct rt6_info *rt, int oif)
 {
        struct net_device *dev = rt->rt6i_dev;
        int ret = 0;
@@ -328,7 +328,7 @@ static int inline rt6_check_dev(struct rt6_info *rt, int oif)
        return ret;
 }
 
-static int inline rt6_check_neigh(struct rt6_info *rt)
+static inline int rt6_check_neigh(struct rt6_info *rt)
 {
        struct neighbour *neigh = rt->rt6i_nexthop;
        int m = 0;
index ee4b84a..93c4223 100644 (file)
@@ -58,7 +58,7 @@ static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly;
 static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE];
 static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE];
 
-static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr)
+static inline unsigned xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr)
 {
        unsigned h;
 
@@ -70,7 +70,7 @@ static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr)
        return h;
 }
 
-static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi)
+static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi)
 {
        return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE;
 }
index 873ae18..bc2e15c 100644 (file)
@@ -419,7 +419,7 @@ typedef struct irnet_socket
   u32                  raccm;          /* to please pppd - dummy) */
   unsigned int         flags;          /* PPP flags (compression, ...) */
   unsigned int         rbits;          /* Unused receive flags ??? */
-
+  struct work_struct disconnect_work;   /* Process context disconnection */
   /* ------------------------ IrTTP part ------------------------ */
   /* We create a pseudo "socket" over the IrDA tranport */
   unsigned long                ttp_open;       /* Set when IrTTP is ready */
index c378e66..a4f1439 100644 (file)
 
 #include "irnet_irda.h"                /* Private header */
 
+/*
+ * PPP disconnect work: we need to make sure we're in
+ * process context when calling ppp_unregister_channel().
+ */
+static void irnet_ppp_disconnect(struct work_struct *work)
+{
+       irnet_socket * self =
+               container_of(work, irnet_socket, disconnect_work);
+
+       if (self == NULL)
+               return;
+       /*
+        * If we were connected, cleanup & close the PPP
+        * channel, which will kill pppd (hangup) and the rest.
+        */
+       if (self->ppp_open && !self->ttp_open && !self->ttp_connect) {
+               ppp_unregister_channel(&self->chan);
+               self->ppp_open = 0;
+       }
+}
+
 /************************* CONTROL CHANNEL *************************/
 /*
  * When ppp is not active, /dev/irnet act as a control channel.
@@ -499,6 +520,8 @@ irda_irnet_create(irnet_socket *    self)
 #endif /* DISCOVERY_NOMASK */
   self->tx_flow = FLOW_START;  /* Flow control from IrTTP */
 
+  INIT_WORK(&self->disconnect_work, irnet_ppp_disconnect);
+
   DEXIT(IRDA_SOCK_TRACE, "\n");
   return(0);
 }
@@ -1134,15 +1157,8 @@ irnet_disconnect_indication(void *       instance,
     {
       if(test_open)
        {
-#ifdef MISSING_PPP_API
-         /* ppp_unregister_channel() wants a user context, which we
-          * are guaranteed to NOT have here. What are we supposed
-          * to do here ? Jean II */
-         /* If we were connected, cleanup & close the PPP channel,
-          * which will kill pppd (hangup) and the rest */
-         ppp_unregister_channel(&self->chan);
-         self->ppp_open = 0;
-#endif
+         /* ppp_unregister_channel() wants a user context. */
+         schedule_work(&self->disconnect_work);
        }
       else
        {
index a7486b3..da3f2bc 100644 (file)
@@ -1455,6 +1455,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
 
        /* Not everything should be copied */
        new->notify.instance = instance;
+       spin_lock_init(&new->lock);
        init_timer(&new->todo_timer);
 
        skb_queue_head_init(&new->rx_queue);
index 253fce3..54698af 100644 (file)
@@ -275,6 +275,7 @@ config NF_CT_NETLINK
        tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
        depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
        depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+       depends on NF_NAT=n || NF_NAT
        help
          This option enables support for a netlink-based userspace interface
 
index e85df07..abc47cc 100644 (file)
@@ -93,7 +93,7 @@ void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32
        spin_unlock_bh(&dev->queue_lock);
 }
 
-static void __inline__
+static inline void
 route4_set_fastmap(struct route4_head *head, u32 id, int iif,
                   struct route4_filter *f)
 {
index fa82b73..78d2ddb 100644 (file)
@@ -1046,6 +1046,9 @@ void sctp_assoc_update(struct sctp_association *asoc,
                trans = list_entry(pos, struct sctp_transport, transports);
                if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr))
                        sctp_assoc_del_peer(asoc, &trans->ipaddr);
+
+               if (asoc->state >= SCTP_STATE_ESTABLISHED)
+                       sctp_transport_reset(trans);
        }
 
        /* If the case is A (association restart), use
@@ -1063,6 +1066,18 @@ void sctp_assoc_update(struct sctp_association *asoc,
                 */
                sctp_ssnmap_clear(asoc->ssnmap);
 
+               /* Flush the ULP reassembly and ordered queue.
+                * Any data there will now be stale and will
+                * cause problems.
+                */
+               sctp_ulpq_flush(&asoc->ulpq);
+
+               /* reset the overall association error count so
+                * that the restarted association doesn't get torn
+                * down on the next retransmission timer.
+                */
+               asoc->overall_error_count = 0;
+
        } else {
                /* Add any peer addresses from the new association. */
                list_for_each(pos, &new->peer.transport_addr_list) {
index 70c39ea..e9097cf 100644 (file)
@@ -4342,8 +4342,24 @@ sctp_disposition_t sctp_sf_do_prm_requestheartbeat(
                                        void *arg,
                                        sctp_cmd_seq_t *commands)
 {
-       return sctp_sf_heartbeat(ep, asoc, type, (struct sctp_transport *)arg,
-                                commands);
+       if (SCTP_DISPOSITION_NOMEM == sctp_sf_heartbeat(ep, asoc, type,
+                                     (struct sctp_transport *)arg, commands))
+               return SCTP_DISPOSITION_NOMEM;
+
+       /*
+        * RFC 2960 (bis), section 8.3
+        *
+        *    D) Request an on-demand HEARTBEAT on a specific destination
+        *    transport address of a given association.
+        *
+        *    The endpoint should increment the respective error  counter of
+        *    the destination transport address each time a HEARTBEAT is sent
+        *    to that address and not acknowledged within one RTO.
+        *
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_RESET,
+                       SCTP_TRANSPORT(arg));
+       return SCTP_DISPOSITION_CONSUME;
 }
 
 /*
index a596f53..4d8c2ab 100644 (file)
@@ -526,3 +526,35 @@ unsigned long sctp_transport_timeout(struct sctp_transport *t)
        timeout += jiffies;
        return timeout;
 }
+
+/* Reset transport variables to their initial values */
+void sctp_transport_reset(struct sctp_transport *t)
+{
+       struct sctp_association *asoc = t->asoc;
+
+       /* RFC 2960 (bis), Section 5.2.4
+        * All the congestion control parameters (e.g., cwnd, ssthresh)
+        * related to this peer MUST be reset to their initial values
+        * (see Section 6.2.1)
+        */
+       t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
+       t->ssthresh = asoc->peer.i.a_rwnd;
+       t->rto = asoc->rto_initial;
+       t->rtt = 0;
+       t->srtt = 0;
+       t->rttvar = 0;
+
+       /* Reset these additional varibles so that we have a clean
+        * slate.
+        */
+       t->partial_bytes_acked = 0;
+       t->flight_size = 0;
+       t->error_count = 0;
+       t->rto_pending = 0;
+
+       /* Initialize the state information for SFR-CACC */
+       t->cacc.changeover_active = 0;
+       t->cacc.cycling_changeover = 0;
+       t->cacc.next_tsn_at_change = 0;
+       t->cacc.cacc_saw_newack = 0;
+}
index f4759a9..bfb197e 100644 (file)
@@ -73,7 +73,7 @@ struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
 
 
 /* Flush the reassembly and ordering queues.  */
-static void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
+void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
 {
        struct sk_buff *skb;
        struct sctp_ulpevent *event;
index d339e0c..8738ec7 100644 (file)
@@ -26,64 +26,66 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from,
        short same_lci = 0;
        int rc = 0;
 
-       if ((rt = x25_get_route(dest_addr)) != NULL) {
+       if ((rt = x25_get_route(dest_addr)) == NULL)
+               goto out_no_route;
 
-               if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) {
-                       /* This shouldnt happen, if it occurs somehow
-                        * do something sensible
-                        */
-                       goto out_put_route;
-               }
-
-               /* Avoid a loop. This is the normal exit path for a
-                * system with only one x.25 iface and default route
+       if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) {
+               /* This shouldnt happen, if it occurs somehow
+                * do something sensible
                 */
-               if (rt->dev == from->dev) {
-                       goto out_put_nb;
-               }
+               goto out_put_route;
+       }
 
-               /* Remote end sending a call request on an already
-                * established LCI? It shouldnt happen, just in case..
-                */
-               read_lock_bh(&x25_forward_list_lock);
-               list_for_each(entry, &x25_forward_list) {
-                       x25_frwd = list_entry(entry, struct x25_forward, node);
-                       if (x25_frwd->lci == lci) {
-                               printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n");
-                               same_lci = 1;
-                       }
-               }
-               read_unlock_bh(&x25_forward_list_lock);
-
-               /* Save the forwarding details for future traffic */
-               if (!same_lci){
-                       if ((new_frwd = kmalloc(sizeof(struct x25_forward),
-                                                       GFP_ATOMIC)) == NULL){
-                               rc = -ENOMEM;
-                               goto out_put_nb;
-                       }
-                       new_frwd->lci = lci;
-                       new_frwd->dev1 = rt->dev;
-                       new_frwd->dev2 = from->dev;
-                       write_lock_bh(&x25_forward_list_lock);
-                       list_add(&new_frwd->node, &x25_forward_list);
-                       write_unlock_bh(&x25_forward_list_lock);
+       /* Avoid a loop. This is the normal exit path for a
+        * system with only one x.25 iface and default route
+        */
+       if (rt->dev == from->dev) {
+               goto out_put_nb;
+       }
+
+       /* Remote end sending a call request on an already
+        * established LCI? It shouldnt happen, just in case..
+        */
+       read_lock_bh(&x25_forward_list_lock);
+       list_for_each(entry, &x25_forward_list) {
+               x25_frwd = list_entry(entry, struct x25_forward, node);
+               if (x25_frwd->lci == lci) {
+                       printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n");
+                       same_lci = 1;
                }
+       }
+       read_unlock_bh(&x25_forward_list_lock);
 
-               /* Forward the call request */
-               if ( (skbn = skb_clone(skb, GFP_ATOMIC)) == NULL){
+       /* Save the forwarding details for future traffic */
+       if (!same_lci){
+               if ((new_frwd = kmalloc(sizeof(struct x25_forward),
+                                               GFP_ATOMIC)) == NULL){
+                       rc = -ENOMEM;
                        goto out_put_nb;
                }
-               x25_transmit_link(skbn, neigh_new);
-               rc = 1;
+               new_frwd->lci = lci;
+               new_frwd->dev1 = rt->dev;
+               new_frwd->dev2 = from->dev;
+               write_lock_bh(&x25_forward_list_lock);
+               list_add(&new_frwd->node, &x25_forward_list);
+               write_unlock_bh(&x25_forward_list_lock);
        }
 
+       /* Forward the call request */
+       if ( (skbn = skb_clone(skb, GFP_ATOMIC)) == NULL){
+               goto out_put_nb;
+       }
+       x25_transmit_link(skbn, neigh_new);
+       rc = 1;
+
 
 out_put_nb:
        x25_neigh_put(neigh_new);
 
 out_put_route:
        x25_route_put(rt);
+
+out_no_route:
        return rc;
 }
 
index 0c3a70a..785c3e3 100644 (file)
@@ -2089,7 +2089,7 @@ void xfrm_audit_log(uid_t auid, u32 sid, int type, int result,
                                        sizeof(struct in6_addr));
                        }
                        audit_log_format(audit_buf,
-                                        " src=" NIP6_FMT "dst=" NIP6_FMT,
+                                        " src=" NIP6_FMT " dst=" NIP6_FMT,
                                         NIP6(saddr6), NIP6(daddr6));
                }
                break;
index 9678995..e81e2fb 100644 (file)
@@ -2025,7 +2025,7 @@ nlmsg_failure:
        return -1;
 }
 
-static int inline xfrm_sa_len(struct xfrm_state *x)
+static inline int xfrm_sa_len(struct xfrm_state *x)
 {
        int l = 0;
        if (x->aalg)