Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (24 commits)
  xfrm: Add security check before flushing SAD/SPD
  [NET_SCHED]: Fix filter double free
  [NET]: Avoid duplicate netlink notification when changing link state
  [UDP]: Revert 2-pass hashing changes.
  [AF_UNIX]: Fix stream recvmsg() race.
  [NETFILTER]: nf_conntrack_amanda: fix textsearch_prepare() error check
  [NETFILTER]: ip_tables: fix compat related crash
  [NETFILTER]: nf_conntrack: fix helper module unload races
  [RTNETLINK]: ifindex 0 does not exist
  [NETLINK]: Mark netlink policies const
  [TCP] tcp_probe: Attach printf attribute properly to printl().
  [TCP]: Use LIMIT_NETDEBUG in tcp_retransmit_timer().
  [NET]: Merge dst_discard_in and dst_discard_out.
  [RFKILL]: Make rfkill->name const
  [IPV4]: Restore old behaviour of default config values
  [IPV4]: Add default config support after inetdev_init
  [IPV4]: Convert IPv4 devconf to an array
  [IPV4]: Only panic if inetdev_init fails for loopback
  [TCP]: Honour sk_bound_dev_if in tcp_v4_send_ack
  [BNX2]: Update version and reldate.
  ...
This commit is contained in:
Linus Torvalds 2007-06-07 17:08:06 -07:00
Родитель e5e3c84b70 4aa2e62c45
Коммит df3872a966
63 изменённых файлов: 751 добавлений и 658 удалений

Просмотреть файл

@ -672,7 +672,7 @@ static int c2_up(struct net_device *netdev)
* rdma interface. * rdma interface.
*/ */
in_dev = in_dev_get(netdev); in_dev = in_dev_get(netdev);
in_dev->cnf.arp_ignore = 1; IN_DEV_CONF_SET(in_dev, ARP_IGNORE, 1);
in_dev_put(in_dev); in_dev_put(in_dev);
return 0; return 0;

Просмотреть файл

@ -54,8 +54,8 @@
#define DRV_MODULE_NAME "bnx2" #define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.5.10" #define DRV_MODULE_VERSION "1.5.11"
#define DRV_MODULE_RELDATE "May 1, 2007" #define DRV_MODULE_RELDATE "June 4, 2007"
#define RUN_AT(x) (jiffies + (x)) #define RUN_AT(x) (jiffies + (x))
@ -1778,6 +1778,15 @@ bnx2_init_5709_context(struct bnx2 *bp)
val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12); val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
val |= (BCM_PAGE_BITS - 8) << 16; val |= (BCM_PAGE_BITS - 8) << 16;
REG_WR(bp, BNX2_CTX_COMMAND, val); REG_WR(bp, BNX2_CTX_COMMAND, val);
for (i = 0; i < 10; i++) {
val = REG_RD(bp, BNX2_CTX_COMMAND);
if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
break;
udelay(2);
}
if (val & BNX2_CTX_COMMAND_MEM_INIT)
return -EBUSY;
for (i = 0; i < bp->ctx_pages; i++) { for (i = 0; i < bp->ctx_pages; i++) {
int j; int j;
@ -1811,6 +1820,7 @@ bnx2_init_context(struct bnx2 *bp)
vcid = 96; vcid = 96;
while (vcid) { while (vcid) {
u32 vcid_addr, pcid_addr, offset; u32 vcid_addr, pcid_addr, offset;
int i;
vcid--; vcid--;
@ -1831,16 +1841,20 @@ bnx2_init_context(struct bnx2 *bp)
pcid_addr = vcid_addr; pcid_addr = vcid_addr;
} }
REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00); for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) {
REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); vcid_addr += (i << PHY_CTX_SHIFT);
pcid_addr += (i << PHY_CTX_SHIFT);
/* Zero out the context. */ REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) { REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
CTX_WR(bp, 0x00, offset, 0);
/* Zero out the context. */
for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
CTX_WR(bp, 0x00, offset, 0);
REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
} }
REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
} }
} }
@ -3691,9 +3705,11 @@ bnx2_init_chip(struct bnx2 *bp)
/* Initialize context mapping and zero out the quick contexts. The /* Initialize context mapping and zero out the quick contexts. The
* context block must have already been enabled. */ * context block must have already been enabled. */
if (CHIP_NUM(bp) == CHIP_NUM_5709) if (CHIP_NUM(bp) == CHIP_NUM_5709) {
bnx2_init_5709_context(bp); rc = bnx2_init_5709_context(bp);
else if (rc)
return rc;
} else
bnx2_init_context(bp); bnx2_init_context(bp);
if ((rc = bnx2_init_cpus(bp)) != 0) if ((rc = bnx2_init_cpus(bp)) != 0)
@ -3772,7 +3788,10 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_HC_CMD_TICKS, REG_WR(bp, BNX2_HC_CMD_TICKS,
(bp->cmd_ticks_int << 16) | bp->cmd_ticks); (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00); if (CHIP_NUM(bp) == CHIP_NUM_5708)
REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
else
REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
if (CHIP_ID(bp) == CHIP_ID_5706_A1) if (CHIP_ID(bp) == CHIP_ID_5706_A1)
@ -3799,6 +3818,11 @@ bnx2_init_chip(struct bnx2 *bp)
/* Initialize the receive filter. */ /* Initialize the receive filter. */
bnx2_set_rx_mode(bp->dev); bnx2_set_rx_mode(bp->dev);
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
}
rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
0); 0);
@ -4620,6 +4644,11 @@ bnx2_timer(unsigned long data)
bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
/* workaround occasional corrupted counters */
if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
BNX2_HC_COMMAND_STATS_NOW);
if (bp->phy_flags & PHY_SERDES_FLAG) { if (bp->phy_flags & PHY_SERDES_FLAG) {
if (CHIP_NUM(bp) == CHIP_NUM_5706) if (CHIP_NUM(bp) == CHIP_NUM_5706)
bnx2_5706_serdes_timer(bp); bnx2_5706_serdes_timer(bp);
@ -5417,6 +5446,10 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
0xff; 0xff;
bp->stats_ticks = coal->stats_block_coalesce_usecs; bp->stats_ticks = coal->stats_block_coalesce_usecs;
if (CHIP_NUM(bp) == CHIP_NUM_5708) {
if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
bp->stats_ticks = USEC_PER_SEC;
}
if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00; if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00;
bp->stats_ticks &= 0xffff00; bp->stats_ticks &= 0xffff00;

Просмотреть файл

@ -1373,6 +1373,7 @@ struct l2_fhdr {
#define BNX2_MISC_NEW_CORE_CTL 0x000008c8 #define BNX2_MISC_NEW_CORE_CTL 0x000008c8
#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0) #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0)
#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1) #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1)
#define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE (1L<<16)
#define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2) #define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2)
#define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16) #define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16)

Просмотреть файл

@ -3,6 +3,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/bitmap.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
@ -10,28 +11,9 @@
struct ipv4_devconf struct ipv4_devconf
{ {
int accept_redirects;
int send_redirects;
int secure_redirects;
int shared_media;
int accept_source_route;
int rp_filter;
int proxy_arp;
int bootp_relay;
int log_martians;
int forwarding;
int mc_forwarding;
int tag;
int arp_filter;
int arp_announce;
int arp_ignore;
int arp_accept;
int medium_id;
int no_xfrm;
int no_policy;
int force_igmp_version;
int promote_secondaries;
void *sysctl; void *sysctl;
int data[__NET_IPV4_CONF_MAX - 1];
DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
}; };
extern struct ipv4_devconf ipv4_devconf; extern struct ipv4_devconf ipv4_devconf;
@ -60,30 +42,70 @@ struct in_device
struct rcu_head rcu_head; struct rcu_head rcu_head;
}; };
#define IN_DEV_FORWARD(in_dev) ((in_dev)->cnf.forwarding) #define IPV4_DEVCONF(cnf, attr) ((cnf).data[NET_IPV4_CONF_ ## attr - 1])
#define IN_DEV_MFORWARD(in_dev) (ipv4_devconf.mc_forwarding && (in_dev)->cnf.mc_forwarding) #define IPV4_DEVCONF_ALL(attr) IPV4_DEVCONF(ipv4_devconf, attr)
#define IN_DEV_RPFILTER(in_dev) (ipv4_devconf.rp_filter && (in_dev)->cnf.rp_filter)
#define IN_DEV_SOURCE_ROUTE(in_dev) (ipv4_devconf.accept_source_route && (in_dev)->cnf.accept_source_route)
#define IN_DEV_BOOTP_RELAY(in_dev) (ipv4_devconf.bootp_relay && (in_dev)->cnf.bootp_relay)
#define IN_DEV_LOG_MARTIANS(in_dev) (ipv4_devconf.log_martians || (in_dev)->cnf.log_martians) static inline int ipv4_devconf_get(struct in_device *in_dev, int index)
#define IN_DEV_PROXY_ARP(in_dev) (ipv4_devconf.proxy_arp || (in_dev)->cnf.proxy_arp) {
#define IN_DEV_SHARED_MEDIA(in_dev) (ipv4_devconf.shared_media || (in_dev)->cnf.shared_media) index--;
#define IN_DEV_TX_REDIRECTS(in_dev) (ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects) return in_dev->cnf.data[index];
#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects) }
#define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag)
#define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id) static inline void ipv4_devconf_set(struct in_device *in_dev, int index,
#define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries) int val)
{
index--;
set_bit(index, in_dev->cnf.state);
in_dev->cnf.data[index] = val;
}
static inline void ipv4_devconf_setall(struct in_device *in_dev)
{
bitmap_fill(in_dev->cnf.state, __NET_IPV4_CONF_MAX - 1);
}
#define IN_DEV_CONF_GET(in_dev, attr) \
ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr)
#define IN_DEV_CONF_SET(in_dev, attr, val) \
ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
#define IN_DEV_ANDCONF(in_dev, attr) \
(IPV4_DEVCONF_ALL(attr) && IN_DEV_CONF_GET((in_dev), attr))
#define IN_DEV_ORCONF(in_dev, attr) \
(IPV4_DEVCONF_ALL(attr) || IN_DEV_CONF_GET((in_dev), attr))
#define IN_DEV_MAXCONF(in_dev, attr) \
(max(IPV4_DEVCONF_ALL(attr), IN_DEV_CONF_GET((in_dev), attr)))
#define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING)
#define IN_DEV_MFORWARD(in_dev) (IPV4_DEVCONF_ALL(MC_FORWARDING) && \
IPV4_DEVCONF((in_dev)->cnf, \
MC_FORWARDING))
#define IN_DEV_RPFILTER(in_dev) IN_DEV_ANDCONF((in_dev), RP_FILTER)
#define IN_DEV_SOURCE_ROUTE(in_dev) IN_DEV_ANDCONF((in_dev), \
ACCEPT_SOURCE_ROUTE)
#define IN_DEV_BOOTP_RELAY(in_dev) IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
#define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS)
#define IN_DEV_PROXY_ARP(in_dev) IN_DEV_ORCONF((in_dev), PROXY_ARP)
#define IN_DEV_SHARED_MEDIA(in_dev) IN_DEV_ORCONF((in_dev), SHARED_MEDIA)
#define IN_DEV_TX_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), SEND_REDIRECTS)
#define IN_DEV_SEC_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), \
SECURE_REDIRECTS)
#define IN_DEV_IDTAG(in_dev) IN_DEV_CONF_GET(in_dev, TAG)
#define IN_DEV_MEDIUM_ID(in_dev) IN_DEV_CONF_GET(in_dev, MEDIUM_ID)
#define IN_DEV_PROMOTE_SECONDARIES(in_dev) \
IN_DEV_ORCONF((in_dev), \
PROMOTE_SECONDARIES)
#define IN_DEV_RX_REDIRECTS(in_dev) \ #define IN_DEV_RX_REDIRECTS(in_dev) \
((IN_DEV_FORWARD(in_dev) && \ ((IN_DEV_FORWARD(in_dev) && \
(ipv4_devconf.accept_redirects && (in_dev)->cnf.accept_redirects)) \ IN_DEV_ANDCONF((in_dev), ACCEPT_REDIRECTS)) \
|| (!IN_DEV_FORWARD(in_dev) && \ || (!IN_DEV_FORWARD(in_dev) && \
(ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects))) IN_DEV_ORCONF((in_dev), ACCEPT_REDIRECTS)))
#define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter) #define IN_DEV_ARPFILTER(in_dev) IN_DEV_ORCONF((in_dev), ARPFILTER)
#define IN_DEV_ARP_ANNOUNCE(in_dev) (max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce)) #define IN_DEV_ARP_ANNOUNCE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
#define IN_DEV_ARP_IGNORE(in_dev) (max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore)) #define IN_DEV_ARP_IGNORE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
struct in_ifaddr struct in_ifaddr
{ {
@ -108,7 +130,6 @@ extern struct net_device *ip_dev_find(__be32 addr);
extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
extern int devinet_ioctl(unsigned int cmd, void __user *); extern int devinet_ioctl(unsigned int cmd, void __user *);
extern void devinet_init(void); extern void devinet_init(void);
extern struct in_device *inetdev_init(struct net_device *dev);
extern struct in_device *inetdev_by_index(int); extern struct in_device *inetdev_by_index(int);
extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
extern __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope); extern __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);

Просмотреть файл

@ -264,6 +264,26 @@ ipt_get_target(struct ipt_entry *e)
__ret; \ __ret; \
}) })
/* fn returns 0 to continue iteration */
#define IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
({ \
unsigned int __i, __n; \
int __ret = 0; \
struct ipt_entry *__entry; \
\
for (__i = 0, __n = 0; __i < (size); \
__i += __entry->next_offset, __n++) { \
__entry = (void *)(entries) + __i; \
if (__n < n) \
continue; \
\
__ret = fn(__entry , ## args); \
if (__ret != 0) \
break; \
} \
__ret; \
})
/* /*
* Main firewall chains definitions and global var's definitions. * Main firewall chains definitions and global var's definitions.
*/ */

Просмотреть файл

@ -63,7 +63,7 @@ enum rfkill_state {
* This structure represents a RF switch located on a network device. * This structure represents a RF switch located on a network device.
*/ */
struct rfkill { struct rfkill {
char *name; const char *name;
enum rfkill_type type; enum rfkill_type type;
enum rfkill_state state; enum rfkill_state state;

Просмотреть файл

@ -64,7 +64,7 @@ struct fib_rules_ops
void (*flush_cache)(void); void (*flush_cache)(void);
int nlgroup; int nlgroup;
struct nla_policy *policy; const struct nla_policy *policy;
struct list_head *rules_list; struct list_head *rules_list;
struct module *owner; struct module *owner;
}; };

Просмотреть файл

@ -60,7 +60,7 @@ struct genl_ops
{ {
u8 cmd; u8 cmd;
unsigned int flags; unsigned int flags;
struct nla_policy *policy; const struct nla_policy *policy;
int (*doit)(struct sk_buff *skb, int (*doit)(struct sk_buff *skb,
struct genl_info *info); struct genl_info *info);
int (*dumpit)(struct sk_buff *skb, int (*dumpit)(struct sk_buff *skb,

Просмотреть файл

@ -143,6 +143,7 @@ struct ip_reply_arg {
__wsum csum; __wsum csum;
int csumoffset; /* u16 offset of csum in iov[0].iov_base */ int csumoffset; /* u16 offset of csum in iov[0].iov_base */
/* -1 if not needed */ /* -1 if not needed */
int bound_dev_if;
}; };
void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,

Просмотреть файл

@ -213,7 +213,7 @@ extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
#endif /* CONFIG_IP_MULTIPLE_TABLES */ #endif /* CONFIG_IP_MULTIPLE_TABLES */
/* Exported by fib_frontend.c */ /* Exported by fib_frontend.c */
extern struct nla_policy rtm_ipv4_policy[]; extern const struct nla_policy rtm_ipv4_policy[];
extern void ip_fib_init(void); extern void ip_fib_init(void);
extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
struct net_device *dev, __be32 *spec_dst, u32 *itag); struct net_device *dev, __be32 *spec_dst, u32 *itag);

Просмотреть файл

@ -222,10 +222,10 @@ extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb,
gfp_t flags); gfp_t flags);
extern int nla_validate(struct nlattr *head, int len, int maxtype, extern int nla_validate(struct nlattr *head, int len, int maxtype,
struct nla_policy *policy); const struct nla_policy *policy);
extern int nla_parse(struct nlattr *tb[], int maxtype, extern int nla_parse(struct nlattr *tb[], int maxtype,
struct nlattr *head, int len, struct nlattr *head, int len,
struct nla_policy *policy); const struct nla_policy *policy);
extern struct nlattr * nla_find(struct nlattr *head, int len, int attrtype); extern struct nlattr * nla_find(struct nlattr *head, int len, int attrtype);
extern size_t nla_strlcpy(char *dst, const struct nlattr *nla, extern size_t nla_strlcpy(char *dst, const struct nlattr *nla,
size_t dstsize); size_t dstsize);
@ -360,7 +360,7 @@ static inline struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
*/ */
static inline int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, static inline int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen,
struct nlattr *tb[], int maxtype, struct nlattr *tb[], int maxtype,
struct nla_policy *policy) const struct nla_policy *policy)
{ {
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return -EINVAL; return -EINVAL;
@ -392,7 +392,7 @@ static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh,
* @policy: validation policy * @policy: validation policy
*/ */
static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
struct nla_policy *policy) const struct nla_policy *policy)
{ {
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return -EINVAL; return -EINVAL;
@ -729,7 +729,7 @@ static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype)
*/ */
static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
struct nlattr *nla, struct nlattr *nla,
struct nla_policy *policy) const struct nla_policy *policy)
{ {
return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
} }
@ -990,7 +990,7 @@ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
* Returns 0 on success or a negative error code. * Returns 0 on success or a negative error code.
*/ */
static inline int nla_validate_nested(struct nlattr *start, int maxtype, static inline int nla_validate_nested(struct nlattr *start, int maxtype,
struct nla_policy *policy) const struct nla_policy *policy)
{ {
return nla_validate(nla_data(start), nla_len(start), maxtype, policy); return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
} }

Просмотреть файл

@ -119,16 +119,9 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
} }
struct udp_get_port_ops {
int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
int (*saddr_any)(const struct sock *sk);
unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
const struct sock *sk);
};
/* net/ipv4/udp.c */ /* net/ipv4/udp.c */
extern int udp_get_port(struct sock *sk, unsigned short snum, extern int udp_get_port(struct sock *sk, unsigned short snum,
const struct udp_get_port_ops *ops); int (*saddr_cmp)(const struct sock *, const struct sock *));
extern void udp_err(struct sk_buff *, u32); extern void udp_err(struct sk_buff *, u32);
extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,

Просмотреть файл

@ -120,5 +120,5 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
extern void udplite4_register(void); extern void udplite4_register(void);
extern int udplite_get_port(struct sock *sk, unsigned short snum, extern int udplite_get_port(struct sock *sk, unsigned short snum,
const struct udp_get_port_ops *ops); int (*scmp)(const struct sock *, const struct sock *));
#endif /* _UDPLITE_H */ #endif /* _UDPLITE_H */

Просмотреть файл

@ -964,7 +964,7 @@ struct xfrmk_spdinfo {
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x); extern int xfrm_state_delete(struct xfrm_state *x);
extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info); extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si); extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si); extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq); extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
@ -1020,13 +1020,13 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
struct xfrm_sec_ctx *ctx, int delete, struct xfrm_sec_ctx *ctx, int delete,
int *err); int *err);
struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err);
void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void); u32 xfrm_get_acqseq(void);
void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi); void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
xfrm_address_t *daddr, xfrm_address_t *saddr, xfrm_address_t *daddr, xfrm_address_t *saddr,
int create, unsigned short family); int create, unsigned short family);
extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); extern int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
struct flowi *fl, int family, int strict); struct flowi *fl, int family, int strict);

Просмотреть файл

@ -2577,7 +2577,7 @@ unsigned dev_get_flags(const struct net_device *dev)
int dev_change_flags(struct net_device *dev, unsigned flags) int dev_change_flags(struct net_device *dev, unsigned flags)
{ {
int ret; int ret, changes;
int old_flags = dev->flags; int old_flags = dev->flags;
/* /*
@ -2632,8 +2632,10 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
dev_set_allmulti(dev, inc); dev_set_allmulti(dev, inc);
} }
if (old_flags ^ dev->flags) /* Exclude state transition flags, already notified */
rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags ^ dev->flags); changes = (old_flags ^ dev->flags) & ~(IFF_UP | IFF_RUNNING);
if (changes)
rtmsg_ifinfo(RTM_NEWLINK, dev, changes);
return ret; return ret;
} }

Просмотреть файл

@ -111,13 +111,7 @@ out:
spin_unlock(&dst_lock); spin_unlock(&dst_lock);
} }
static int dst_discard_in(struct sk_buff *skb) static int dst_discard(struct sk_buff *skb)
{
kfree_skb(skb);
return 0;
}
static int dst_discard_out(struct sk_buff *skb)
{ {
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
@ -138,8 +132,7 @@ void * dst_alloc(struct dst_ops * ops)
dst->ops = ops; dst->ops = ops;
dst->lastuse = jiffies; dst->lastuse = jiffies;
dst->path = dst; dst->path = dst;
dst->input = dst_discard_in; dst->input = dst->output = dst_discard;
dst->output = dst_discard_out;
#if RT_CACHE_DEBUG >= 2 #if RT_CACHE_DEBUG >= 2
atomic_inc(&dst_total); atomic_inc(&dst_total);
#endif #endif
@ -153,8 +146,7 @@ static void ___dst_free(struct dst_entry * dst)
protocol module is unloaded. protocol module is unloaded.
*/ */
if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) { if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
dst->input = dst_discard_in; dst->input = dst->output = dst_discard;
dst->output = dst_discard_out;
} }
dst->obsolete = 2; dst->obsolete = 2;
} }
@ -242,8 +234,7 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
return; return;
if (!unregister) { if (!unregister) {
dst->input = dst_discard_in; dst->input = dst->output = dst_discard;
dst->output = dst_discard_out;
} else { } else {
dst->dev = &loopback_dev; dst->dev = &loopback_dev;
dev_hold(&loopback_dev); dev_hold(&loopback_dev);

Просмотреть файл

@ -1761,7 +1761,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
return NULL; return NULL;
} }
static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = { static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
[NDTA_NAME] = { .type = NLA_STRING }, [NDTA_NAME] = { .type = NLA_STRING },
[NDTA_THRESH1] = { .type = NLA_U32 }, [NDTA_THRESH1] = { .type = NLA_U32 },
[NDTA_THRESH2] = { .type = NLA_U32 }, [NDTA_THRESH2] = { .type = NLA_U32 },
@ -1770,7 +1770,7 @@ static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = {
[NDTA_PARMS] = { .type = NLA_NESTED }, [NDTA_PARMS] = { .type = NLA_NESTED },
}; };
static struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] __read_mostly = { static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
[NDTPA_IFINDEX] = { .type = NLA_U32 }, [NDTPA_IFINDEX] = { .type = NLA_U32 },
[NDTPA_QUEUE_LEN] = { .type = NLA_U32 }, [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
[NDTPA_PROXY_QLEN] = { .type = NLA_U32 }, [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },

Просмотреть файл

@ -551,7 +551,7 @@ cont:
return skb->len; return skb->len;
} }
static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = { static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
[IFLA_MTU] = { .type = NLA_U32 }, [IFLA_MTU] = { .type = NLA_U32 },
@ -580,7 +580,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = -EINVAL; err = -EINVAL;
ifm = nlmsg_data(nlh); ifm = nlmsg_data(nlh);
if (ifm->ifi_index >= 0) if (ifm->ifi_index > 0)
dev = dev_get_by_index(ifm->ifi_index); dev = dev_get_by_index(ifm->ifi_index);
else if (tb[IFLA_IFNAME]) else if (tb[IFLA_IFNAME])
dev = dev_get_by_name(ifname); dev = dev_get_by_name(ifname);
@ -672,7 +672,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
* name provided implies that a name change has been * name provided implies that a name change has been
* requested. * requested.
*/ */
if (ifm->ifi_index >= 0 && ifname[0]) { if (ifm->ifi_index > 0 && ifname[0]) {
err = dev_change_name(dev, ifname); err = dev_change_name(dev, ifname);
if (err < 0) if (err < 0)
goto errout_dev; goto errout_dev;
@ -740,7 +740,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
return err; return err;
ifm = nlmsg_data(nlh); ifm = nlmsg_data(nlh);
if (ifm->ifi_index >= 0) { if (ifm->ifi_index > 0) {
dev = dev_get_by_index(ifm->ifi_index); dev = dev_get_by_index(ifm->ifi_index);
if (dev == NULL) if (dev == NULL)
return -ENODEV; return -ENODEV;

Просмотреть файл

@ -638,7 +638,7 @@ static struct dn_dev *dn_dev_by_index(int ifindex)
return dn_dev; return dn_dev;
} }
static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = { static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
[IFA_ADDRESS] = { .type = NLA_U16 }, [IFA_ADDRESS] = { .type = NLA_U16 },
[IFA_LOCAL] = { .type = NLA_U16 }, [IFA_LOCAL] = { .type = NLA_U16 },
[IFA_LABEL] = { .type = NLA_STRING, [IFA_LABEL] = { .type = NLA_STRING,

Просмотреть файл

@ -108,7 +108,7 @@ errout:
return err; return err;
} }
static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { static const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY, FRA_GENERIC_POLICY,
}; };

Просмотреть файл

@ -877,7 +877,7 @@ static int arp_process(struct sk_buff *skb)
n = __neigh_lookup(&arp_tbl, &sip, dev, 0); n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
if (ipv4_devconf.arp_accept) { if (IPV4_DEVCONF_ALL(ARP_ACCEPT)) {
/* Unsolicited ARP is not accepted by default. /* Unsolicited ARP is not accepted by default.
It is possible, that this option should be enabled for some It is possible, that this option should be enabled for some
devices (strip is candidate) devices (strip is candidate)
@ -987,11 +987,11 @@ static int arp_req_set(struct arpreq *r, struct net_device * dev)
return 0; return 0;
} }
if (dev == NULL) { if (dev == NULL) {
ipv4_devconf.proxy_arp = 1; IPV4_DEVCONF_ALL(PROXY_ARP) = 1;
return 0; return 0;
} }
if (__in_dev_get_rtnl(dev)) { if (__in_dev_get_rtnl(dev)) {
__in_dev_get_rtnl(dev)->cnf.proxy_arp = 1; IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1);
return 0; return 0;
} }
return -ENXIO; return -ENXIO;
@ -1093,11 +1093,12 @@ static int arp_req_delete(struct arpreq *r, struct net_device * dev)
return pneigh_delete(&arp_tbl, &ip, dev); return pneigh_delete(&arp_tbl, &ip, dev);
if (mask == 0) { if (mask == 0) {
if (dev == NULL) { if (dev == NULL) {
ipv4_devconf.proxy_arp = 0; IPV4_DEVCONF_ALL(PROXY_ARP) = 0;
return 0; return 0;
} }
if (__in_dev_get_rtnl(dev)) { if (__in_dev_get_rtnl(dev)) {
__in_dev_get_rtnl(dev)->cnf.proxy_arp = 0; IN_DEV_CONF_SET(__in_dev_get_rtnl(dev),
PROXY_ARP, 0);
return 0; return 0;
} }
return -ENXIO; return -ENXIO;

Просмотреть файл

@ -64,21 +64,27 @@
#include <net/rtnetlink.h> #include <net/rtnetlink.h>
struct ipv4_devconf ipv4_devconf = { struct ipv4_devconf ipv4_devconf = {
.accept_redirects = 1, .data = {
.send_redirects = 1, [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
.secure_redirects = 1, [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
.shared_media = 1, [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
[NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
},
}; };
static struct ipv4_devconf ipv4_devconf_dflt = { static struct ipv4_devconf ipv4_devconf_dflt = {
.accept_redirects = 1, .data = {
.send_redirects = 1, [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
.secure_redirects = 1, [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
.shared_media = 1, [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
.accept_source_route = 1, [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
[NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1,
},
}; };
static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = { #define IPV4_DEVCONF_DFLT(attr) IPV4_DEVCONF(ipv4_devconf_dflt, attr)
static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
[IFA_LOCAL] = { .type = NLA_U32 }, [IFA_LOCAL] = { .type = NLA_U32 },
[IFA_ADDRESS] = { .type = NLA_U32 }, [IFA_ADDRESS] = { .type = NLA_U32 },
[IFA_BROADCAST] = { .type = NLA_U32 }, [IFA_BROADCAST] = { .type = NLA_U32 },
@ -141,7 +147,7 @@ void in_dev_finish_destroy(struct in_device *idev)
} }
} }
struct in_device *inetdev_init(struct net_device *dev) static struct in_device *inetdev_init(struct net_device *dev)
{ {
struct in_device *in_dev; struct in_device *in_dev;
@ -399,12 +405,10 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
ASSERT_RTNL(); ASSERT_RTNL();
if (!in_dev) { if (!in_dev) {
in_dev = inetdev_init(dev); inet_free_ifa(ifa);
if (!in_dev) { return -ENOBUFS;
inet_free_ifa(ifa);
return -ENOBUFS;
}
} }
ipv4_devconf_setall(in_dev);
if (ifa->ifa_dev != in_dev) { if (ifa->ifa_dev != in_dev) {
BUG_TRAP(!ifa->ifa_dev); BUG_TRAP(!ifa->ifa_dev);
in_dev_hold(in_dev); in_dev_hold(in_dev);
@ -514,13 +518,12 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
in_dev = __in_dev_get_rtnl(dev); in_dev = __in_dev_get_rtnl(dev);
if (in_dev == NULL) { if (in_dev == NULL) {
in_dev = inetdev_init(dev); err = -ENOBUFS;
if (in_dev == NULL) { goto errout;
err = -ENOBUFS;
goto errout;
}
} }
ipv4_devconf_setall(in_dev);
ifa = inet_alloc_ifa(); ifa = inet_alloc_ifa();
if (ifa == NULL) { if (ifa == NULL) {
/* /*
@ -1057,11 +1060,12 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
if (!in_dev) { if (!in_dev) {
if (event == NETDEV_REGISTER) { if (event == NETDEV_REGISTER) {
in_dev = inetdev_init(dev); in_dev = inetdev_init(dev);
if (!in_dev)
panic("devinet: Failed to create loopback\n");
if (dev == &loopback_dev) { if (dev == &loopback_dev) {
in_dev->cnf.no_xfrm = 1; if (!in_dev)
in_dev->cnf.no_policy = 1; panic("devinet: "
"Failed to create loopback\n");
IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
} }
} }
goto out; goto out;
@ -1237,66 +1241,49 @@ errout:
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
void inet_forward_change(void) static void devinet_copy_dflt_conf(int i)
{ {
struct net_device *dev; struct net_device *dev;
int on = ipv4_devconf.forwarding;
ipv4_devconf.accept_redirects = !on;
ipv4_devconf_dflt.forwarding = on;
read_lock(&dev_base_lock); read_lock(&dev_base_lock);
for_each_netdev(dev) { for_each_netdev(dev) {
struct in_device *in_dev; struct in_device *in_dev;
rcu_read_lock(); rcu_read_lock();
in_dev = __in_dev_get_rcu(dev); in_dev = __in_dev_get_rcu(dev);
if (in_dev) if (in_dev && !test_bit(i, in_dev->cnf.state))
in_dev->cnf.forwarding = on; in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
rcu_read_unlock(); rcu_read_unlock();
} }
read_unlock(&dev_base_lock); read_unlock(&dev_base_lock);
rt_cache_flush(0);
} }
static int devinet_sysctl_forward(ctl_table *ctl, int write, static int devinet_conf_proc(ctl_table *ctl, int write,
struct file* filp, void __user *buffer, struct file* filp, void __user *buffer,
size_t *lenp, loff_t *ppos) size_t *lenp, loff_t *ppos)
{ {
int *valp = ctl->data;
int val = *valp;
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && *valp != val) { if (write) {
if (valp == &ipv4_devconf.forwarding) struct ipv4_devconf *cnf = ctl->extra1;
inet_forward_change(); int i = (int *)ctl->data - cnf->data;
else if (valp != &ipv4_devconf_dflt.forwarding)
rt_cache_flush(0); set_bit(i, cnf->state);
if (cnf == &ipv4_devconf_dflt)
devinet_copy_dflt_conf(i);
} }
return ret; return ret;
} }
int ipv4_doint_and_flush(ctl_table *ctl, int write, static int devinet_conf_sysctl(ctl_table *table, int __user *name, int nlen,
struct file* filp, void __user *buffer, void __user *oldval, size_t __user *oldlenp,
size_t *lenp, loff_t *ppos) void __user *newval, size_t newlen)
{
int *valp = ctl->data;
int val = *valp;
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && *valp != val)
rt_cache_flush(0);
return ret;
}
int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{ {
struct ipv4_devconf *cnf;
int *valp = table->data; int *valp = table->data;
int new; int new;
int i;
if (!newval || !newlen) if (!newval || !newlen)
return 0; return 0;
@ -1327,10 +1314,113 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
} }
*valp = new; *valp = new;
rt_cache_flush(0);
cnf = table->extra1;
i = (int *)table->data - cnf->data;
set_bit(i, cnf->state);
if (cnf == &ipv4_devconf_dflt)
devinet_copy_dflt_conf(i);
return 1; return 1;
} }
void inet_forward_change(void)
{
struct net_device *dev;
int on = IPV4_DEVCONF_ALL(FORWARDING);
IPV4_DEVCONF_ALL(ACCEPT_REDIRECTS) = !on;
IPV4_DEVCONF_DFLT(FORWARDING) = on;
read_lock(&dev_base_lock);
for_each_netdev(dev) {
struct in_device *in_dev;
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
if (in_dev)
IN_DEV_CONF_SET(in_dev, FORWARDING, on);
rcu_read_unlock();
}
read_unlock(&dev_base_lock);
rt_cache_flush(0);
}
static int devinet_sysctl_forward(ctl_table *ctl, int write,
struct file* filp, void __user *buffer,
size_t *lenp, loff_t *ppos)
{
int *valp = ctl->data;
int val = *valp;
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && *valp != val) {
if (valp == &IPV4_DEVCONF_ALL(FORWARDING))
inet_forward_change();
else if (valp != &IPV4_DEVCONF_DFLT(FORWARDING))
rt_cache_flush(0);
}
return ret;
}
int ipv4_doint_and_flush(ctl_table *ctl, int write,
struct file* filp, void __user *buffer,
size_t *lenp, loff_t *ppos)
{
int *valp = ctl->data;
int val = *valp;
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && *valp != val)
rt_cache_flush(0);
return ret;
}
int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
newval, newlen);
if (ret == 1)
rt_cache_flush(0);
return ret;
}
#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \
{ \
.ctl_name = NET_IPV4_CONF_ ## attr, \
.procname = name, \
.data = ipv4_devconf.data + \
NET_IPV4_CONF_ ## attr - 1, \
.maxlen = sizeof(int), \
.mode = mval, \
.proc_handler = proc, \
.strategy = sysctl, \
.extra1 = &ipv4_devconf, \
}
#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \
devinet_conf_sysctl)
#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \
devinet_conf_sysctl)
#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \
DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl)
#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush, \
ipv4_doint_and_flush_strategy)
static struct devinet_sysctl_table { static struct devinet_sysctl_table {
struct ctl_table_header *sysctl_header; struct ctl_table_header *sysctl_header;
@ -1341,178 +1431,34 @@ static struct devinet_sysctl_table {
ctl_table devinet_root_dir[2]; ctl_table devinet_root_dir[2];
} devinet_sysctl = { } devinet_sysctl = {
.devinet_vars = { .devinet_vars = {
{ DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
.ctl_name = NET_IPV4_CONF_FORWARDING, devinet_sysctl_forward,
.procname = "forwarding", devinet_conf_sysctl),
.data = &ipv4_devconf.forwarding, DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
.maxlen = sizeof(int),
.mode = 0644, DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
.proc_handler = &devinet_sysctl_forward, DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
}, DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
{ DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
.ctl_name = NET_IPV4_CONF_MC_FORWARDING, DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
.procname = "mc_forwarding", DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
.data = &ipv4_devconf.mc_forwarding, "accept_source_route"),
.maxlen = sizeof(int), DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
.mode = 0444, DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
.proc_handler = &proc_dointvec, DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
}, DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
{ DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
.ctl_name = NET_IPV4_CONF_ACCEPT_REDIRECTS, DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
.procname = "accept_redirects", DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
.data = &ipv4_devconf.accept_redirects, DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
.maxlen = sizeof(int), DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
.mode = 0644,
.proc_handler = &proc_dointvec, DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
}, DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
{ DEVINET_SYSCTL_FLUSHING_ENTRY(FORCE_IGMP_VERSION,
.ctl_name = NET_IPV4_CONF_SECURE_REDIRECTS, "force_igmp_version"),
.procname = "secure_redirects", DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
.data = &ipv4_devconf.secure_redirects, "promote_secondaries"),
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_SHARED_MEDIA,
.procname = "shared_media",
.data = &ipv4_devconf.shared_media,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_RP_FILTER,
.procname = "rp_filter",
.data = &ipv4_devconf.rp_filter,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_SEND_REDIRECTS,
.procname = "send_redirects",
.data = &ipv4_devconf.send_redirects,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE,
.procname = "accept_source_route",
.data = &ipv4_devconf.accept_source_route,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_PROXY_ARP,
.procname = "proxy_arp",
.data = &ipv4_devconf.proxy_arp,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_MEDIUM_ID,
.procname = "medium_id",
.data = &ipv4_devconf.medium_id,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_BOOTP_RELAY,
.procname = "bootp_relay",
.data = &ipv4_devconf.bootp_relay,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_LOG_MARTIANS,
.procname = "log_martians",
.data = &ipv4_devconf.log_martians,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_TAG,
.procname = "tag",
.data = &ipv4_devconf.tag,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_ARPFILTER,
.procname = "arp_filter",
.data = &ipv4_devconf.arp_filter,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_ARP_ANNOUNCE,
.procname = "arp_announce",
.data = &ipv4_devconf.arp_announce,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_ARP_IGNORE,
.procname = "arp_ignore",
.data = &ipv4_devconf.arp_ignore,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_ARP_ACCEPT,
.procname = "arp_accept",
.data = &ipv4_devconf.arp_accept,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_CONF_NOXFRM,
.procname = "disable_xfrm",
.data = &ipv4_devconf.no_xfrm,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_doint_and_flush,
.strategy = &ipv4_doint_and_flush_strategy,
},
{
.ctl_name = NET_IPV4_CONF_NOPOLICY,
.procname = "disable_policy",
.data = &ipv4_devconf.no_policy,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_doint_and_flush,
.strategy = &ipv4_doint_and_flush_strategy,
},
{
.ctl_name = NET_IPV4_CONF_FORCE_IGMP_VERSION,
.procname = "force_igmp_version",
.data = &ipv4_devconf.force_igmp_version,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_doint_and_flush,
.strategy = &ipv4_doint_and_flush_strategy,
},
{
.ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES,
.procname = "promote_secondaries",
.data = &ipv4_devconf.promote_secondaries,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_doint_and_flush,
.strategy = &ipv4_doint_and_flush_strategy,
},
}, },
.devinet_dev = { .devinet_dev = {
{ {
@ -1561,6 +1507,7 @@ static void devinet_sysctl_register(struct in_device *in_dev,
return; return;
for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) { for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf; t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
t->devinet_vars[i].extra1 = p;
} }
if (dev) { if (dev) {

Просмотреть файл

@ -441,7 +441,7 @@ int ip_rt_ioctl(unsigned int cmd, void __user *arg)
return -EINVAL; return -EINVAL;
} }
struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = { const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = {
[RTA_DST] = { .type = NLA_U32 }, [RTA_DST] = { .type = NLA_U32 },
[RTA_SRC] = { .type = NLA_U32 }, [RTA_SRC] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 }, [RTA_IIF] = { .type = NLA_U32 },

Просмотреть файл

@ -169,7 +169,7 @@ static struct fib_table *fib_empty_table(void)
return NULL; return NULL;
} }
static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY, FRA_GENERIC_POLICY,
[FRA_FLOW] = { .type = NLA_U32 }, [FRA_FLOW] = { .type = NLA_U32 },
}; };

Просмотреть файл

@ -128,14 +128,16 @@
* contradict to specs provided this delay is small enough. * contradict to specs provided this delay is small enough.
*/ */
#define IGMP_V1_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 1 || \ #define IGMP_V1_SEEN(in_dev) \
(in_dev)->cnf.force_igmp_version == 1 || \ (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 1 || \
((in_dev)->mr_v1_seen && \ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
time_before(jiffies, (in_dev)->mr_v1_seen))) ((in_dev)->mr_v1_seen && \
#define IGMP_V2_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 2 || \ time_before(jiffies, (in_dev)->mr_v1_seen)))
(in_dev)->cnf.force_igmp_version == 2 || \ #define IGMP_V2_SEEN(in_dev) \
((in_dev)->mr_v2_seen && \ (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 2 || \
time_before(jiffies, (in_dev)->mr_v2_seen))) IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
((in_dev)->mr_v2_seen && \
time_before(jiffies, (in_dev)->mr_v2_seen)))
static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im); static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr); static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);

Просмотреть файл

@ -1352,7 +1352,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
} }
{ {
struct flowi fl = { .nl_u = { .ip4_u = struct flowi fl = { .oif = arg->bound_dev_if,
.nl_u = { .ip4_u =
{ .daddr = daddr, { .daddr = daddr,
.saddr = rt->rt_spec_dst, .saddr = rt->rt_spec_dst,
.tos = RT_TOS(ip_hdr(skb)->tos) } }, .tos = RT_TOS(ip_hdr(skb)->tos) } },
@ -1376,6 +1377,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
inet->tos = ip_hdr(skb)->tos; inet->tos = ip_hdr(skb)->tos;
sk->sk_priority = skb->priority; sk->sk_priority = skb->priority;
sk->sk_protocol = ip_hdr(skb)->protocol; sk->sk_protocol = ip_hdr(skb)->protocol;
sk->sk_bound_dev_if = arg->bound_dev_if;
ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0, ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0,
&ipc, rt, MSG_DONTWAIT); &ipc, rt, MSG_DONTWAIT);
if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {

Просмотреть файл

@ -152,9 +152,11 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v)
dev->flags |= IFF_MULTICAST; dev->flags |= IFF_MULTICAST;
in_dev = __in_dev_get_rtnl(dev); in_dev = __in_dev_get_rtnl(dev);
if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL) if (in_dev == NULL)
goto failure; goto failure;
in_dev->cnf.rp_filter = 0;
ipv4_devconf_setall(in_dev);
IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
if (dev_open(dev)) if (dev_open(dev))
goto failure; goto failure;
@ -218,10 +220,15 @@ static struct net_device *ipmr_reg_vif(void)
} }
dev->iflink = 0; dev->iflink = 0;
if ((in_dev = inetdev_init(dev)) == NULL) rcu_read_lock();
if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
rcu_read_unlock();
goto failure; goto failure;
}
in_dev->cnf.rp_filter = 0; ipv4_devconf_setall(in_dev);
IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
rcu_read_unlock();
if (dev_open(dev)) if (dev_open(dev))
goto failure; goto failure;
@ -281,7 +288,7 @@ static int vif_delete(int vifi)
dev_set_allmulti(dev, -1); dev_set_allmulti(dev, -1);
if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) {
in_dev->cnf.mc_forwarding--; IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
ip_rt_multicast_event(in_dev); ip_rt_multicast_event(in_dev);
} }
@ -426,7 +433,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
in_dev->cnf.mc_forwarding++; IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
dev_set_allmulti(dev, +1); dev_set_allmulti(dev, +1);
ip_rt_multicast_event(in_dev); ip_rt_multicast_event(in_dev);
@ -841,7 +848,7 @@ static void mrtsock_destruct(struct sock *sk)
{ {
rtnl_lock(); rtnl_lock();
if (sk == mroute_socket) { if (sk == mroute_socket) {
ipv4_devconf.mc_forwarding--; IPV4_DEVCONF_ALL(MC_FORWARDING)--;
write_lock_bh(&mrt_lock); write_lock_bh(&mrt_lock);
mroute_socket=NULL; mroute_socket=NULL;
@ -890,7 +897,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt
mroute_socket=sk; mroute_socket=sk;
write_unlock_bh(&mrt_lock); write_unlock_bh(&mrt_lock);
ipv4_devconf.mc_forwarding++; IPV4_DEVCONF_ALL(MC_FORWARDING)++;
} }
rtnl_unlock(); rtnl_unlock();
return ret; return ret;

Просмотреть файл

@ -499,7 +499,8 @@ check_entry(struct ipt_entry *e, const char *name)
} }
static inline int check_match(struct ipt_entry_match *m, const char *name, static inline int check_match(struct ipt_entry_match *m, const char *name,
const struct ipt_ip *ip, unsigned int hookmask) const struct ipt_ip *ip, unsigned int hookmask,
unsigned int *i)
{ {
struct xt_match *match; struct xt_match *match;
int ret; int ret;
@ -515,6 +516,8 @@ static inline int check_match(struct ipt_entry_match *m, const char *name,
m->u.kernel.match->name); m->u.kernel.match->name);
ret = -EINVAL; ret = -EINVAL;
} }
if (!ret)
(*i)++;
return ret; return ret;
} }
@ -537,11 +540,10 @@ find_check_match(struct ipt_entry_match *m,
} }
m->u.kernel.match = match; m->u.kernel.match = match;
ret = check_match(m, name, ip, hookmask); ret = check_match(m, name, ip, hookmask, i);
if (ret) if (ret)
goto err; goto err;
(*i)++;
return 0; return 0;
err: err:
module_put(m->u.kernel.match->me); module_put(m->u.kernel.match->me);
@ -1425,7 +1427,7 @@ out:
} }
static inline int static inline int
compat_check_calc_match(struct ipt_entry_match *m, compat_find_calc_match(struct ipt_entry_match *m,
const char *name, const char *name,
const struct ipt_ip *ip, const struct ipt_ip *ip,
unsigned int hookmask, unsigned int hookmask,
@ -1448,6 +1450,31 @@ compat_check_calc_match(struct ipt_entry_match *m,
return 0; return 0;
} }
static inline int
compat_release_match(struct ipt_entry_match *m, unsigned int *i)
{
if (i && (*i)-- == 0)
return 1;
module_put(m->u.kernel.match->me);
return 0;
}
static inline int
compat_release_entry(struct ipt_entry *e, unsigned int *i)
{
struct ipt_entry_target *t;
if (i && (*i)-- == 0)
return 1;
/* Cleanup all matches */
IPT_MATCH_ITERATE(e, compat_release_match, NULL);
t = ipt_get_target(e);
module_put(t->u.kernel.target->me);
return 0;
}
static inline int static inline int
check_compat_entry_size_and_hooks(struct ipt_entry *e, check_compat_entry_size_and_hooks(struct ipt_entry *e,
struct xt_table_info *newinfo, struct xt_table_info *newinfo,
@ -1485,10 +1512,10 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
off = 0; off = 0;
entry_offset = (void *)e - (void *)base; entry_offset = (void *)e - (void *)base;
j = 0; j = 0;
ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip, ret = IPT_MATCH_ITERATE(e, compat_find_calc_match, name, &e->ip,
e->comefrom, &off, &j); e->comefrom, &off, &j);
if (ret != 0) if (ret != 0)
goto cleanup_matches; goto release_matches;
t = ipt_get_target(e); t = ipt_get_target(e);
target = try_then_request_module(xt_find_target(AF_INET, target = try_then_request_module(xt_find_target(AF_INET,
@ -1499,7 +1526,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
t->u.user.name); t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT; ret = target ? PTR_ERR(target) : -ENOENT;
goto cleanup_matches; goto release_matches;
} }
t->u.kernel.target = target; t->u.kernel.target = target;
@ -1526,8 +1553,8 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
out: out:
module_put(t->u.kernel.target->me); module_put(t->u.kernel.target->me);
cleanup_matches: release_matches:
IPT_MATCH_ITERATE(e, cleanup_match, &j); IPT_MATCH_ITERATE(e, compat_release_match, &j);
return ret; return ret;
} }
@ -1574,15 +1601,26 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
return ret; return ret;
} }
static inline int compat_check_entry(struct ipt_entry *e, const char *name) static inline int compat_check_entry(struct ipt_entry *e, const char *name,
unsigned int *i)
{ {
int ret; int j, ret;
ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom); j = 0;
ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
if (ret) if (ret)
return ret; goto cleanup_matches;
return check_target(e, name); ret = check_target(e, name);
if (ret)
goto cleanup_matches;
(*i)++;
return 0;
cleanup_matches:
IPT_MATCH_ITERATE(e, cleanup_match, &j);
return ret;
} }
static int static int
@ -1673,10 +1711,17 @@ translate_compat_table(const char *name,
if (!mark_source_chains(newinfo, valid_hooks, entry1)) if (!mark_source_chains(newinfo, valid_hooks, entry1))
goto free_newinfo; goto free_newinfo;
i = 0;
ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
name); name, &i);
if (ret) if (ret) {
goto free_newinfo; j -= i;
IPT_ENTRY_ITERATE_CONTINUE(entry1, newinfo->size, i,
compat_release_entry, &j);
IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
xt_free_table_info(newinfo);
return ret;
}
/* And one copy for every other CPU */ /* And one copy for every other CPU */
for_each_possible_cpu(i) for_each_possible_cpu(i)
@ -1691,7 +1736,7 @@ translate_compat_table(const char *name,
free_newinfo: free_newinfo:
xt_free_table_info(newinfo); xt_free_table_info(newinfo);
out: out:
IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j); IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
return ret; return ret;
out_unlock: out_unlock:
compat_flush_offsets(); compat_flush_offsets();

Просмотреть файл

@ -133,6 +133,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
struct nf_conn *ct; struct nf_conn *ct;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn_help *help; struct nf_conn_help *help;
struct nf_conntrack_helper *helper;
/* This is where we call the helper: as the packet goes out. */ /* This is where we call the helper: as the packet goes out. */
ct = nf_ct_get(*pskb, &ctinfo); ct = nf_ct_get(*pskb, &ctinfo);
@ -140,12 +141,14 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
return NF_ACCEPT; return NF_ACCEPT;
help = nfct_help(ct); help = nfct_help(ct);
if (!help || !help->helper) if (!help)
return NF_ACCEPT; return NF_ACCEPT;
/* rcu_read_lock()ed by nf_hook_slow */
return help->helper->help(pskb, helper = rcu_dereference(help->helper);
skb_network_offset(*pskb) + ip_hdrlen(*pskb), if (!helper)
ct, ctinfo); return NF_ACCEPT;
return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb),
ct, ctinfo);
} }
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,

Просмотреть файл

@ -260,7 +260,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, " %s", snmp4_ipstats_list[i].name); seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
seq_printf(seq, "\nIp: %d %d", seq_printf(seq, "\nIp: %d %d",
ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl); IPV4_DEVCONF_ALL(FORWARDING) ? 1 : 2, sysctl_ip_default_ttl);
for (i = 0; snmp4_ipstats_list[i].name != NULL; i++) for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
seq_printf(seq, " %lu", seq_printf(seq, " %lu",

Просмотреть файл

@ -1636,7 +1636,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
atomic_set(&rth->u.dst.__refcnt, 1); atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST; rth->u.dst.flags= DST_HOST;
if (in_dev->cnf.no_policy) if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY; rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = daddr; rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr; rth->rt_dst = daddr;
@ -1778,9 +1778,9 @@ static inline int __mkroute_input(struct sk_buff *skb,
if (res->fi->fib_nhs > 1) if (res->fi->fib_nhs > 1)
rth->u.dst.flags |= DST_BALANCED; rth->u.dst.flags |= DST_BALANCED;
#endif #endif
if (in_dev->cnf.no_policy) if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY; rth->u.dst.flags |= DST_NOPOLICY;
if (out_dev->cnf.no_xfrm) if (IN_DEV_CONF_GET(out_dev, NOXFRM))
rth->u.dst.flags |= DST_NOXFRM; rth->u.dst.flags |= DST_NOXFRM;
rth->fl.fl4_dst = daddr; rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr; rth->rt_dst = daddr;
@ -2021,7 +2021,7 @@ local_input:
atomic_set(&rth->u.dst.__refcnt, 1); atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST; rth->u.dst.flags= DST_HOST;
if (in_dev->cnf.no_policy) if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY; rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = daddr; rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr; rth->rt_dst = daddr;
@ -2218,9 +2218,9 @@ static inline int __mkroute_output(struct rtable **result,
rth->u.dst.flags |= DST_BALANCED; rth->u.dst.flags |= DST_BALANCED;
} }
#endif #endif
if (in_dev->cnf.no_xfrm) if (IN_DEV_CONF_GET(in_dev, NOXFRM))
rth->u.dst.flags |= DST_NOXFRM; rth->u.dst.flags |= DST_NOXFRM;
if (in_dev->cnf.no_policy) if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY; rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = oldflp->fl4_dst; rth->fl.fl4_dst = oldflp->fl4_dst;
@ -2759,7 +2759,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
__be32 dst = rt->rt_dst; __be32 dst = rt->rt_dst;
if (MULTICAST(dst) && !LOCAL_MCAST(dst) && if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
ipv4_devconf.mc_forwarding) { IPV4_DEVCONF_ALL(MC_FORWARDING)) {
int err = ipmr_get_route(skb, r, nowait); int err = ipmr_get_route(skb, r, nowait);
if (err <= 0) { if (err <= 0) {
if (!nowait) { if (!nowait) {

Просмотреть файл

@ -37,12 +37,12 @@ static
int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp, int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos) void __user *buffer, size_t *lenp, loff_t *ppos)
{ {
int val = ipv4_devconf.forwarding; int val = IPV4_DEVCONF_ALL(FORWARDING);
int ret; int ret;
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && ipv4_devconf.forwarding != val) if (write && IPV4_DEVCONF_ALL(FORWARDING) != val)
inet_forward_change(); inet_forward_change();
return ret; return ret;
@ -222,7 +222,7 @@ ctl_table ipv4_table[] = {
{ {
.ctl_name = NET_IPV4_FORWARD, .ctl_name = NET_IPV4_FORWARD,
.procname = "ip_forward", .procname = "ip_forward",
.data = &ipv4_devconf.forwarding, .data = &IPV4_DEVCONF_ALL(FORWARDING),
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = &ipv4_sysctl_forward, .proc_handler = &ipv4_sysctl_forward,

Просмотреть файл

@ -705,6 +705,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
ip_hdr(skb)->saddr, /* XXX */ ip_hdr(skb)->saddr, /* XXX */
arg.iov[0].iov_len, IPPROTO_TCP, 0); arg.iov[0].iov_len, IPPROTO_TCP, 0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2; arg.csumoffset = offsetof(struct tcphdr, check) / 2;
if (twsk)
arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len); ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);

Просмотреть файл

@ -62,6 +62,9 @@ struct {
* Print to log with timestamps. * Print to log with timestamps.
* FIXME: causes an extra copy * FIXME: causes an extra copy
*/ */
static void printl(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
static void printl(const char *fmt, ...) static void printl(const char *fmt, ...)
{ {
va_list args; va_list args;
@ -80,8 +83,7 @@ static void printl(const char *fmt, ...)
kfifo_put(tcpw.fifo, tbuf, len); kfifo_put(tcpw.fifo, tbuf, len);
wake_up(&tcpw.wait); wake_up(&tcpw.wait);
} __attribute__ ((format (printf, 1, 2))); }
/* /*
* Hook inserted to be called before each receive packet. * Hook inserted to be called before each receive packet.

Просмотреть файл

@ -292,9 +292,9 @@ static void tcp_retransmit_timer(struct sock *sk)
* we cannot allow such beasts to hang infinitely. * we cannot allow such beasts to hang infinitely.
*/ */
#ifdef TCP_DEBUG #ifdef TCP_DEBUG
if (net_ratelimit()) { if (1) {
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n", LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
NIPQUAD(inet->daddr), ntohs(inet->dport), NIPQUAD(inet->daddr), ntohs(inet->dport),
inet->num, tp->snd_una, tp->snd_nxt); inet->num, tp->snd_una, tp->snd_nxt);
} }

Просмотреть файл

@ -114,36 +114,14 @@ DEFINE_RWLOCK(udp_hash_lock);
static int udp_port_rover; static int udp_port_rover;
/* static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
* Note about this hash function :
* Typical use is probably daddr = 0, only dport is going to vary hash
*/
static inline unsigned int udp_hash_port(__u16 port)
{
return port;
}
static inline int __udp_lib_port_inuse(unsigned int hash, int port,
const struct sock *this_sk,
struct hlist_head udptable[],
const struct udp_get_port_ops *ops)
{ {
struct sock *sk; struct sock *sk;
struct hlist_node *node; struct hlist_node *node;
struct inet_sock *inet;
sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) { sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
if (sk->sk_hash != hash) if (sk->sk_hash == num)
continue;
inet = inet_sk(sk);
if (inet->num != port)
continue;
if (this_sk) {
if (ops->saddr_cmp(sk, this_sk))
return 1;
} else if (ops->saddr_any(sk))
return 1; return 1;
}
return 0; return 0;
} }
@ -154,16 +132,16 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port,
* @snum: port number to look up * @snum: port number to look up
* @udptable: hash list table, must be of UDP_HTABLE_SIZE * @udptable: hash list table, must be of UDP_HTABLE_SIZE
* @port_rover: pointer to record of last unallocated port * @port_rover: pointer to record of last unallocated port
* @ops: AF-dependent address operations * @saddr_comp: AF-dependent comparison of bound local IP addresses
*/ */
int __udp_lib_get_port(struct sock *sk, unsigned short snum, int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover, struct hlist_head udptable[], int *port_rover,
const struct udp_get_port_ops *ops) int (*saddr_comp)(const struct sock *sk1,
const struct sock *sk2 ) )
{ {
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
struct sock *sk2; struct sock *sk2;
unsigned int hash;
int error = 1; int error = 1;
write_lock_bh(&udp_hash_lock); write_lock_bh(&udp_hash_lock);
@ -178,8 +156,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
int size; int size;
hash = ops->hash_port_and_rcv_saddr(result, sk); head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
if (hlist_empty(head)) { if (hlist_empty(head)) {
if (result > sysctl_local_port_range[1]) if (result > sysctl_local_port_range[1])
result = sysctl_local_port_range[0] + result = sysctl_local_port_range[0] +
@ -204,16 +181,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
result = sysctl_local_port_range[0] result = sysctl_local_port_range[0]
+ ((result - sysctl_local_port_range[0]) & + ((result - sysctl_local_port_range[0]) &
(UDP_HTABLE_SIZE - 1)); (UDP_HTABLE_SIZE - 1));
hash = udp_hash_port(result); if (! __udp_lib_lport_inuse(result, udptable))
if (__udp_lib_port_inuse(hash, result,
NULL, udptable, ops))
continue;
if (ops->saddr_any(sk))
break;
hash = ops->hash_port_and_rcv_saddr(result, sk);
if (! __udp_lib_port_inuse(hash, result,
sk, udptable, ops))
break; break;
} }
if (i >= (1 << 16) / UDP_HTABLE_SIZE) if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@ -221,40 +189,21 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
gotit: gotit:
*port_rover = snum = result; *port_rover = snum = result;
} else { } else {
hash = udp_hash_port(snum); head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head) sk_for_each(sk2, node, head)
if (sk2->sk_hash == hash && if (sk2->sk_hash == snum &&
sk2 != sk && sk2 != sk &&
inet_sk(sk2)->num == snum && (!sk2->sk_reuse || !sk->sk_reuse) &&
(!sk2->sk_reuse || !sk->sk_reuse) && (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && (*saddr_comp)(sk, sk2) )
ops->saddr_cmp(sk, sk2))
goto fail; goto fail;
if (!ops->saddr_any(sk)) {
hash = ops->hash_port_and_rcv_saddr(snum, sk);
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head)
if (sk2->sk_hash == hash &&
sk2 != sk &&
inet_sk(sk2)->num == snum &&
(!sk2->sk_reuse || !sk->sk_reuse) &&
(!sk2->sk_bound_dev_if ||
!sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if ==
sk->sk_bound_dev_if) &&
ops->saddr_cmp(sk, sk2))
goto fail;
}
} }
inet_sk(sk)->num = snum; inet_sk(sk)->num = snum;
sk->sk_hash = hash; sk->sk_hash = snum;
if (sk_unhashed(sk)) { if (sk_unhashed(sk)) {
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
sk_add_node(sk, head); sk_add_node(sk, head);
sock_prot_inc_use(sk->sk_prot); sock_prot_inc_use(sk->sk_prot);
} }
@ -265,12 +214,12 @@ fail:
} }
int udp_get_port(struct sock *sk, unsigned short snum, int udp_get_port(struct sock *sk, unsigned short snum,
const struct udp_get_port_ops *ops) int (*scmp)(const struct sock *, const struct sock *))
{ {
return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops); return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
} }
static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
{ {
struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
@ -279,33 +228,9 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
inet1->rcv_saddr == inet2->rcv_saddr )); inet1->rcv_saddr == inet2->rcv_saddr ));
} }
static int ipv4_rcv_saddr_any(const struct sock *sk)
{
return !inet_sk(sk)->rcv_saddr;
}
static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
{
addr ^= addr >> 16;
addr ^= addr >> 8;
return port ^ addr;
}
static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
const struct sock *sk)
{
return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
}
const struct udp_get_port_ops udp_ipv4_ops = {
.saddr_cmp = ipv4_rcv_saddr_equal,
.saddr_any = ipv4_rcv_saddr_any,
.hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
};
static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
{ {
return udp_get_port(sk, snum, &udp_ipv4_ops); return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
} }
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
@ -317,77 +242,63 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
{ {
struct sock *sk, *result = NULL; struct sock *sk, *result = NULL;
struct hlist_node *node; struct hlist_node *node;
unsigned int hash, hashwild; unsigned short hnum = ntohs(dport);
int score, best = -1, hport = ntohs(dport); int badness = -1;
hash = ipv4_hash_port_and_addr(hport, daddr);
hashwild = udp_hash_port(hport);
read_lock(&udp_hash_lock); read_lock(&udp_hash_lock);
sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
lookup:
sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) {
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
if (sk->sk_hash != hash || ipv6_only_sock(sk) || if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
inet->num != hport) int score = (sk->sk_family == PF_INET ? 1 : 0);
continue; if (inet->rcv_saddr) {
if (inet->rcv_saddr != daddr)
score = (sk->sk_family == PF_INET ? 1 : 0); continue;
if (inet->rcv_saddr) { score+=2;
if (inet->rcv_saddr != daddr) }
continue; if (inet->daddr) {
score+=2; if (inet->daddr != saddr)
} continue;
if (inet->daddr) { score+=2;
if (inet->daddr != saddr) }
continue; if (inet->dport) {
score+=2; if (inet->dport != sport)
} continue;
if (inet->dport) { score+=2;
if (inet->dport != sport) }
continue; if (sk->sk_bound_dev_if) {
score+=2; if (sk->sk_bound_dev_if != dif)
} continue;
if (sk->sk_bound_dev_if) { score+=2;
if (sk->sk_bound_dev_if != dif) }
continue; if (score == 9) {
score+=2; result = sk;
} break;
if (score == 9) { } else if (score > badness) {
result = sk; result = sk;
goto found; badness = score;
} else if (score > best) { }
result = sk;
best = score;
} }
} }
if (hash != hashwild) {
hash = hashwild;
goto lookup;
}
found:
if (result) if (result)
sock_hold(result); sock_hold(result);
read_unlock(&udp_hash_lock); read_unlock(&udp_hash_lock);
return result; return result;
} }
static inline struct sock *udp_v4_mcast_next(struct sock *sk, unsigned int hnum, static inline struct sock *udp_v4_mcast_next(struct sock *sk,
int hport, __be32 loc_addr, __be16 loc_port, __be32 loc_addr,
__be16 rmt_port, __be32 rmt_addr, __be16 rmt_port, __be32 rmt_addr,
int dif) int dif)
{ {
struct hlist_node *node; struct hlist_node *node;
struct sock *s = sk; struct sock *s = sk;
unsigned short hnum = ntohs(loc_port);
sk_for_each_from(s, node) { sk_for_each_from(s, node) {
struct inet_sock *inet = inet_sk(s); struct inet_sock *inet = inet_sk(s);
if (s->sk_hash != hnum || if (s->sk_hash != hnum ||
inet->num != hport ||
(inet->daddr && inet->daddr != rmt_addr) || (inet->daddr && inet->daddr != rmt_addr) ||
(inet->dport != rmt_port && inet->dport) || (inet->dport != rmt_port && inet->dport) ||
(inet->rcv_saddr && inet->rcv_saddr != loc_addr) || (inet->rcv_saddr && inet->rcv_saddr != loc_addr) ||
@ -1221,45 +1132,29 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
__be32 saddr, __be32 daddr, __be32 saddr, __be32 daddr,
struct hlist_head udptable[]) struct hlist_head udptable[])
{ {
struct sock *sk, *skw, *sknext; struct sock *sk;
int dif; int dif;
int hport = ntohs(uh->dest);
unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
unsigned int hashwild = udp_hash_port(hport);
dif = skb->dev->ifindex;
read_lock(&udp_hash_lock); read_lock(&udp_hash_lock);
sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
sk = sk_head(&udptable[hash & (UDP_HTABLE_SIZE - 1)]); dif = skb->dev->ifindex;
skw = sk_head(&udptable[hashwild & (UDP_HTABLE_SIZE - 1)]); sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
sk = udp_v4_mcast_next(sk, hash, hport, daddr, uh->source, saddr, dif);
if (!sk) {
hash = hashwild;
sk = udp_v4_mcast_next(skw, hash, hport, daddr, uh->source,
saddr, dif);
}
if (sk) { if (sk) {
struct sock *sknext = NULL;
do { do {
struct sk_buff *skb1 = skb; struct sk_buff *skb1 = skb;
sknext = udp_v4_mcast_next(sk_next(sk), hash, hport,
daddr, uh->source, saddr, dif); sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr,
if (!sknext && hash != hashwild) { uh->source, saddr, dif);
hash = hashwild;
sknext = udp_v4_mcast_next(skw, hash, hport,
daddr, uh->source, saddr, dif);
}
if (sknext) if (sknext)
skb1 = skb_clone(skb, GFP_ATOMIC); skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1) { if (skb1) {
int ret = udp_queue_rcv_skb(sk, skb1); int ret = udp_queue_rcv_skb(sk, skb1);
if (ret > 0) if (ret > 0)
/* /* we should probably re-process instead
* we should probably re-process * of dropping packets here. */
* instead of dropping packets here.
*/
kfree_skb(skb1); kfree_skb(skb1);
} }
sk = sknext; sk = sknext;
@ -1346,7 +1241,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
skb->dev->ifindex, udptable); skb->dev->ifindex, udptable );
if (sk != NULL) { if (sk != NULL) {
int ret = udp_queue_rcv_skb(sk, skb); int ret = udp_queue_rcv_skb(sk, skb);

Просмотреть файл

@ -5,14 +5,14 @@
#include <net/protocol.h> #include <net/protocol.h>
#include <net/inet_common.h> #include <net/inet_common.h>
extern const struct udp_get_port_ops udp_ipv4_ops;
extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
extern int __udp_lib_get_port(struct sock *sk, unsigned short snum, extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover, struct hlist_head udptable[], int *port_rover,
const struct udp_get_port_ops *ops); int (*)(const struct sock*,const struct sock*));
extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
extern int udp_setsockopt(struct sock *sk, int level, int optname, extern int udp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen); char __user *optval, int optlen);

Просмотреть файл

@ -19,15 +19,14 @@ struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
static int udplite_port_rover; static int udplite_port_rover;
int udplite_get_port(struct sock *sk, unsigned short p, int udplite_get_port(struct sock *sk, unsigned short p,
const struct udp_get_port_ops *ops) int (*c)(const struct sock *, const struct sock *))
{ {
return __udp_lib_get_port(sk, p, udplite_hash, return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
&udplite_port_rover, ops);
} }
static int udplite_v4_get_port(struct sock *sk, unsigned short snum) static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
{ {
return udplite_get_port(sk, snum, &udp_ipv4_ops); return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
} }
static int udplite_rcv(struct sk_buff *skb) static int udplite_rcv(struct sk_buff *skb)

Просмотреть файл

@ -2990,7 +2990,7 @@ static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
return pfx; return pfx;
} }
static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = { static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
[IFA_ADDRESS] = { .len = sizeof(struct in6_addr) }, [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
[IFA_LOCAL] = { .len = sizeof(struct in6_addr) }, [IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
[IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },

Просмотреть файл

@ -157,7 +157,7 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
return 1; return 1;
} }
static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY, FRA_GENERIC_POLICY,
}; };

Просмотреть файл

@ -160,6 +160,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
{ {
struct nf_conn *ct; struct nf_conn *ct;
struct nf_conn_help *help; struct nf_conn_help *help;
struct nf_conntrack_helper *helper;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
unsigned int ret, protoff; unsigned int ret, protoff;
unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
@ -172,7 +173,11 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
goto out; goto out;
help = nfct_help(ct); help = nfct_help(ct);
if (!help || !help->helper) if (!help)
goto out;
/* rcu_read_lock()ed by nf_hook_slow */
helper = rcu_dereference(help->helper);
if (!helper)
goto out; goto out;
protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
@ -182,7 +187,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
return NF_ACCEPT; return NF_ACCEPT;
} }
ret = help->helper->help(pskb, protoff, ct, ctinfo); ret = helper->help(pskb, protoff, ct, ctinfo);
if (ret != NF_ACCEPT) if (ret != NF_ACCEPT)
return ret; return ret;
out: out:

Просмотреть файл

@ -1999,7 +1999,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu)
fib6_clean_all(rt6_mtu_change_route, 0, &arg); fib6_clean_all(rt6_mtu_change_route, 0, &arg);
} }
static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = { static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_GATEWAY] = { .len = sizeof(struct in6_addr) }, [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) },
[RTA_OIF] = { .type = NLA_U32 }, [RTA_OIF] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 }, [RTA_IIF] = { .type = NLA_U32 },

Просмотреть файл

@ -52,28 +52,9 @@
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
static int ipv6_rcv_saddr_any(const struct sock *sk)
{
struct ipv6_pinfo *np = inet6_sk(sk);
return ipv6_addr_any(&np->rcv_saddr);
}
static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
const struct sock *sk)
{
return port;
}
const struct udp_get_port_ops udp_ipv6_ops = {
.saddr_cmp = ipv6_rcv_saddr_equal,
.saddr_any = ipv6_rcv_saddr_any,
.hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
};
static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
{ {
return udp_get_port(sk, snum, &udp_ipv6_ops); return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
} }
static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,

Просмотреть файл

@ -6,8 +6,6 @@
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/inet_common.h> #include <net/inet_common.h>
extern const struct udp_get_port_ops udp_ipv6_ops;
extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
int , int , int , __be32 , struct hlist_head []); int , int , int , __be32 , struct hlist_head []);

Просмотреть файл

@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = {
static int udplite_v6_get_port(struct sock *sk, unsigned short snum) static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
{ {
return udplite_get_port(sk, snum, &udp_ipv6_ops); return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
} }
struct proto udplitev6_prot = { struct proto udplitev6_prot = {

Просмотреть файл

@ -1682,6 +1682,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
unsigned proto; unsigned proto;
struct km_event c; struct km_event c;
struct xfrm_audit audit_info; struct xfrm_audit audit_info;
int err;
proto = pfkey_satype2proto(hdr->sadb_msg_satype); proto = pfkey_satype2proto(hdr->sadb_msg_satype);
if (proto == 0) if (proto == 0)
@ -1689,7 +1690,9 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
audit_info.loginuid = audit_get_loginuid(current->audit_context); audit_info.loginuid = audit_get_loginuid(current->audit_context);
audit_info.secid = 0; audit_info.secid = 0;
xfrm_state_flush(proto, &audit_info); err = xfrm_state_flush(proto, &audit_info);
if (err)
return err;
c.data.proto = proto; c.data.proto = proto;
c.seq = hdr->sadb_msg_seq; c.seq = hdr->sadb_msg_seq;
c.pid = hdr->sadb_msg_pid; c.pid = hdr->sadb_msg_pid;
@ -2683,10 +2686,13 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
{ {
struct km_event c; struct km_event c;
struct xfrm_audit audit_info; struct xfrm_audit audit_info;
int err;
audit_info.loginuid = audit_get_loginuid(current->audit_context); audit_info.loginuid = audit_get_loginuid(current->audit_context);
audit_info.secid = 0; audit_info.secid = 0;
xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info); err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
if (err)
return err;
c.data.type = XFRM_POLICY_TYPE_MAIN; c.data.type = XFRM_POLICY_TYPE_MAIN;
c.event = XFRM_MSG_FLUSHPOLICY; c.event = XFRM_MSG_FLUSHPOLICY;
c.pid = hdr->sadb_msg_pid; c.pid = hdr->sadb_msg_pid;

Просмотреть файл

@ -208,13 +208,14 @@ static int __init nf_conntrack_amanda_init(void)
{ {
int ret, i; int ret, i;
ret = -ENOMEM;
for (i = 0; i < ARRAY_SIZE(search); i++) { for (i = 0; i < ARRAY_SIZE(search); i++) {
search[i].ts = textsearch_prepare(ts_algo, search[i].string, search[i].ts = textsearch_prepare(ts_algo, search[i].string,
search[i].len, search[i].len,
GFP_KERNEL, TS_AUTOLOAD); GFP_KERNEL, TS_AUTOLOAD);
if (search[i].ts == NULL) if (IS_ERR(search[i].ts)) {
ret = PTR_ERR(search[i].ts);
goto err1; goto err1;
}
} }
ret = nf_conntrack_helper_register(&amanda_helper[0]); ret = nf_conntrack_helper_register(&amanda_helper[0]);
if (ret < 0) if (ret < 0)
@ -227,10 +228,9 @@ static int __init nf_conntrack_amanda_init(void)
err2: err2:
nf_conntrack_helper_unregister(&amanda_helper[0]); nf_conntrack_helper_unregister(&amanda_helper[0]);
err1: err1:
for (; i >= 0; i--) { while (--i >= 0)
if (search[i].ts) textsearch_destroy(search[i].ts);
textsearch_destroy(search[i].ts);
}
return ret; return ret;
} }

Просмотреть файл

@ -350,9 +350,15 @@ static void death_by_timeout(unsigned long ul_conntrack)
{ {
struct nf_conn *ct = (void *)ul_conntrack; struct nf_conn *ct = (void *)ul_conntrack;
struct nf_conn_help *help = nfct_help(ct); struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_helper *helper;
if (help && help->helper && help->helper->destroy) if (help) {
help->helper->destroy(ct); rcu_read_lock();
helper = rcu_dereference(help->helper);
if (helper && helper->destroy)
helper->destroy(ct);
rcu_read_unlock();
}
write_lock_bh(&nf_conntrack_lock); write_lock_bh(&nf_conntrack_lock);
/* Inside lock so preempt is disabled on module removal path. /* Inside lock so preempt is disabled on module removal path.
@ -661,6 +667,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
unsigned int dataoff) unsigned int dataoff)
{ {
struct nf_conn *conntrack; struct nf_conn *conntrack;
struct nf_conn_help *help;
struct nf_conntrack_tuple repl_tuple; struct nf_conntrack_tuple repl_tuple;
struct nf_conntrack_expect *exp; struct nf_conntrack_expect *exp;
u_int32_t features = 0; u_int32_t features = 0;
@ -691,6 +698,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
write_lock_bh(&nf_conntrack_lock); write_lock_bh(&nf_conntrack_lock);
exp = find_expectation(tuple); exp = find_expectation(tuple);
help = nfct_help(conntrack);
if (exp) { if (exp) {
DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
conntrack, exp); conntrack, exp);
@ -698,7 +706,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
__set_bit(IPS_EXPECTED_BIT, &conntrack->status); __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
conntrack->master = exp->master; conntrack->master = exp->master;
if (exp->helper) if (exp->helper)
nfct_help(conntrack)->helper = exp->helper; rcu_assign_pointer(help->helper, exp->helper);
#ifdef CONFIG_NF_CONNTRACK_MARK #ifdef CONFIG_NF_CONNTRACK_MARK
conntrack->mark = exp->master->mark; conntrack->mark = exp->master->mark;
#endif #endif
@ -708,10 +716,11 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
nf_conntrack_get(&conntrack->master->ct_general); nf_conntrack_get(&conntrack->master->ct_general);
NF_CT_STAT_INC(expect_new); NF_CT_STAT_INC(expect_new);
} else { } else {
struct nf_conn_help *help = nfct_help(conntrack); if (help) {
/* not in hash table yet, so not strictly necessary */
if (help) rcu_assign_pointer(help->helper,
help->helper = __nf_ct_helper_find(&repl_tuple); __nf_ct_helper_find(&repl_tuple));
}
NF_CT_STAT_INC(new); NF_CT_STAT_INC(new);
} }
@ -893,7 +902,8 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
helper = __nf_ct_helper_find(newreply); helper = __nf_ct_helper_find(newreply);
if (helper) if (helper)
memset(&help->help, 0, sizeof(help->help)); memset(&help->help, 0, sizeof(help->help));
help->helper = helper; /* not in hash table yet, so not strictly necessary */
rcu_assign_pointer(help->helper, helper);
} }
write_unlock_bh(&nf_conntrack_lock); write_unlock_bh(&nf_conntrack_lock);
} }

Просмотреть файл

@ -337,6 +337,10 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
NF_CT_ASSERT(master_help); NF_CT_ASSERT(master_help);
write_lock_bh(&nf_conntrack_lock); write_lock_bh(&nf_conntrack_lock);
if (!master_help->helper) {
ret = -ESHUTDOWN;
goto out;
}
list_for_each_entry(i, &nf_conntrack_expect_list, list) { list_for_each_entry(i, &nf_conntrack_expect_list, list) {
if (expect_matches(i, expect)) { if (expect_matches(i, expect)) {
/* Refresh timer: if it's dying, ignore.. */ /* Refresh timer: if it's dying, ignore.. */

Просмотреть файл

@ -93,7 +93,7 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i,
if (help && help->helper == me) { if (help && help->helper == me) {
nf_conntrack_event(IPCT_HELPER, ct); nf_conntrack_event(IPCT_HELPER, ct);
help->helper = NULL; rcu_assign_pointer(help->helper, NULL);
} }
return 0; return 0;
} }

Просмотреть файл

@ -171,21 +171,29 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
{ {
struct nfattr *nest_helper; struct nfattr *nest_helper;
const struct nf_conn_help *help = nfct_help(ct); const struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_helper *helper;
if (!help || !help->helper) if (!help)
return 0; return 0;
nest_helper = NFA_NEST(skb, CTA_HELP); rcu_read_lock();
NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name); helper = rcu_dereference(help->helper);
if (!helper)
goto out;
if (help->helper->to_nfattr) nest_helper = NFA_NEST(skb, CTA_HELP);
help->helper->to_nfattr(skb, ct); NFA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
if (helper->to_nfattr)
helper->to_nfattr(skb, ct);
NFA_NEST_END(skb, nest_helper); NFA_NEST_END(skb, nest_helper);
out:
rcu_read_unlock();
return 0; return 0;
nfattr_failure: nfattr_failure:
rcu_read_unlock();
return -1; return -1;
} }
@ -842,7 +850,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
if (help && help->helper) { if (help && help->helper) {
/* we had a helper before ... */ /* we had a helper before ... */
nf_ct_remove_expectations(ct); nf_ct_remove_expectations(ct);
help->helper = NULL; rcu_assign_pointer(help->helper, NULL);
} }
return 0; return 0;
@ -866,7 +874,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
/* need to zero data of old helper */ /* need to zero data of old helper */
memset(&help->help, 0, sizeof(help->help)); memset(&help->help, 0, sizeof(help->help));
help->helper = helper; rcu_assign_pointer(help->helper, helper);
return 0; return 0;
} }
@ -950,6 +958,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
struct nf_conn *ct; struct nf_conn *ct;
int err = -EINVAL; int err = -EINVAL;
struct nf_conn_help *help; struct nf_conn_help *help;
struct nf_conntrack_helper *helper = NULL;
ct = nf_conntrack_alloc(otuple, rtuple); ct = nf_conntrack_alloc(otuple, rtuple);
if (ct == NULL || IS_ERR(ct)) if (ct == NULL || IS_ERR(ct))
@ -980,14 +989,17 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
#endif #endif
help = nfct_help(ct); help = nfct_help(ct);
if (help) if (help) {
help->helper = nf_ct_helper_find_get(rtuple); helper = nf_ct_helper_find_get(rtuple);
/* not in hash table yet so not strictly necessary */
rcu_assign_pointer(help->helper, helper);
}
add_timer(&ct->timeout); add_timer(&ct->timeout);
nf_conntrack_hash_insert(ct); nf_conntrack_hash_insert(ct);
if (help && help->helper) if (helper)
nf_ct_helper_put(help->helper); nf_ct_helper_put(helper);
return 0; return 0;

Просмотреть файл

@ -100,7 +100,6 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conn_help *help = nfct_help(ct); struct nf_conn_help *help = nfct_help(ct);
struct nf_ct_gre_keymap **kmp, *km; struct nf_ct_gre_keymap **kmp, *km;
BUG_ON(strcmp(help->helper->name, "pptp"));
kmp = &help->help.ct_pptp_info.keymap[dir]; kmp = &help->help.ct_pptp_info.keymap[dir];
if (*kmp) { if (*kmp) {
/* check whether it's a retransmission */ /* check whether it's a retransmission */
@ -137,7 +136,6 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
enum ip_conntrack_dir dir; enum ip_conntrack_dir dir;
DEBUGP("entering for ct %p\n", ct); DEBUGP("entering for ct %p\n", ct);
BUG_ON(strcmp(help->helper->name, "pptp"));
write_lock_bh(&nf_ct_gre_lock); write_lock_bh(&nf_ct_gre_lock);
for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {

Просмотреть файл

@ -59,7 +59,7 @@ static struct genl_family netlbl_cipsov4_gnl_family = {
}; };
/* NetLabel Netlink attribute policy */ /* NetLabel Netlink attribute policy */
static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = { static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
[NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 }, [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
[NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 }, [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
[NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 }, [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },

Просмотреть файл

@ -59,7 +59,7 @@ static struct genl_family netlbl_mgmt_gnl_family = {
}; };
/* NetLabel Netlink attribute policy */ /* NetLabel Netlink attribute policy */
static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
[NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING }, [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
[NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 }, [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
[NLBL_MGMT_A_VERSION] = { .type = NLA_U32 }, [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },

Просмотреть файл

@ -61,7 +61,7 @@ static struct genl_family netlbl_unlabel_gnl_family = {
}; };
/* NetLabel Netlink attribute policy */ /* NetLabel Netlink attribute policy */
static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = { static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
[NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 }, [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
}; };

Просмотреть файл

@ -24,9 +24,9 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
}; };
static int validate_nla(struct nlattr *nla, int maxtype, static int validate_nla(struct nlattr *nla, int maxtype,
struct nla_policy *policy) const struct nla_policy *policy)
{ {
struct nla_policy *pt; const struct nla_policy *pt;
int minlen = 0, attrlen = nla_len(nla); int minlen = 0, attrlen = nla_len(nla);
if (nla->nla_type <= 0 || nla->nla_type > maxtype) if (nla->nla_type <= 0 || nla->nla_type > maxtype)
@ -99,7 +99,7 @@ static int validate_nla(struct nlattr *nla, int maxtype,
* Returns 0 on success or a negative error code. * Returns 0 on success or a negative error code.
*/ */
int nla_validate(struct nlattr *head, int len, int maxtype, int nla_validate(struct nlattr *head, int len, int maxtype,
struct nla_policy *policy) const struct nla_policy *policy)
{ {
struct nlattr *nla; struct nlattr *nla;
int rem, err; int rem, err;
@ -130,7 +130,7 @@ errout:
* Returns 0 on success or a negative error code. * Returns 0 on success or a negative error code.
*/ */
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
struct nla_policy *policy) const struct nla_policy *policy)
{ {
struct nlattr *nla; struct nlattr *nla;
int rem, err; int rem, err;

Просмотреть файл

@ -472,7 +472,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
return skb; return skb;
} }
static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = { static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
[CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING, [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
.len = GENL_NAMSIZ - 1 }, .len = GENL_NAMSIZ - 1 },

Просмотреть файл

@ -599,6 +599,7 @@ static void atm_tc_destroy(struct Qdisc *sch)
/* races ? */ /* races ? */
while ((flow = p->flows)) { while ((flow = p->flows)) {
tcf_destroy_chain(flow->filter_list); tcf_destroy_chain(flow->filter_list);
flow->filter_list = NULL;
if (flow->ref > 1) if (flow->ref > 1)
printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow,
flow->ref); flow->ref);

Просмотреть файл

@ -1748,10 +1748,12 @@ cbq_destroy(struct Qdisc* sch)
* classes from root to leafs which means that filters can still * classes from root to leafs which means that filters can still
* be bound to classes which have been destroyed already. --TGR '04 * be bound to classes which have been destroyed already. --TGR '04
*/ */
for (h = 0; h < 16; h++) for (h = 0; h < 16; h++) {
for (cl = q->classes[h]; cl; cl = cl->next) for (cl = q->classes[h]; cl; cl = cl->next) {
tcf_destroy_chain(cl->filter_list); tcf_destroy_chain(cl->filter_list);
cl->filter_list = NULL;
}
}
for (h = 0; h < 16; h++) { for (h = 0; h < 16; h++) {
struct cbq_class *next; struct cbq_class *next;

Просмотреть файл

@ -1744,20 +1744,23 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
int chunk; int chunk;
struct sk_buff *skb; struct sk_buff *skb;
unix_state_lock(sk);
skb = skb_dequeue(&sk->sk_receive_queue); skb = skb_dequeue(&sk->sk_receive_queue);
if (skb==NULL) if (skb==NULL)
{ {
if (copied >= target) if (copied >= target)
break; goto unlock;
/* /*
* POSIX 1003.1g mandates this order. * POSIX 1003.1g mandates this order.
*/ */
if ((err = sock_error(sk)) != 0) if ((err = sock_error(sk)) != 0)
break; goto unlock;
if (sk->sk_shutdown & RCV_SHUTDOWN) if (sk->sk_shutdown & RCV_SHUTDOWN)
break; goto unlock;
unix_state_unlock(sk);
err = -EAGAIN; err = -EAGAIN;
if (!timeo) if (!timeo)
break; break;
@ -1771,7 +1774,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
} }
mutex_lock(&u->readlock); mutex_lock(&u->readlock);
continue; continue;
unlock:
unix_state_unlock(sk);
break;
} }
unix_state_unlock(sk);
if (check_creds) { if (check_creds) {
/* Never glue messages from different writers */ /* Never glue messages from different writers */

Просмотреть файл

@ -834,11 +834,67 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
} }
EXPORT_SYMBOL(xfrm_policy_byid); EXPORT_SYMBOL(xfrm_policy_byid);
void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) #ifdef CONFIG_SECURITY_NETWORK_XFRM
static inline int
xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
{ {
int dir; int dir, err = 0;
for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
struct xfrm_policy *pol;
struct hlist_node *entry;
int i;
hlist_for_each_entry(pol, entry,
&xfrm_policy_inexact[dir], bydst) {
if (pol->type != type)
continue;
err = security_xfrm_policy_delete(pol);
if (err) {
xfrm_audit_log(audit_info->loginuid,
audit_info->secid,
AUDIT_MAC_IPSEC_DELSPD, 0,
pol, NULL);
return err;
}
}
for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
hlist_for_each_entry(pol, entry,
xfrm_policy_bydst[dir].table + i,
bydst) {
if (pol->type != type)
continue;
err = security_xfrm_policy_delete(pol);
if (err) {
xfrm_audit_log(audit_info->loginuid,
audit_info->secid,
AUDIT_MAC_IPSEC_DELSPD,
0, pol, NULL);
return err;
}
}
}
}
return err;
}
#else
static inline int
xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
{
return 0;
}
#endif
int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
{
int dir, err = 0;
write_lock_bh(&xfrm_policy_lock); write_lock_bh(&xfrm_policy_lock);
err = xfrm_policy_flush_secctx_check(type, audit_info);
if (err)
goto out;
for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
struct xfrm_policy *pol; struct xfrm_policy *pol;
struct hlist_node *entry; struct hlist_node *entry;
@ -891,7 +947,9 @@ void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
xfrm_policy_count[dir] -= killed; xfrm_policy_count[dir] -= killed;
} }
atomic_inc(&flow_cache_genid); atomic_inc(&flow_cache_genid);
out:
write_unlock_bh(&xfrm_policy_lock); write_unlock_bh(&xfrm_policy_lock);
return err;
} }
EXPORT_SYMBOL(xfrm_policy_flush); EXPORT_SYMBOL(xfrm_policy_flush);
@ -2583,4 +2641,3 @@ restore_state:
} }
EXPORT_SYMBOL(xfrm_migrate); EXPORT_SYMBOL(xfrm_migrate);
#endif #endif

Просмотреть файл

@ -391,12 +391,48 @@ int xfrm_state_delete(struct xfrm_state *x)
} }
EXPORT_SYMBOL(xfrm_state_delete); EXPORT_SYMBOL(xfrm_state_delete);
void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info) #ifdef CONFIG_SECURITY_NETWORK_XFRM
static inline int
xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
{ {
int i; int i, err = 0;
int err = 0;
for (i = 0; i <= xfrm_state_hmask; i++) {
struct hlist_node *entry;
struct xfrm_state *x;
hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
if (xfrm_id_proto_match(x->id.proto, proto) &&
(err = security_xfrm_state_delete(x)) != 0) {
xfrm_audit_log(audit_info->loginuid,
audit_info->secid,
AUDIT_MAC_IPSEC_DELSA,
0, NULL, x);
return err;
}
}
}
return err;
}
#else
static inline int
xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
{
return 0;
}
#endif
int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
{
int i, err = 0;
spin_lock_bh(&xfrm_state_lock); spin_lock_bh(&xfrm_state_lock);
err = xfrm_state_flush_secctx_check(proto, audit_info);
if (err)
goto out;
for (i = 0; i <= xfrm_state_hmask; i++) { for (i = 0; i <= xfrm_state_hmask; i++) {
struct hlist_node *entry; struct hlist_node *entry;
struct xfrm_state *x; struct xfrm_state *x;
@ -419,8 +455,12 @@ restart:
} }
} }
} }
err = 0;
out:
spin_unlock_bh(&xfrm_state_lock); spin_unlock_bh(&xfrm_state_lock);
wake_up(&km_waitq); wake_up(&km_waitq);
return err;
} }
EXPORT_SYMBOL(xfrm_state_flush); EXPORT_SYMBOL(xfrm_state_flush);

Просмотреть файл

@ -1418,10 +1418,13 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct km_event c; struct km_event c;
struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
struct xfrm_audit audit_info; struct xfrm_audit audit_info;
int err;
audit_info.loginuid = NETLINK_CB(skb).loginuid; audit_info.loginuid = NETLINK_CB(skb).loginuid;
audit_info.secid = NETLINK_CB(skb).sid; audit_info.secid = NETLINK_CB(skb).sid;
xfrm_state_flush(p->proto, &audit_info); err = xfrm_state_flush(p->proto, &audit_info);
if (err)
return err;
c.data.proto = p->proto; c.data.proto = p->proto;
c.event = nlh->nlmsg_type; c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq; c.seq = nlh->nlmsg_seq;
@ -1582,7 +1585,9 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
audit_info.loginuid = NETLINK_CB(skb).loginuid; audit_info.loginuid = NETLINK_CB(skb).loginuid;
audit_info.secid = NETLINK_CB(skb).sid; audit_info.secid = NETLINK_CB(skb).sid;
xfrm_policy_flush(type, &audit_info); err = xfrm_policy_flush(type, &audit_info);
if (err)
return err;
c.data.type = type; c.data.type = type;
c.event = nlh->nlmsg_type; c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq; c.seq = nlh->nlmsg_seq;