Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
authorDavid S. Miller <davem@davemloft.net>
Fri, 27 Mar 2009 05:45:23 +0000 (22:45 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 27 Mar 2009 05:45:23 +0000 (22:45 -0700)
1  2 
include/linux/netfilter/x_tables.h
lib/nlattr.c
net/ipv4/netfilter/arp_tables.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_tcp.c

Simple merge
diff --cc lib/nlattr.c
index 80009a2,0000000..c4706eb
mode 100644,000000..100644
--- /dev/null
@@@ -1,475 -1,0 +1,502 @@@
 +/*
 + * NETLINK      Netlink attributes
 + *
 + *            Authors:        Thomas Graf <tgraf@suug.ch>
 + *                            Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
 + */
 +
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/errno.h>
 +#include <linux/jiffies.h>
 +#include <linux/netdevice.h>
 +#include <linux/skbuff.h>
 +#include <linux/string.h>
 +#include <linux/types.h>
 +#include <net/netlink.h>
 +
 +static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
 +      [NLA_U8]        = sizeof(u8),
 +      [NLA_U16]       = sizeof(u16),
 +      [NLA_U32]       = sizeof(u32),
 +      [NLA_U64]       = sizeof(u64),
 +      [NLA_NESTED]    = NLA_HDRLEN,
 +};
 +
 +static int validate_nla(struct nlattr *nla, int maxtype,
 +                      const struct nla_policy *policy)
 +{
 +      const struct nla_policy *pt;
 +      int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
 +
 +      if (type <= 0 || type > maxtype)
 +              return 0;
 +
 +      pt = &policy[type];
 +
 +      BUG_ON(pt->type > NLA_TYPE_MAX);
 +
 +      switch (pt->type) {
 +      case NLA_FLAG:
 +              if (attrlen > 0)
 +                      return -ERANGE;
 +              break;
 +
 +      case NLA_NUL_STRING:
 +              if (pt->len)
 +                      minlen = min_t(int, attrlen, pt->len + 1);
 +              else
 +                      minlen = attrlen;
 +
 +              if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
 +                      return -EINVAL;
 +              /* fall through */
 +
 +      case NLA_STRING:
 +              if (attrlen < 1)
 +                      return -ERANGE;
 +
 +              if (pt->len) {
 +                      char *buf = nla_data(nla);
 +
 +                      if (buf[attrlen - 1] == '\0')
 +                              attrlen--;
 +
 +                      if (attrlen > pt->len)
 +                              return -ERANGE;
 +              }
 +              break;
 +
 +      case NLA_BINARY:
 +              if (pt->len && attrlen > pt->len)
 +                      return -ERANGE;
 +              break;
 +
 +      case NLA_NESTED_COMPAT:
 +              if (attrlen < pt->len)
 +                      return -ERANGE;
 +              if (attrlen < NLA_ALIGN(pt->len))
 +                      break;
 +              if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
 +                      return -ERANGE;
 +              nla = nla_data(nla) + NLA_ALIGN(pt->len);
 +              if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
 +                      return -ERANGE;
 +              break;
 +      case NLA_NESTED:
 +              /* a nested attributes is allowed to be empty; if its not,
 +               * it must have a size of at least NLA_HDRLEN.
 +               */
 +              if (attrlen == 0)
 +                      break;
 +      default:
 +              if (pt->len)
 +                      minlen = pt->len;
 +              else if (pt->type != NLA_UNSPEC)
 +                      minlen = nla_attr_minlen[pt->type];
 +
 +              if (attrlen < minlen)
 +                      return -ERANGE;
 +      }
 +
 +      return 0;
 +}
 +
 +/**
 + * nla_validate - Validate a stream of attributes
 + * @head: head of attribute stream
 + * @len: length of attribute stream
 + * @maxtype: maximum attribute type to be expected
 + * @policy: validation policy
 + *
 + * Validates all attributes in the specified attribute stream against the
 + * specified policy. Attributes with a type exceeding maxtype will be
 + * ignored. See documenation of struct nla_policy for more details.
 + *
 + * Returns 0 on success or a negative error code.
 + */
 +int nla_validate(struct nlattr *head, int len, int maxtype,
 +               const struct nla_policy *policy)
 +{
 +      struct nlattr *nla;
 +      int rem, err;
 +
 +      nla_for_each_attr(nla, head, len, rem) {
 +              err = validate_nla(nla, maxtype, policy);
 +              if (err < 0)
 +                      goto errout;
 +      }
 +
 +      err = 0;
 +errout:
 +      return err;
 +}
 +
++/**
++ * nla_policy_len - Determin the max. length of a policy
++ * @policy: policy to use
++ * @n: number of policies
++ *
++ * Determines the max. length of the policy.  It is currently used
++ * to allocated Netlink buffers roughly the size of the actual
++ * message.
++ *
++ * Returns 0 on success or a negative error code.
++ */
++int
++nla_policy_len(const struct nla_policy *p, int n)
++{
++      int i, len = 0;
++
++      for (i = 0; i < n; i++) {
++              if (p->len)
++                      len += nla_total_size(p->len);
++              else if (nla_attr_minlen[p->type])
++                      len += nla_total_size(nla_attr_minlen[p->type]);
++      }
++
++      return len;
++}
++
 +/**
 + * nla_parse - Parse a stream of attributes into a tb buffer
 + * @tb: destination array with maxtype+1 elements
 + * @maxtype: maximum attribute type to be expected
 + * @head: head of attribute stream
 + * @len: length of attribute stream
 + * @policy: validation policy
 + *
 + * Parses a stream of attributes and stores a pointer to each attribute in
 + * the tb array accessable via the attribute type. Attributes with a type
 + * exceeding maxtype will be silently ignored for backwards compatibility
 + * reasons. policy may be set to NULL if no validation is required.
 + *
 + * Returns 0 on success or a negative error code.
 + */
 +int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
 +            const struct nla_policy *policy)
 +{
 +      struct nlattr *nla;
 +      int rem, err;
 +
 +      memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
 +
 +      nla_for_each_attr(nla, head, len, rem) {
 +              u16 type = nla_type(nla);
 +
 +              if (type > 0 && type <= maxtype) {
 +                      if (policy) {
 +                              err = validate_nla(nla, maxtype, policy);
 +                              if (err < 0)
 +                                      goto errout;
 +                      }
 +
 +                      tb[type] = nla;
 +              }
 +      }
 +
 +      if (unlikely(rem > 0))
 +              printk(KERN_WARNING "netlink: %d bytes leftover after parsing "
 +                     "attributes.\n", rem);
 +
 +      err = 0;
 +errout:
 +      return err;
 +}
 +
 +/**
 + * nla_find - Find a specific attribute in a stream of attributes
 + * @head: head of attribute stream
 + * @len: length of attribute stream
 + * @attrtype: type of attribute to look for
 + *
 + * Returns the first attribute in the stream matching the specified type.
 + */
 +struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
 +{
 +      struct nlattr *nla;
 +      int rem;
 +
 +      nla_for_each_attr(nla, head, len, rem)
 +              if (nla_type(nla) == attrtype)
 +                      return nla;
 +
 +      return NULL;
 +}
 +
 +/**
 + * nla_strlcpy - Copy string attribute payload into a sized buffer
 + * @dst: where to copy the string to
 + * @nla: attribute to copy the string from
 + * @dstsize: size of destination buffer
 + *
 + * Copies at most dstsize - 1 bytes into the destination buffer.
 + * The result is always a valid NUL-terminated string. Unlike
 + * strlcpy the destination buffer is always padded out.
 + *
 + * Returns the length of the source buffer.
 + */
 +size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
 +{
 +      size_t srclen = nla_len(nla);
 +      char *src = nla_data(nla);
 +
 +      if (srclen > 0 && src[srclen - 1] == '\0')
 +              srclen--;
 +
 +      if (dstsize > 0) {
 +              size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
 +
 +              memset(dst, 0, dstsize);
 +              memcpy(dst, src, len);
 +      }
 +
 +      return srclen;
 +}
 +
 +/**
 + * nla_memcpy - Copy a netlink attribute into another memory area
 + * @dest: where to copy to memcpy
 + * @src: netlink attribute to copy from
 + * @count: size of the destination area
 + *
 + * Note: The number of bytes copied is limited by the length of
 + *       attribute's payload. memcpy
 + *
 + * Returns the number of bytes copied.
 + */
 +int nla_memcpy(void *dest, const struct nlattr *src, int count)
 +{
 +      int minlen = min_t(int, count, nla_len(src));
 +
 +      memcpy(dest, nla_data(src), minlen);
 +
 +      return minlen;
 +}
 +
 +/**
 + * nla_memcmp - Compare an attribute with sized memory area
 + * @nla: netlink attribute
 + * @data: memory area
 + * @size: size of memory area
 + */
 +int nla_memcmp(const struct nlattr *nla, const void *data,
 +                           size_t size)
 +{
 +      int d = nla_len(nla) - size;
 +
 +      if (d == 0)
 +              d = memcmp(nla_data(nla), data, size);
 +
 +      return d;
 +}
 +
 +/**
 + * nla_strcmp - Compare a string attribute against a string
 + * @nla: netlink string attribute
 + * @str: another string
 + */
 +int nla_strcmp(const struct nlattr *nla, const char *str)
 +{
 +      int len = strlen(str) + 1;
 +      int d = nla_len(nla) - len;
 +
 +      if (d == 0)
 +              d = memcmp(nla_data(nla), str, len);
 +
 +      return d;
 +}
 +
 +#ifdef CONFIG_NET
 +/**
 + * __nla_reserve - reserve room for attribute on the skb
 + * @skb: socket buffer to reserve room on
 + * @attrtype: attribute type
 + * @attrlen: length of attribute payload
 + *
 + * Adds a netlink attribute header to a socket buffer and reserves
 + * room for the payload but does not copy it.
 + *
 + * The caller is responsible to ensure that the skb provides enough
 + * tailroom for the attribute header and payload.
 + */
 +struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
 +{
 +      struct nlattr *nla;
 +
 +      nla = (struct nlattr *) skb_put(skb, nla_total_size(attrlen));
 +      nla->nla_type = attrtype;
 +      nla->nla_len = nla_attr_size(attrlen);
 +
 +      memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
 +
 +      return nla;
 +}
 +EXPORT_SYMBOL(__nla_reserve);
 +
 +/**
 + * __nla_reserve_nohdr - reserve room for attribute without header
 + * @skb: socket buffer to reserve room on
 + * @attrlen: length of attribute payload
 + *
 + * Reserves room for attribute payload without a header.
 + *
 + * The caller is responsible to ensure that the skb provides enough
 + * tailroom for the payload.
 + */
 +void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
 +{
 +      void *start;
 +
 +      start = skb_put(skb, NLA_ALIGN(attrlen));
 +      memset(start, 0, NLA_ALIGN(attrlen));
 +
 +      return start;
 +}
 +EXPORT_SYMBOL(__nla_reserve_nohdr);
 +
 +/**
 + * nla_reserve - reserve room for attribute on the skb
 + * @skb: socket buffer to reserve room on
 + * @attrtype: attribute type
 + * @attrlen: length of attribute payload
 + *
 + * Adds a netlink attribute header to a socket buffer and reserves
 + * room for the payload but does not copy it.
 + *
 + * Returns NULL if the tailroom of the skb is insufficient to store
 + * the attribute header and payload.
 + */
 +struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
 +{
 +      if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
 +              return NULL;
 +
 +      return __nla_reserve(skb, attrtype, attrlen);
 +}
 +EXPORT_SYMBOL(nla_reserve);
 +
 +/**
 + * nla_reserve_nohdr - reserve room for attribute without header
 + * @skb: socket buffer to reserve room on
 + * @attrlen: length of attribute payload
 + *
 + * Reserves room for attribute payload without a header.
 + *
 + * Returns NULL if the tailroom of the skb is insufficient to store
 + * the attribute payload.
 + */
 +void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
 +{
 +      if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
 +              return NULL;
 +
 +      return __nla_reserve_nohdr(skb, attrlen);
 +}
 +EXPORT_SYMBOL(nla_reserve_nohdr);
 +
 +/**
 + * __nla_put - Add a netlink attribute to a socket buffer
 + * @skb: socket buffer to add attribute to
 + * @attrtype: attribute type
 + * @attrlen: length of attribute payload
 + * @data: head of attribute payload
 + *
 + * The caller is responsible to ensure that the skb provides enough
 + * tailroom for the attribute header and payload.
 + */
 +void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
 +                           const void *data)
 +{
 +      struct nlattr *nla;
 +
 +      nla = __nla_reserve(skb, attrtype, attrlen);
 +      memcpy(nla_data(nla), data, attrlen);
 +}
 +EXPORT_SYMBOL(__nla_put);
 +
 +/**
 + * __nla_put_nohdr - Add a netlink attribute without header
 + * @skb: socket buffer to add attribute to
 + * @attrlen: length of attribute payload
 + * @data: head of attribute payload
 + *
 + * The caller is responsible to ensure that the skb provides enough
 + * tailroom for the attribute payload.
 + */
 +void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
 +{
 +      void *start;
 +
 +      start = __nla_reserve_nohdr(skb, attrlen);
 +      memcpy(start, data, attrlen);
 +}
 +EXPORT_SYMBOL(__nla_put_nohdr);
 +
 +/**
 + * nla_put - Add a netlink attribute to a socket buffer
 + * @skb: socket buffer to add attribute to
 + * @attrtype: attribute type
 + * @attrlen: length of attribute payload
 + * @data: head of attribute payload
 + *
 + * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
 + * the attribute header and payload.
 + */
 +int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
 +{
 +      if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
 +              return -EMSGSIZE;
 +
 +      __nla_put(skb, attrtype, attrlen, data);
 +      return 0;
 +}
 +EXPORT_SYMBOL(nla_put);
 +
 +/**
 + * nla_put_nohdr - Add a netlink attribute without header
 + * @skb: socket buffer to add attribute to
 + * @attrlen: length of attribute payload
 + * @data: head of attribute payload
 + *
 + * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
 + * the attribute payload.
 + */
 +int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
 +{
 +      if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
 +              return -EMSGSIZE;
 +
 +      __nla_put_nohdr(skb, attrlen, data);
 +      return 0;
 +}
 +EXPORT_SYMBOL(nla_put_nohdr);
 +
 +/**
 + * nla_append - Add a netlink attribute without header or padding
 + * @skb: socket buffer to add attribute to
 + * @attrlen: length of attribute payload
 + * @data: head of attribute payload
 + *
 + * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
 + * the attribute payload.
 + */
 +int nla_append(struct sk_buff *skb, int attrlen, const void *data)
 +{
 +      if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
 +              return -EMSGSIZE;
 +
 +      memcpy(skb_put(skb, attrlen), data, attrlen);
 +      return 0;
 +}
 +EXPORT_SYMBOL(nla_append);
 +#endif
 +
 +EXPORT_SYMBOL(nla_validate);
++EXPORT_SYMBOL(nla_policy_len);
 +EXPORT_SYMBOL(nla_parse);
 +EXPORT_SYMBOL(nla_find);
 +EXPORT_SYMBOL(nla_strlcpy);
 +EXPORT_SYMBOL(nla_memcpy);
 +EXPORT_SYMBOL(nla_memcmp);
 +EXPORT_SYMBOL(nla_strcmp);
@@@ -81,28 -80,13 +81,16 @@@ static inline int arp_devaddr_compare(c
  static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask)
  {
  #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-       const unsigned long *a = (const unsigned long *)_a;
-       const unsigned long *b = (const unsigned long *)_b;
-       const unsigned long *mask = (const unsigned long *)_mask;
-       unsigned long ret;
-       ret = (a[0] ^ b[0]) & mask[0];
-       if (IFNAMSIZ > sizeof(unsigned long))
-               ret |= (a[1] ^ b[1]) & mask[1];
-       if (IFNAMSIZ > 2 * sizeof(unsigned long))
-               ret |= (a[2] ^ b[2]) & mask[2];
-       if (IFNAMSIZ > 3 * sizeof(unsigned long))
-               ret |= (a[3] ^ b[3]) & mask[3];
-       BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
+       unsigned long ret = ifname_compare_aligned(_a, _b, _mask);
  #else
        unsigned long ret = 0;
 +      const u16 *a = (const u16 *)_a;
 +      const u16 *b = (const u16 *)_b;
 +      const u16 *mask = (const u16 *)_mask;
        int i;
  
 -      for (i = 0; i < IFNAMSIZ; i++)
 -              ret |= (_a[i] ^ _b[i]) & _mask[i];
 +      for (i = 0; i < IFNAMSIZ/sizeof(u16); i++)
 +              ret |= (a[i] ^ b[i]) & mask[i];
  #endif
        return ret;
  }
Simple merge
Simple merge