diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 21:06:29 +1100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 21:06:29 +1100 |
commit | cec03afcb62fbbb0eaf943f6349ade61b89d7d40 (patch) | |
tree | cc80c13e373337d1c1dee9dd7269173da1f7c079 | |
parent | 2da53b0134ad41b91556d2d2a322cc03487a1ab7 (diff) | |
parent | 4814bdbd590e835ecec2d5e505165ec1c19796b2 (diff) | |
download | op-kernel-dev-cec03afcb62fbbb0eaf943f6349ade61b89d7d40.zip op-kernel-dev-cec03afcb62fbbb0eaf943f6349ade61b89d7d40.tar.gz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (173 commits)
[NETNS]: Lookup in FIB semantic hashes taking into account the namespace.
[NETNS]: Add a namespace mark to fib_info.
[IPV4]: fib_sync_down rework.
[NETNS]: Process interface address manipulation routines in the namespace.
[IPV4]: Small style cleanup of the error path in rtm_to_ifaddr.
[IPV4]: Fix memory leak on error path during FIB initialization.
[NETFILTER]: Ipv6-related xt_hashlimit compilation fix.
[NET_SCHED]: Add flow classifier
[NET_SCHED]: sch_sfq: make internal queues visible as classes
[NET_SCHED]: sch_sfq: add support for external classifiers
[NET_SCHED]: Constify struct tcf_ext_map
[BLUETOOTH]: Fix bugs in previous conn add/del workqueue changes.
[TCP]: Unexport sysctl_tcp_tso_win_divisor
[IPV4]: Make struct ipv4_devconf static.
[TR] net/802/tr.c: sysctl_tr_rif_timeout static
[XFRM]: Fix statistics.
[XFRM]: Remove unused exports.
[PKT_SCHED] sch_teql.c: Duplicate IFF_BROADCAST in FMASK, remove 2nd.
[BNX2]: Fix ASYM PAUSE advertisement for remote PHY.
[IPV4] route cache: Introduce rt_genid for smooth cache invalidation
...
271 files changed, 9495 insertions, 4036 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 4413a2d..11fe51c 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1919,11 +1919,6 @@ max_size Maximum size of the routing cache. Old entries will be purged once the cache reached has this size. -max_delay, min_delay --------------------- - -Delays for flushing the routing cache. - redirect_load, redirect_number ------------------------------ diff --git a/Documentation/networking/xfrm_proc.txt b/Documentation/networking/xfrm_proc.txt index 53c1a58..d0d8baf 100644 --- a/Documentation/networking/xfrm_proc.txt +++ b/Documentation/networking/xfrm_proc.txt @@ -26,8 +26,9 @@ XfrmInStateProtoError: e.g. SA key is wrong XfrmInStateModeError: Transformation mode specific error -XfrmInSeqOutOfWindow: - Sequence out of window +XfrmInStateSeqError: + Sequence error + i.e. Sequence number is out of window XfrmInStateExpired: State is expired XfrmInStateMismatch: @@ -60,6 +61,9 @@ XfrmOutStateProtoError: Transformation protocol specific error XfrmOutStateModeError: Transformation mode specific error +XfrmOutStateSeqError: + Sequence error + i.e. Sequence number overflow XfrmOutStateExpired: State is expired XfrmOutPolBlock: diff --git a/MAINTAINERS b/MAINTAINERS index 093cf04..91082e6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4085,6 +4085,12 @@ L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained +USB WIRELESS RNDIS DRIVER (rndis_wlan) +P: Jussi Kivilinna +M: jussi.kivilinna@mbnet.fi +L: linux-wireless@vger.kernel.org +S: Maintained + USB ZC0301 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 34aebc6..8b552c6 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.7.2" -#define DRV_MODULE_RELDATE "January 21, 2008" +#define DRV_MODULE_VERSION "1.7.3" +#define DRV_MODULE_RELDATE "January 29, 2008" #define RUN_AT(x) (jiffies + (x)) @@ -266,6 +266,18 @@ bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val) } static void +bnx2_shmem_wr(struct bnx2 *bp, u32 offset, u32 val) +{ + bnx2_reg_wr_ind(bp, bp->shmem_base + offset, val); +} + +static u32 +bnx2_shmem_rd(struct bnx2 *bp, u32 offset) +{ + return (bnx2_reg_rd_ind(bp, bp->shmem_base + offset)); +} + +static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) { offset += cid_addr; @@ -685,7 +697,7 @@ bnx2_report_fw_link(struct bnx2 *bp) else fw_link_status = BNX2_LINK_STATUS_LINK_DOWN; - REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status); + bnx2_shmem_wr(bp, BNX2_LINK_STATUS, fw_link_status); } static char * @@ -980,6 +992,42 @@ bnx2_copper_linkup(struct bnx2 *bp) return 0; } +static void +bnx2_init_rx_context0(struct bnx2 *bp) +{ + u32 val, rx_cid_addr = GET_CID_ADDR(RX_CID); + + val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; + val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; + val |= 0x02 << 8; + + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + u32 lo_water, hi_water; + + if (bp->flow_ctrl & FLOW_CTRL_TX) + lo_water = BNX2_L2CTX_LO_WATER_MARK_DEFAULT; + else + lo_water = BNX2_L2CTX_LO_WATER_MARK_DIS; + if (lo_water >= bp->rx_ring_size) + lo_water = 0; + + hi_water = bp->rx_ring_size / 4; + + if (hi_water <= lo_water) + lo_water = 0; + + hi_water /= BNX2_L2CTX_HI_WATER_MARK_SCALE; + lo_water /= BNX2_L2CTX_LO_WATER_MARK_SCALE; + + if (hi_water > 0xf) + hi_water = 0xf; + else if (hi_water == 0) + lo_water = 0; + val |= lo_water | (hi_water << BNX2_L2CTX_HI_WATER_MARK_SHIFT); + } + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val); +} + static int bnx2_set_mac_link(struct bnx2 *bp) { @@ -1044,6 +1092,9 @@ bnx2_set_mac_link(struct bnx2 *bp) /* Acknowledge the interrupt. */ REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE); + if (CHIP_NUM(bp) == CHIP_NUM_5709) + bnx2_init_rx_context0(bp); + return 0; } @@ -1378,14 +1429,14 @@ bnx2_setup_remote_phy(struct bnx2 *bp, u8 port) if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP)) speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE; - if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM)) + if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_PAUSE_ASYM)) speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE; if (port == PORT_TP) speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE | BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED; - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg); + bnx2_shmem_wr(bp, BNX2_DRV_MB_ARG0, speed_arg); spin_unlock_bh(&bp->phy_lock); bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0); @@ -1530,9 +1581,9 @@ bnx2_set_default_remote_link(struct bnx2 *bp) u32 link; if (bp->phy_port == PORT_TP) - link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK); + link = bnx2_shmem_rd(bp, BNX2_RPHY_COPPER_LINK); else - link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK); + link = bnx2_shmem_rd(bp, BNX2_RPHY_SERDES_LINK); if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) { bp->req_line_speed = 0; @@ -1584,7 +1635,7 @@ bnx2_set_default_link(struct bnx2 *bp) bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); + reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG); reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { bp->autoneg = 0; @@ -1616,7 +1667,7 @@ bnx2_remote_phy_event(struct bnx2 *bp) u8 link_up = bp->link_up; u8 old_port; - msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); + msg = bnx2_shmem_rd(bp, BNX2_LINK_STATUS); if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED) bnx2_send_heart_beat(bp); @@ -1693,7 +1744,7 @@ bnx2_set_remote_link(struct bnx2 *bp) { u32 evt_code; - evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB); + evt_code = bnx2_shmem_rd(bp, BNX2_FW_EVT_CODE_MB); switch (evt_code) { case BNX2_FW_EVT_CODE_LINK_EVENT: bnx2_remote_phy_event(bp); @@ -1905,14 +1956,13 @@ bnx2_init_5708s_phy(struct bnx2 *bp) bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); } - val = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG) & + val = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG) & BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK; if (val) { u32 is_backplane; - is_backplane = REG_RD_IND(bp, bp->shmem_base + - BNX2_SHARED_HW_CFG_CONFIG); + is_backplane = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG); if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) { bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_TX_MISC); @@ -2111,13 +2161,13 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent) bp->fw_wr_seq++; msg_data |= bp->fw_wr_seq; - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); + bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data); /* wait for an acknowledgement. */ for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) { msleep(10); - val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB); + val = bnx2_shmem_rd(bp, BNX2_FW_MB); if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ)) break; @@ -2134,7 +2184,7 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent) msg_data &= ~BNX2_DRV_MSG_CODE; msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); + bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data); return -EBUSY; } @@ -2226,7 +2276,7 @@ bnx2_init_context(struct bnx2 *bp) /* Zero out the context. */ for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) - CTX_WR(bp, vcid_addr, offset, 0); + bnx2_ctx_wr(bp, vcid_addr, offset, 0); } } } @@ -2251,11 +2301,12 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) good_mbuf_cnt = 0; /* Allocate a bunch of mbufs and save the good ones in an array. */ - val = REG_RD_IND(bp, BNX2_RBUF_STATUS1); + val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1); while (val & BNX2_RBUF_STATUS1_FREE_COUNT) { - REG_WR_IND(bp, BNX2_RBUF_COMMAND, BNX2_RBUF_COMMAND_ALLOC_REQ); + bnx2_reg_wr_ind(bp, BNX2_RBUF_COMMAND, + BNX2_RBUF_COMMAND_ALLOC_REQ); - val = REG_RD_IND(bp, BNX2_RBUF_FW_BUF_ALLOC); + val = bnx2_reg_rd_ind(bp, BNX2_RBUF_FW_BUF_ALLOC); val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE; @@ -2265,7 +2316,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) good_mbuf_cnt++; } - val = REG_RD_IND(bp, BNX2_RBUF_STATUS1); + val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1); } /* Free the good ones back to the mbuf pool thus discarding @@ -2276,7 +2327,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) val = good_mbuf[good_mbuf_cnt]; val = (val << 9) | val | 1; - REG_WR_IND(bp, BNX2_RBUF_FW_BUF_FREE, val); + bnx2_reg_wr_ind(bp, BNX2_RBUF_FW_BUF_FREE, val); } kfree(good_mbuf); return 0; @@ -3151,10 +3202,10 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) int rc; /* Halt the CPU. */ - val = REG_RD_IND(bp, cpu_reg->mode); + val = bnx2_reg_rd_ind(bp, cpu_reg->mode); val |= cpu_reg->mode_value_halt; - REG_WR_IND(bp, cpu_reg->mode, val); - REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear); + bnx2_reg_wr_ind(bp, cpu_reg->mode, val); + bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear); /* Load the Text area. */ offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base); @@ -3167,7 +3218,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) return rc; for (j = 0; j < (fw->text_len / 4); j++, offset += 4) { - REG_WR_IND(bp, offset, le32_to_cpu(fw->text[j])); + bnx2_reg_wr_ind(bp, offset, le32_to_cpu(fw->text[j])); } } @@ -3177,7 +3228,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) int j; for (j = 0; j < (fw->data_len / 4); j++, offset += 4) { - REG_WR_IND(bp, offset, fw->data[j]); + bnx2_reg_wr_ind(bp, offset, fw->data[j]); } } @@ -3187,7 +3238,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) int j; for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) { - REG_WR_IND(bp, offset, 0); + bnx2_reg_wr_ind(bp, offset, 0); } } @@ -3197,7 +3248,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) int j; for (j = 0; j < (fw->bss_len/4); j++, offset += 4) { - REG_WR_IND(bp, offset, 0); + bnx2_reg_wr_ind(bp, offset, 0); } } @@ -3208,19 +3259,19 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) int j; for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) { - REG_WR_IND(bp, offset, fw->rodata[j]); + bnx2_reg_wr_ind(bp, offset, fw->rodata[j]); } } /* Clear the pre-fetch instruction. */ - REG_WR_IND(bp, cpu_reg->inst, 0); - REG_WR_IND(bp, cpu_reg->pc, fw->start_addr); + bnx2_reg_wr_ind(bp, cpu_reg->inst, 0); + bnx2_reg_wr_ind(bp, cpu_reg->pc, fw->start_addr); /* Start the CPU. */ - val = REG_RD_IND(bp, cpu_reg->mode); + val = bnx2_reg_rd_ind(bp, cpu_reg->mode); val &= ~cpu_reg->mode_value_halt; - REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear); - REG_WR_IND(bp, cpu_reg->mode, val); + bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear); + bnx2_reg_wr_ind(bp, cpu_reg->mode, val); return 0; } @@ -3833,7 +3884,7 @@ bnx2_init_nvram(struct bnx2 *bp) } get_flash_size: - val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2); + val = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG2); val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK; if (val) bp->flash_size = val; @@ -4142,14 +4193,14 @@ bnx2_init_remote_phy(struct bnx2 *bp) if (!(bp->phy_flags & BNX2_PHY_FLAG_SERDES)) return; - val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB); + val = bnx2_shmem_rd(bp, BNX2_FW_CAP_MB); if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE) return; if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) { bp->phy_flags |= BNX2_PHY_FLAG_REMOTE_PHY_CAP; - val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); + val = bnx2_shmem_rd(bp, BNX2_LINK_STATUS); if (val & BNX2_LINK_STATUS_SERDES_LINK) bp->phy_port = PORT_FIBRE; else @@ -4167,8 +4218,7 @@ bnx2_init_remote_phy(struct bnx2 *bp) } sig = BNX2_DRV_ACK_CAP_SIGNATURE | BNX2_FW_CAP_REMOTE_PHY_CAPABLE; - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB, - sig); + bnx2_shmem_wr(bp, BNX2_DRV_ACK_CAP_MB, sig); } } } @@ -4204,8 +4254,8 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) /* Deposit a driver reset signature so the firmware knows that * this is a soft reset. */ - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE, - BNX2_DRV_RESET_SIGNATURE_MAGIC); + bnx2_shmem_wr(bp, BNX2_DRV_RESET_SIGNATURE, + BNX2_DRV_RESET_SIGNATURE_MAGIC); /* Do a dummy read to force the chip to complete all current transaction * before we issue a reset. */ @@ -4438,18 +4488,21 @@ bnx2_init_chip(struct bnx2 *bp) } if (bp->flags & BNX2_FLAG_USING_MSIX) { + u32 base = ((BNX2_TX_VEC - 1) * BNX2_HC_SB_CONFIG_SIZE) + + BNX2_HC_SB_CONFIG_1; + REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR, BNX2_HC_MSIX_BIT_VECTOR_VAL); - REG_WR(bp, BNX2_HC_SB_CONFIG_1, + REG_WR(bp, base, BNX2_HC_SB_CONFIG_1_TX_TMR_MODE | BNX2_HC_SB_CONFIG_1_ONE_SHOT); - REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP_1, + REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF, (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip); - REG_WR(bp, BNX2_HC_TX_TICKS_1, + REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF, (bp->tx_ticks_int << 16) | bp->tx_ticks); val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B; @@ -4509,6 +4562,7 @@ static void bnx2_init_tx_context(struct bnx2 *bp, u32 cid) { u32 val, offset0, offset1, offset2, offset3; + u32 cid_addr = GET_CID_ADDR(cid); if (CHIP_NUM(bp) == CHIP_NUM_5709) { offset0 = BNX2_L2CTX_TYPE_XI; @@ -4522,16 +4576,16 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid) offset3 = BNX2_L2CTX_TBDR_BHADDR_LO; } val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2; - CTX_WR(bp, GET_CID_ADDR(cid), offset0, val); + bnx2_ctx_wr(bp, cid_addr, offset0, val); val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16); - CTX_WR(bp, GET_CID_ADDR(cid), offset1, val); + bnx2_ctx_wr(bp, cid_addr, offset1, val); val = (u64) bp->tx_desc_mapping >> 32; - CTX_WR(bp, GET_CID_ADDR(cid), offset2, val); + bnx2_ctx_wr(bp, cid_addr, offset2, val); val = (u64) bp->tx_desc_mapping & 0xffffffff; - CTX_WR(bp, GET_CID_ADDR(cid), offset3, val); + bnx2_ctx_wr(bp, cid_addr, offset3, val); } static void @@ -4601,36 +4655,38 @@ bnx2_init_rx_ring(struct bnx2 *bp) bnx2_init_rxbd_rings(bp->rx_desc_ring, bp->rx_desc_mapping, bp->rx_buf_use_size, bp->rx_max_ring); - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0); + bnx2_init_rx_context0(bp); + + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + val = REG_RD(bp, BNX2_MQ_MAP_L2_5); + REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM); + } + + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0); if (bp->rx_pg_ring_size) { bnx2_init_rxbd_rings(bp->rx_pg_desc_ring, bp->rx_pg_desc_mapping, PAGE_SIZE, bp->rx_max_pg_ring); val = (bp->rx_buf_use_size << 16) | PAGE_SIZE; - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val); - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY, + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val); + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY, BNX2_L2CTX_RBDC_JUMBO_KEY); val = (u64) bp->rx_pg_desc_mapping[0] >> 32; - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val); + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val); val = (u64) bp->rx_pg_desc_mapping[0] & 0xffffffff; - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val); + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val); if (CHIP_NUM(bp) == CHIP_NUM_5709) REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT); } - val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; - val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; - val |= 0x02 << 8; - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val); - val = (u64) bp->rx_desc_mapping[0] >> 32; - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val); + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val); val = (u64) bp->rx_desc_mapping[0] & 0xffffffff; - CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val); + bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val); ring_prod = prod = bnapi->rx_pg_prod; for (i = 0; i < bp->rx_pg_ring_size; i++) { @@ -5003,9 +5059,9 @@ bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size) for (offset = 0; offset < size; offset += 4) { - REG_WR_IND(bp, start + offset, test_pattern[i]); + bnx2_reg_wr_ind(bp, start + offset, test_pattern[i]); - if (REG_RD_IND(bp, start + offset) != + if (bnx2_reg_rd_ind(bp, start + offset) != test_pattern[i]) { return -ENODEV; } @@ -5315,7 +5371,7 @@ bnx2_5706_serdes_has_link(struct bnx2 *bp) bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); - if (an_dbg & MISC_SHDW_AN_DBG_NOSYNC) + if (an_dbg & (MISC_SHDW_AN_DBG_NOSYNC | MISC_SHDW_AN_DBG_RUDI_INVALID)) return 0; bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_REG1); @@ -5440,7 +5496,8 @@ bnx2_timer(unsigned long data) bnx2_send_heart_beat(bp); - bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); + bp->stats_blk->stat_FwRxDrop = + bnx2_reg_rd_ind(bp, BNX2_FW_RX_DROP_COUNT); /* workaround occasional corrupted counters */ if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks) @@ -7155,20 +7212,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bnx2_init_nvram(bp); - reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE); + reg = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_SIGNATURE); if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) == BNX2_SHM_HDR_SIGNATURE_SIG) { u32 off = PCI_FUNC(pdev->devfn) << 2; - bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0 + off); + bp->shmem_base = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_ADDR_0 + off); } else bp->shmem_base = HOST_VIEW_SHMEM_BASE; /* Get the permanent MAC address. First we need to make sure the * firmware is actually running. */ - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_SIGNATURE); + reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE); if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) != BNX2_DEV_INFO_SIGNATURE_MAGIC) { @@ -7177,7 +7234,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_unmap; } - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); + reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV); for (i = 0, j = 0; i < 3; i++) { u8 num, k, skip0; @@ -7191,7 +7248,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if (i != 2) bp->fw_version[j++] = '.'; } - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE); + reg = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE); if (reg & BNX2_PORT_FEATURE_WOL_ENABLED) bp->wol = 1; @@ -7199,34 +7256,33 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= BNX2_FLAG_ASF_ENABLE; for (i = 0; i < 30; i++) { - reg = REG_RD_IND(bp, bp->shmem_base + - BNX2_BC_STATE_CONDITION); + reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION); if (reg & BNX2_CONDITION_MFW_RUN_MASK) break; msleep(10); } } - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION); + reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION); reg &= BNX2_CONDITION_MFW_RUN_MASK; if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN && reg != BNX2_CONDITION_MFW_RUN_NONE) { int i; - u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR); + u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR); bp->fw_version[j++] = ' '; for (i = 0; i < 3; i++) { - reg = REG_RD_IND(bp, addr + i * 4); + reg = bnx2_reg_rd_ind(bp, addr + i * 4); reg = swab32(reg); memcpy(&bp->fw_version[j], ®, 4); j += 4; } } - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER); + reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_UPPER); bp->mac_addr[0] = (u8) (reg >> 8); bp->mac_addr[1] = (u8) reg; - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_LOWER); + reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_LOWER); bp->mac_addr[2] = (u8) (reg >> 24); bp->mac_addr[3] = (u8) (reg >> 16); bp->mac_addr[4] = (u8) (reg >> 8); @@ -7265,8 +7321,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->phy_port = PORT_TP; if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { bp->phy_port = PORT_FIBRE; - reg = REG_RD_IND(bp, bp->shmem_base + - BNX2_SHARED_HW_CFG_CONFIG); + reg = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG); if (!(reg & BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX)) { bp->flags |= BNX2_FLAG_NO_WOL; bp->wol = 0; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index d8e0347..3aa0364 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -348,6 +348,12 @@ struct l2_fhdr { #define BNX2_L2CTX_BD_PRE_READ 0x00000000 #define BNX2_L2CTX_CTX_SIZE 0x00000000 #define BNX2_L2CTX_CTX_TYPE 0x00000000 +#define BNX2_L2CTX_LO_WATER_MARK_DEFAULT 32 +#define BNX2_L2CTX_LO_WATER_MARK_SCALE 4 +#define BNX2_L2CTX_LO_WATER_MARK_DIS 0 +#define BNX2_L2CTX_HI_WATER_MARK_SHIFT 4 +#define BNX2_L2CTX_HI_WATER_MARK_SCALE 16 +#define BNX2_L2CTX_WATER_MARKS_MSK 0x000000ff #define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16) #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28) #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28) @@ -4494,6 +4500,9 @@ struct l2_fhdr { #define BNX2_MQ_MAP_L2_3_ENA (0x1L<<31) #define BNX2_MQ_MAP_L2_3_DEFAULT 0x82004646 +#define BNX2_MQ_MAP_L2_5 0x00003d34 +#define BNX2_MQ_MAP_L2_5_ARM (0x3L<<26) + /* * tsch_reg definition * offset: 0x4c00 @@ -5510,6 +5519,15 @@ struct l2_fhdr { #define BNX2_HC_PERIODIC_TICKS_8_HC_PERIODIC_TICKS (0xffffL<<0) #define BNX2_HC_PERIODIC_TICKS_8_HC_INT_PERIODIC_TICKS (0xffffL<<16) +#define BNX2_HC_SB_CONFIG_SIZE (BNX2_HC_SB_CONFIG_2 - BNX2_HC_SB_CONFIG_1) +#define BNX2_HC_COMP_PROD_TRIP_OFF (BNX2_HC_COMP_PROD_TRIP_1 - \ + BNX2_HC_SB_CONFIG_1) +#define BNX2_HC_COM_TICKS_OFF (BNX2_HC_COM_TICKS_1 - BNX2_HC_SB_CONFIG_1) +#define BNX2_HC_CMD_TICKS_OFF (BNX2_HC_CMD_TICKS_1 - BNX2_HC_SB_CONFIG_1) +#define BNX2_HC_TX_QUICK_CONS_TRIP_OFF (BNX2_HC_TX_QUICK_CONS_TRIP_1 - \ + BNX2_HC_SB_CONFIG_1) +#define BNX2_HC_TX_TICKS_OFF (BNX2_HC_TX_TICKS_1 - BNX2_HC_SB_CONFIG_1) + /* * txp_reg definition @@ -6346,11 +6364,12 @@ struct l2_fhdr { #define MII_BNX2_DSP_EXPAND_REG 0x0f00 #define MII_EXPAND_REG1 (MII_BNX2_DSP_EXPAND_REG | 1) #define MII_EXPAND_REG1_RUDI_C 0x20 -#define MII_EXPAND_SERDES_CTL (MII_BNX2_DSP_EXPAND_REG | 2) +#define MII_EXPAND_SERDES_CTL (MII_BNX2_DSP_EXPAND_REG | 3) #define MII_BNX2_MISC_SHADOW 0x1c #define MISC_SHDW_AN_DBG 0x6800 #define MISC_SHDW_AN_DBG_NOSYNC 0x0002 +#define MISC_SHDW_AN_DBG_RUDI_INVALID 0x0100 #define MISC_SHDW_MODE_CTL 0x7c00 #define MISC_SHDW_MODE_CTL_SIG_DET 0x0010 @@ -6395,7 +6414,7 @@ struct l2_fhdr { #define RX_COPY_THRESH 128 -#define BNX2_MISC_ENABLE_DEFAULT 0x7ffffff +#define BNX2_MISC_ENABLE_DEFAULT 0x17ffffff #define DMA_READ_CHANS 5 #define DMA_WRITE_CHANS 3 @@ -6795,9 +6814,6 @@ struct bnx2 { int irq_nvecs; }; -static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); -static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val); - #define REG_RD(bp, offset) \ readl(bp->regview + offset) @@ -6807,19 +6823,6 @@ static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val); #define REG_WR16(bp, offset, val) \ writew(val, bp->regview + offset) -#define REG_RD_IND(bp, offset) \ - bnx2_reg_rd_ind(bp, offset) - -#define REG_WR_IND(bp, offset, val) \ - bnx2_reg_wr_ind(bp, offset, val) - -/* Indirect context access. Unlike the MBQ_WR, these macros will not - * trigger a chip event. */ -static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val); - -#define CTX_WR(bp, cid_addr, offset, val) \ - bnx2_ctx_wr(bp, cid_addr, offset, val) - struct cpu_reg { u32 mode; u32 mode_value_halt; diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index c1ad4dd..3b839d4 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -2168,760 +2168,761 @@ static struct fw_info bnx2_cp_fw_06 = { }; static u8 bnx2_RXP_b06FwText[] = { - 0xec, 0x5b, 0x6d, 0x6c, 0x5c, 0x57, 0x5a, 0x7e, 0xef, 0x99, 0xb1, 0x3d, - 0x76, 0x6c, 0xe7, 0xda, 0x99, 0xa6, 0x93, 0xe2, 0x6e, 0x67, 0xec, 0x6b, - 0x7b, 0xba, 0x36, 0xe5, 0x3a, 0x4c, 0x5b, 0xaf, 0x18, 0xb6, 0xc3, 0x1d, - 0x27, 0x75, 0x77, 0x83, 0xe4, 0xb6, 0x61, 0x37, 0x82, 0xae, 0xb0, 0x66, - 0x12, 0x51, 0x84, 0x10, 0x21, 0x82, 0xaa, 0x2c, 0x5d, 0x65, 0x34, 0x76, - 0x53, 0xb7, 0x3b, 0xf1, 0x0c, 0x89, 0x4b, 0xf8, 0xd8, 0x1f, 0xee, 0xd8, - 0x4e, 0x0a, 0x9a, 0x78, 0xba, 0xcb, 0x8f, 0x5d, 0x56, 0x4d, 0x63, 0xd2, - 0x12, 0xfa, 0x03, 0x89, 0x16, 0x56, 0x50, 0x89, 0x85, 0x86, 0x24, 0xdb, - 0x14, 0x09, 0x41, 0x77, 0x01, 0x6d, 0xa1, 0x69, 0x2f, 0xcf, 0x73, 0xee, - 0xbd, 0xc9, 0xc4, 0x35, 0x6c, 0x7f, 0xf0, 0xf3, 0x1e, 0xc9, 0xba, 0xf7, - 0x9e, 0xf3, 0x9e, 0xf7, 0xbc, 0xdf, 0x1f, 0x67, 0x92, 0xdf, 0xe8, 0x96, - 0x2e, 0xf1, 0x47, 0x0f, 0xfe, 0x32, 0x87, 0x9f, 0x3c, 0x72, 0xef, 0x3d, - 0xf6, 0x3d, 0xfc, 0x8e, 0xb4, 0x49, 0x94, 0x4f, 0x43, 0xc2, 0x11, 0x8e, - 0x70, 0x84, 0x23, 0x1c, 0xe1, 0x08, 0x47, 0x38, 0xc2, 0x11, 0x8e, 0x70, - 0x84, 0x23, 0x1c, 0xe1, 0x08, 0x47, 0x38, 0xc2, 0x11, 0x8e, 0x70, 0x84, - 0x23, 0x1c, 0xe1, 0x08, 0x47, 0x38, 0xc2, 0x11, 0x8e, 0x70, 0x84, 0x23, - 0x1c, 0xe1, 0x08, 0x47, 0x38, 0xc2, 0x11, 0x8e, 0x70, 0x84, 0x23, 0x1c, - 0xe1, 0x08, 0x47, 0x38, 0xc2, 0x11, 0x8e, 0x70, 0x84, 0x23, 0x1c, 0xe1, - 0x08, 0x47, 0x38, 0xc2, 0xf1, 0xff, 0x39, 0x22, 0x22, 0x26, 0x9f, 0x3d, - 0xfe, 0x9f, 0xc4, 0x54, 0x56, 0x8e, 0x38, 0x96, 0xc4, 0x22, 0xd9, 0xd5, - 0x27, 0x8a, 0x96, 0x48, 0xae, 0x31, 0x96, 0xcc, 0xcb, 0x87, 0x6e, 0x29, - 0x1e, 0x15, 0xce, 0xdf, 0x99, 0xbd, 0x7e, 0xf4, 0xdc, 0xfd, 0xa9, 0xf7, - 0x96, 0x23, 0x12, 0x33, 0xb3, 0x6f, 0x4c, 0x98, 0x23, 0x12, 0x1b, 0xc0, - 0x9e, 0xaf, 0x8d, 0xbe, 0xbc, 0x5d, 0x7a, 0x03, 0x5c, 0x22, 0xf5, 0x4a, - 0xca, 0xde, 0x2b, 0x63, 0xe6, 0x05, 0x89, 0x4a, 0x0e, 0x67, 0x9c, 0x6e, - 0x88, 0x94, 0x2b, 0x06, 0x71, 0x48, 0xb9, 0x11, 0x93, 0x4b, 0x11, 0x42, - 0x7d, 0xcb, 0x70, 0xaa, 0x1f, 0xb9, 0xb9, 0x28, 0xce, 0xb5, 0xf0, 0xde, - 0x0c, 0xe6, 0x63, 0xa2, 0xb2, 0xa9, 0x84, 0x13, 0x99, 0x96, 0xc2, 0x92, - 0xeb, 0xce, 0xdb, 0xb7, 0x03, 0x47, 0xbf, 0xcc, 0x5b, 0xde, 0xb7, 0x63, - 0x7f, 0xda, 0x9c, 0x92, 0x1d, 0x98, 0x8b, 0x88, 0xb2, 0xee, 0xc0, 0xdf, - 0x57, 0x0d, 0x67, 0xa5, 0x5b, 0xca, 0x55, 0xc9, 0x39, 0x76, 0x0c, 0xf3, - 0x09, 0x99, 0xab, 0x26, 0x0d, 0xe7, 0xa4, 0x21, 0xc5, 0x0c, 0xde, 0x9b, - 0xae, 0x38, 0xf6, 0x47, 0xae, 0x63, 0x11, 0xff, 0x92, 0xe1, 0x9c, 0xf9, - 0xc8, 0x55, 0x96, 0x65, 0x16, 0x84, 0xdf, 0x09, 0x29, 0x37, 0x89, 0x87, - 0xef, 0xc4, 0x73, 0xc9, 0x3d, 0x37, 0x9a, 0x90, 0x6f, 0x34, 0xe3, 0xf2, - 0xf5, 0xa6, 0x29, 0x2f, 0x35, 0x07, 0xe4, 0x7c, 0xd3, 0x75, 0xbf, 0x6e, - 0xbb, 0xee, 0x1b, 0xf8, 0xfb, 0x81, 0x7d, 0x83, 0x66, 0x8c, 0x92, 0x31, - 0xd5, 0xfc, 0xc3, 0x6e, 0xe9, 0x4d, 0x25, 0x45, 0x75, 0xe3, 0xcc, 0x84, - 0xcc, 0x57, 0x2b, 0xc6, 0xc3, 0x67, 0x16, 0x8d, 0x99, 0x33, 0x35, 0x23, - 0x7f, 0x26, 0x8a, 0x39, 0x29, 0x95, 0xed, 0x17, 0x8d, 0x7c, 0x73, 0xc1, - 0x78, 0xe4, 0x4c, 0xaf, 0xa6, 0xad, 0x5c, 0xdd, 0x09, 0xda, 0xae, 0x83, - 0x26, 0xca, 0x34, 0x65, 0xfe, 0x3c, 0xc4, 0xec, 0x54, 0xc8, 0x57, 0xbb, - 0xe4, 0xe2, 0x5c, 0x77, 0x5d, 0x95, 0x75, 0x8f, 0x3a, 0x19, 0xcb, 0x2c, - 0x0b, 0xe9, 0xd3, 0x73, 0xe7, 0x23, 0xa0, 0x39, 0x2f, 0xa7, 0x41, 0x7f, - 0xb7, 0x91, 0x3f, 0x15, 0x05, 0x1d, 0x32, 0x10, 0x11, 0xee, 0x1b, 0x4e, - 0x14, 0xa4, 0x81, 0x33, 0xc4, 0x54, 0x59, 0xca, 0x11, 0x34, 0x83, 0x96, - 0x6f, 0x54, 0xc1, 0x43, 0x15, 0x3c, 0x54, 0xc9, 0x5b, 0x52, 0xce, 0x8d, - 0x06, 0xbc, 0xb9, 0xee, 0x5f, 0xdb, 0xa4, 0x3d, 0x95, 0xcc, 0xa9, 0x80, - 0x4f, 0xd7, 0xfd, 0xbe, 0x4d, 0x5e, 0xc9, 0x8f, 0xeb, 0xbe, 0x64, 0x53, - 0x86, 0xee, 0x79, 0x65, 0x55, 0xc0, 0x8b, 0x05, 0xfc, 0x94, 0xef, 0x22, - 0x78, 0x58, 0x00, 0x7f, 0xa7, 0xc1, 0x5b, 0x0d, 0x74, 0xfc, 0xa8, 0xf3, - 0x4a, 0x46, 0x7e, 0xf4, 0x86, 0xbc, 0x92, 0x94, 0x71, 0x61, 0x55, 0x41, - 0xd6, 0xdb, 0xa4, 0xb0, 0x6c, 0xca, 0xec, 0x6a, 0xb0, 0x3f, 0xd0, 0xfb, - 0x61, 0xd9, 0x57, 0xed, 0x87, 0x6c, 0x28, 0xcb, 0x94, 0x2d, 0x42, 0xbd, - 0x95, 0xd3, 0x4a, 0xc4, 0x28, 0xd8, 0x47, 0xb5, 0xbe, 0x57, 0x2d, 0xc9, - 0x15, 0x6c, 0xca, 0x51, 0x92, 0x05, 0xbb, 0x94, 0x88, 0xc2, 0xbe, 0x56, - 0xad, 0x92, 0x19, 0x15, 0xca, 0x31, 0x95, 0xf8, 0x32, 0x64, 0x79, 0xa8, - 0x22, 0xb9, 0xcf, 0x55, 0x02, 0x19, 0x7b, 0xf2, 0xfd, 0x7c, 0xe5, 0xa7, - 0x7b, 0xa4, 0x4b, 0x7d, 0xaa, 0x4d, 0x7e, 0x15, 0x7b, 0x89, 0xfb, 0x96, - 0xbd, 0xd8, 0xe7, 0xc1, 0x79, 0x7b, 0x53, 0x07, 0x44, 0x08, 0x5b, 0x1e, - 0x6a, 0xf3, 0x7c, 0xc2, 0x70, 0xac, 0x52, 0x22, 0x02, 0xb8, 0x82, 0x94, - 0x27, 0xfc, 0xb9, 0x36, 0xc7, 0xba, 0x1e, 0x99, 0xb7, 0x53, 0xc9, 0xb2, - 0x5c, 0x8f, 0x5c, 0xb4, 0xf5, 0x5c, 0xa7, 0x63, 0xb9, 0xb2, 0x06, 0xec, - 0xcf, 0xc0, 0xfe, 0x2f, 0x80, 0xa3, 0x5f, 0xae, 0xe8, 0xf9, 0x1e, 0xec, - 0x4f, 0xb7, 0x01, 0x67, 0x97, 0xa4, 0xd2, 0x75, 0xcc, 0x5f, 0xf4, 0xe6, - 0xfb, 0x3c, 0xbc, 0xe5, 0xa1, 0x2e, 0x8d, 0x5b, 0xe4, 0x45, 0x6f, 0xfe, - 0x36, 0x0f, 0x77, 0xf9, 0x6e, 0xcc, 0x03, 0xff, 0xc8, 0xf4, 0xa8, 0xa1, - 0xe7, 0x77, 0xd1, 0x7f, 0x7e, 0xa9, 0x72, 0x3d, 0xb2, 0x66, 0xbb, 0x92, - 0x9f, 0x18, 0x99, 0x1e, 0x31, 0x3c, 0x7c, 0xc7, 0xbc, 0x7d, 0x77, 0x7a, - 0xf8, 0x46, 0xa6, 0xd3, 0x86, 0x87, 0x6f, 0xb5, 0xa2, 0xf7, 0x4a, 0xa1, - 0x42, 0xd8, 0x91, 0x69, 0xcb, 0xb8, 0x53, 0x66, 0xfb, 0x46, 0xa6, 0x07, - 0x0d, 0xf5, 0xa9, 0x6d, 0x1e, 0x1f, 0xa9, 0x80, 0x86, 0x6d, 0x9a, 0x06, - 0x9e, 0xab, 0xe7, 0x87, 0x1d, 0xab, 0x7c, 0xf7, 0x36, 0x7d, 0x3e, 0xcf, - 0xd4, 0x73, 0x77, 0x93, 0x2e, 0x9e, 0x5d, 0x9c, 0xb8, 0xe5, 0xdc, 0x1f, - 0xbf, 0x29, 0x9f, 0xad, 0xce, 0xe4, 0x79, 0x12, 0x8b, 0x66, 0xa3, 0x13, - 0xf3, 0x95, 0xc3, 0xe2, 0x54, 0x93, 0x32, 0x37, 0xde, 0x29, 0xb3, 0xe6, - 0xd0, 0xec, 0x3e, 0x61, 0xac, 0x89, 0x4d, 0x14, 0x7d, 0x1d, 0xe6, 0xc5, - 0x90, 0x39, 0xf0, 0xb8, 0xaf, 0x21, 0x31, 0x03, 0xf0, 0x43, 0x8d, 0xa8, - 0x3c, 0xdb, 0x34, 0xa4, 0x5d, 0xfb, 0x67, 0xca, 0xdc, 0x80, 0x1d, 0x3e, - 0x5d, 0xa5, 0x1d, 0xd3, 0x66, 0x25, 0x57, 0x87, 0x9d, 0x9e, 0xd7, 0xbe, - 0xda, 0x45, 0xbd, 0x96, 0x4a, 0x02, 0x57, 0xcc, 0x5a, 0x66, 0x5d, 0x3a, - 0x24, 0x37, 0x23, 0x25, 0xae, 0xfb, 0xbe, 0x93, 0x58, 0x91, 0x73, 0xb0, - 0x01, 0x31, 0x9d, 0x0c, 0xe7, 0x09, 0xdf, 0x02, 0x6b, 0x7a, 0x7e, 0x17, - 0x81, 0xdf, 0x15, 0x33, 0x84, 0x95, 0x92, 0x93, 0xa1, 0xef, 0xc1, 0x16, - 0x9b, 0xbb, 0x7a, 0xbc, 0xd8, 0x86, 0xd8, 0x12, 0xef, 0x86, 0x8f, 0x7f, - 0x0a, 0xfe, 0x37, 0x60, 0x38, 0xa7, 0x5c, 0xb7, 0x68, 0x4b, 0x5c, 0x09, - 0xfd, 0x0f, 0xbe, 0xde, 0xe4, 0x5a, 0x37, 0xe6, 0xc5, 0x9c, 0xb3, 0xfb, - 0xc0, 0x9f, 0xeb, 0x4e, 0xdb, 0x49, 0x29, 0xdb, 0xdb, 0xb1, 0xaf, 0x4d, - 0xfa, 0x2c, 0xda, 0x3b, 0x7d, 0x7a, 0x1b, 0xce, 0x33, 0xf8, 0xdd, 0x8b, - 0xf3, 0x7a, 0x30, 0x97, 0x98, 0xa3, 0x1f, 0x67, 0xc6, 0xc0, 0xbf, 0x17, - 0x2f, 0x45, 0xde, 0x06, 0xad, 0xdc, 0xa3, 0xe1, 0x62, 0x1d, 0xd9, 0x8c, - 0x5c, 0xab, 0xec, 0x92, 0x4b, 0x71, 0xf2, 0x0f, 0x9c, 0x55, 0xc4, 0xc4, - 0xb8, 0x01, 0xfa, 0x13, 0x7e, 0xdc, 0xdb, 0xe1, 0x7f, 0x1b, 0x77, 0x79, - 0x67, 0x88, 0x19, 0xc9, 0xf6, 0x4a, 0x5e, 0xcf, 0x89, 0x52, 0x13, 0xdb, - 0xfc, 0xf5, 0x5e, 0x63, 0xef, 0x29, 0x25, 0xa3, 0xf7, 0x21, 0x66, 0xe1, - 0xac, 0x8b, 0x96, 0xeb, 0x5e, 0xb4, 0xbf, 0x0f, 0x9f, 0x57, 0xd2, 0x66, - 0xfd, 0x63, 0xaf, 0x74, 0x41, 0x9e, 0x55, 0xa3, 0x45, 0x86, 0x09, 0x39, - 0x56, 0xe5, 0x9e, 0x92, 0x44, 0x2d, 0xc2, 0x10, 0xfe, 0xef, 0x01, 0x17, - 0x91, 0x0e, 0xf8, 0xe2, 0x05, 0x3b, 0x4e, 0x7a, 0xb7, 0x7b, 0xf0, 0x7d, - 0x38, 0x83, 0xb4, 0xd3, 0xf7, 0x5c, 0xed, 0x7b, 0x4e, 0x44, 0xe5, 0xa6, - 0x96, 0xe0, 0x49, 0xe3, 0x94, 0xb7, 0xd3, 0x87, 0x50, 0x2f, 0x73, 0xa3, - 0x25, 0x53, 0x69, 0x5d, 0x8b, 0xe4, 0x2b, 0x77, 0xc9, 0xbc, 0x8d, 0xf3, - 0xac, 0x28, 0x68, 0x66, 0x9c, 0x19, 0x2e, 0x45, 0x14, 0x3c, 0xac, 0x9f, - 0xb2, 0x0a, 0x68, 0x7d, 0x0b, 0xe7, 0x95, 0x8c, 0xa8, 0xc5, 0x33, 0xbe, - 0xe4, 0xcb, 0x87, 0x76, 0x67, 0x8b, 0x53, 0xe9, 0xe6, 0x37, 0xe8, 0xe8, - 0xd2, 0x74, 0x44, 0xb2, 0x5a, 0x77, 0x86, 0xca, 0x52, 0x96, 0x6d, 0x3e, - 0x3d, 0xb7, 0xe0, 0x01, 0x1f, 0xdc, 0x6b, 0x61, 0x6f, 0x0c, 0x34, 0xf6, - 0xb4, 0xd0, 0xdf, 0x45, 0x78, 0xc8, 0x2a, 0xe6, 0x9f, 0xa1, 0xf9, 0x36, - 0x3c, 0xbe, 0x03, 0x59, 0x7d, 0x1b, 0xb2, 0xfa, 0xc0, 0x1d, 0xdd, 0x4d, - 0x1c, 0x19, 0xe0, 0x60, 0x1e, 0x62, 0xbc, 0x62, 0x8c, 0x32, 0x6f, 0xe0, - 0x82, 0x1f, 0xa8, 0x48, 0xb6, 0x5b, 0xf2, 0xa6, 0xce, 0x01, 0x80, 0x9d, - 0x14, 0x1d, 0xe3, 0x2d, 0xf2, 0xe8, 0x7f, 0x5b, 0x29, 0x6d, 0x37, 0x85, - 0x1a, 0xf3, 0xc0, 0x57, 0x40, 0xdb, 0x46, 0x4a, 0x69, 0xd6, 0xba, 0x21, - 0x73, 0x89, 0xb5, 0x65, 0xdf, 0x90, 0xb5, 0x8a, 0xda, 0xd9, 0x2e, 0xdb, - 0x65, 0x06, 0x32, 0xaa, 0x4f, 0x22, 0x7f, 0x8e, 0x77, 0x4b, 0xe4, 0x1e, - 0xe6, 0x81, 0x04, 0x68, 0xdd, 0x48, 0x99, 0x72, 0xdd, 0x55, 0x23, 0xd8, - 0x3f, 0x0e, 0x3d, 0xec, 0xa7, 0x4e, 0x95, 0x0f, 0x47, 0x98, 0x08, 0x65, - 0xde, 0xdf, 0x2e, 0xc4, 0xcd, 0xb5, 0xb1, 0x84, 0x29, 0x9c, 0xef, 0x84, - 0x5e, 0xb9, 0x97, 0xfc, 0x79, 0x7b, 0x3e, 0xce, 0x5f, 0xb0, 0x4e, 0x99, - 0x51, 0x76, 0xb0, 0x31, 0xf0, 0xe8, 0xd8, 0x3f, 0xeb, 0xcb, 0xe6, 0x76, - 0xb9, 0x64, 0x8a, 0x51, 0xb7, 0x6f, 0x6b, 0x91, 0x1f, 0x79, 0xee, 0xdb, - 0xc4, 0x33, 0x71, 0x6c, 0xcd, 0xf7, 0xc1, 0x1a, 0xcf, 0xf4, 0xce, 0x9e, - 0xb7, 0x36, 0x52, 0x51, 0xb9, 0x55, 0xbe, 0xd0, 0xa5, 0x14, 0x2b, 0xb4, - 0x8d, 0x76, 0x29, 0xa0, 0xfe, 0xb0, 0x77, 0x23, 0xa8, 0x3c, 0xa2, 0x64, - 0xe2, 0x3e, 0xe2, 0xfc, 0x3b, 0xf2, 0x34, 0x99, 0x54, 0x86, 0x14, 0xec, - 0xce, 0x16, 0x7d, 0x71, 0xae, 0xd5, 0xb6, 0xbf, 0xed, 0xdb, 0xf6, 0x07, - 0xee, 0xc4, 0xee, 0x40, 0xef, 0x90, 0xd7, 0xc7, 0xf6, 0x08, 0xf4, 0xfc, - 0x7f, 0xed, 0xa1, 0xad, 0xc4, 0x36, 0xed, 0x29, 0x6d, 0xb1, 0x67, 0x87, - 0xc8, 0x17, 0xe8, 0x43, 0x3d, 0x7e, 0xcc, 0x08, 0x7c, 0x2a, 0xc0, 0x03, - 0xdd, 0x68, 0x5b, 0xe5, 0xdc, 0x56, 0xbe, 0x48, 0x1c, 0xc4, 0xc5, 0xbd, - 0x84, 0x09, 0x72, 0x2a, 0xd4, 0x21, 0x5b, 0xe6, 0x55, 0x8c, 0x69, 0xbc, - 0x2b, 0xc4, 0xa1, 0xd6, 0xfc, 0xca, 0x39, 0x13, 0xdf, 0x53, 0x78, 0x5a, - 0x52, 0x68, 0xd0, 0x9f, 0xb8, 0x9f, 0xf9, 0xf6, 0x5d, 0x3f, 0x7e, 0x76, - 0xcf, 0x46, 0xb3, 0x71, 0xc4, 0x4f, 0x99, 0x29, 0x57, 0x8e, 0xba, 0x11, - 0x4b, 0x4a, 0x77, 0x64, 0x69, 0x1f, 0xdd, 0x93, 0x88, 0x91, 0x33, 0xe5, - 0x06, 0xeb, 0x22, 0x84, 0x31, 0xec, 0x43, 0x8e, 0x8e, 0xa9, 0xc5, 0x58, - 0xe9, 0xc7, 0xb2, 0x8c, 0xcb, 0x49, 0x49, 0x36, 0xde, 0x43, 0xdd, 0x61, - 0x8a, 0xa3, 0x6d, 0xed, 0xf9, 0x5d, 0xa4, 0xb7, 0x8c, 0x1a, 0x22, 0x9a, - 0x95, 0xa8, 0xca, 0xb6, 0xc7, 0xe6, 0x32, 0xdd, 0xe2, 0x64, 0xa6, 0x77, - 0xa9, 0xf5, 0x7d, 0xbb, 0x22, 0xeb, 0x3b, 0x67, 0xdb, 0xb2, 0xa5, 0x5d, - 0x6a, 0x51, 0x64, 0xa5, 0x22, 0x0a, 0x75, 0x4d, 0xe2, 0xa0, 0xe0, 0x7b, - 0xfd, 0xd1, 0x47, 0x55, 0x36, 0x02, 0xdd, 0xca, 0x53, 0xab, 0x99, 0x28, - 0x6b, 0xc6, 0xe4, 0x8c, 0x3c, 0x85, 0x3a, 0xf1, 0x49, 0x99, 0xab, 0x80, - 0x2e, 0xcd, 0x77, 0x02, 0xfc, 0x0e, 0x00, 0x37, 0x69, 0x8f, 0x23, 0xc6, - 0x7a, 0xb4, 0x83, 0xe6, 0x5c, 0x9e, 0x75, 0x52, 0x86, 0x79, 0xe5, 0x3d, - 0xd8, 0x0f, 0xfd, 0xe5, 0x5f, 0x64, 0xcd, 0xea, 0x94, 0x82, 0x17, 0x1f, - 0x68, 0xaf, 0x58, 0x7b, 0xd7, 0x5f, 0xbb, 0x8a, 0x35, 0xda, 0xef, 0xb6, - 0x16, 0x1d, 0x7e, 0x55, 0xd7, 0x3a, 0x17, 0x6d, 0xbe, 0x13, 0xf6, 0x2f, - 0x27, 0x3c, 0xd8, 0xd7, 0x27, 0xd6, 0xac, 0x47, 0xb7, 0x4b, 0x97, 0x49, - 0xbd, 0xe1, 0x9c, 0x38, 0x63, 0x2c, 0xd6, 0x2f, 0xf9, 0xb8, 0xbe, 0x0b, - 0x5c, 0xdd, 0xa4, 0x1b, 0x23, 0x8a, 0x75, 0xd0, 0x87, 0x9a, 0xa7, 0x70, - 0x23, 0xd6, 0x10, 0xf6, 0x65, 0x1f, 0xd7, 0xb7, 0x5a, 0x70, 0x71, 0x8d, - 0x4f, 0x9e, 0x89, 0xb3, 0xbb, 0xc8, 0x1b, 0xf9, 0xa1, 0x0e, 0xa8, 0x8f, - 0xb4, 0x31, 0x83, 0xd8, 0x3e, 0xd3, 0xd4, 0xb5, 0x9d, 0x91, 0xaf, 0xa2, - 0xe6, 0x6a, 0x3e, 0x0f, 0x1a, 0x59, 0xc3, 0x0e, 0xfa, 0xf5, 0x35, 0xed, - 0x68, 0x43, 0xdb, 0x23, 0xe3, 0x4e, 0x59, 0xdb, 0xd5, 0x6b, 0x9e, 0x5d, - 0x59, 0xd4, 0xcd, 0x6b, 0x32, 0xd8, 0xa8, 0x6c, 0xf7, 0xfe, 0xaf, 0xb6, - 0x29, 0x11, 0xad, 0x4f, 0xe6, 0x37, 0xda, 0xd8, 0xed, 0x88, 0xeb, 0xee, - 0x0f, 0x99, 0x67, 0x66, 0x98, 0x83, 0x66, 0x98, 0x3b, 0x0c, 0x3f, 0x1e, - 0x26, 0x5b, 0x70, 0x24, 0x81, 0xa3, 0xee, 0xdb, 0xef, 0x73, 0x3e, 0xae, - 0xa0, 0xfe, 0x0c, 0x62, 0xea, 0xef, 0xdf, 0x71, 0xeb, 0xfa, 0x47, 0x3e, - 0x7d, 0xed, 0x3a, 0x1e, 0xc3, 0xd6, 0x41, 0x7f, 0x72, 0x56, 0xc1, 0xbe, - 0xf2, 0x0d, 0x4f, 0x1f, 0xf0, 0x7d, 0xd8, 0x1e, 0x5f, 0x03, 0xdd, 0x7a, - 0xf5, 0xb7, 0x27, 0x03, 0xea, 0x34, 0x47, 0xbe, 0x73, 0x51, 0xd2, 0xd2, - 0x9c, 0xc6, 0x7e, 0x39, 0xcc, 0xdc, 0x58, 0x00, 0x1f, 0x07, 0xcd, 0x31, - 0x73, 0x8e, 0xb8, 0xe3, 0x02, 0x9c, 0xa8, 0x25, 0xb3, 0x1d, 0xbe, 0x9e, - 0xbf, 0xc9, 0xf3, 0x81, 0x7b, 0x1b, 0xbf, 0xf1, 0xfc, 0xa6, 0x4f, 0xcf, - 0x95, 0x5e, 0x8f, 0x9e, 0x60, 0x7d, 0xd0, 0xbc, 0xf5, 0xbb, 0xbe, 0xcb, - 0x97, 0x27, 0xde, 0x9f, 0xf4, 0xe9, 0xa2, 0x6e, 0x5a, 0x69, 0xa2, 0x5e, - 0xfe, 0x1d, 0x78, 0x74, 0xad, 0x51, 0x52, 0x59, 0xd4, 0x2e, 0x19, 0xe6, - 0xac, 0xd4, 0x64, 0x4e, 0x2c, 0xe8, 0x24, 0x65, 0xcf, 0x62, 0xd7, 0xbb, - 0x15, 0xea, 0xf9, 0x3a, 0x62, 0x35, 0xf5, 0xfe, 0xbe, 0xcc, 0x57, 0x86, - 0xec, 0x76, 0x83, 0xfe, 0x9a, 0x4a, 0x9f, 0x96, 0x31, 0xfb, 0xb4, 0xae, - 0xa1, 0x52, 0xc9, 0x63, 0x42, 0xd9, 0x5e, 0x97, 0x61, 0x5d, 0xdb, 0xbc, - 0x2f, 0x16, 0xe4, 0x32, 0x53, 0x85, 0x8f, 0xed, 0xfe, 0x57, 0x57, 0xd7, - 0xa4, 0x08, 0x6f, 0xef, 0x6c, 0x81, 0xeb, 0x75, 0x8d, 0x87, 0xf8, 0x5a, - 0x71, 0x19, 0xd2, 0xb1, 0x3b, 0xc0, 0x67, 0xc9, 0x42, 0x33, 0xc0, 0x19, - 0x45, 0x5c, 0x46, 0x0c, 0xd8, 0xfd, 0x05, 0x5f, 0x1f, 0x7c, 0x7f, 0xd3, - 0x65, 0x2d, 0xa4, 0xb2, 0xa7, 0xfc, 0xb9, 0x3f, 0xa3, 0x0c, 0xf0, 0x1d, - 0xc8, 0xfd, 0x79, 0x3f, 0xde, 0x94, 0x8c, 0x5c, 0x93, 0x32, 0xa0, 0xad, - 0x40, 0xff, 0xda, 0x3e, 0xe1, 0x33, 0xd5, 0xcf, 0x22, 0x66, 0xf5, 0x79, - 0xf5, 0x03, 0x7a, 0xb0, 0x5c, 0x93, 0x73, 0x1b, 0x1d, 0x8e, 0xdd, 0xe6, - 0xfb, 0xd2, 0x3e, 0xcc, 0xcd, 0xe0, 0x8f, 0xb2, 0x23, 0xcc, 0x7e, 0xbc, - 0xe7, 0x7c, 0x38, 0x99, 0x74, 0x90, 0xbb, 0x72, 0xfb, 0xa7, 0xf0, 0x6d, - 0xf8, 0x7d, 0x96, 0x96, 0x7b, 0x0d, 0xb5, 0x0a, 0xe4, 0x39, 0x0c, 0x7e, - 0x92, 0x32, 0xd5, 0x84, 0xce, 0x6f, 0xc4, 0xb3, 0x1b, 0x30, 0xa5, 0x9b, - 0x30, 0x5e, 0xec, 0x9b, 0x6a, 0xbe, 0xe5, 0x32, 0x1e, 0xfc, 0x89, 0xf6, - 0x97, 0x24, 0x68, 0x0f, 0x7a, 0xb5, 0x9c, 0xf1, 0x70, 0x75, 0xda, 0x78, - 0xa4, 0xca, 0x3d, 0xea, 0x6b, 0xfd, 0x62, 0x25, 0x1d, 0x85, 0x3a, 0x75, - 0x77, 0x2f, 0xce, 0x3c, 0x06, 0xdb, 0x28, 0x19, 0x33, 0xa3, 0xdb, 0xa5, - 0x90, 0xee, 0x07, 0xcd, 0xf7, 0xe3, 0xd9, 0x8e, 0xf9, 0x9f, 0xc2, 0x3c, - 0xec, 0x28, 0x4d, 0xff, 0xe8, 0xd4, 0xbd, 0xe4, 0xac, 0x49, 0x1a, 0x87, - 0x7d, 0xdb, 0xfa, 0x8e, 0xe9, 0xd9, 0xd2, 0x13, 0xf8, 0xde, 0x86, 0xf9, - 0x5f, 0xc0, 0x13, 0xb9, 0x6c, 0x77, 0x30, 0x4f, 0x1f, 0x9c, 0xc4, 0xfc, - 0xbd, 0xc0, 0xf1, 0xdb, 0x78, 0xbf, 0x0b, 0xef, 0xbf, 0xb5, 0x69, 0xef, - 0x6f, 0xf2, 0x6c, 0xcc, 0x3b, 0x9b, 0xe6, 0x83, 0xf8, 0xcd, 0xf3, 0x44, - 0xfa, 0xd6, 0xc1, 0xf8, 0x7a, 0x4c, 0x76, 0x9c, 0xee, 0x12, 0x55, 0xf7, - 0x62, 0xb8, 0xaa, 0x9b, 0xd2, 0x7f, 0x9a, 0xf1, 0xfb, 0xaf, 0xb0, 0xc7, - 0x12, 0xb5, 0x0e, 0xa5, 0x51, 0xb7, 0xda, 0x47, 0x0f, 0x1c, 0x19, 0x5c, - 0xe6, 0x73, 0xf6, 0xc8, 0x44, 0x83, 0x30, 0x7c, 0x7f, 0xec, 0xc8, 0x60, - 0xe3, 0x6f, 0x01, 0x0b, 0xb9, 0x54, 0x03, 0xfc, 0x84, 0xff, 0xd3, 0x4d, - 0x67, 0x6a, 0xd9, 0xe2, 0x4c, 0xfa, 0xfd, 0x81, 0x23, 0x4e, 0x8d, 0x75, - 0x42, 0x2a, 0x21, 0xba, 0x16, 0x9f, 0x3d, 0x52, 0x44, 0x7e, 0x8c, 0x68, - 0x5a, 0x82, 0x75, 0xae, 0x51, 0x0f, 0x5b, 0xd1, 0x46, 0xba, 0x5a, 0xf1, - 0x30, 0xcf, 0x10, 0xcf, 0x63, 0xc0, 0x93, 0x06, 0x1e, 0xe6, 0x1b, 0x8f, - 0xde, 0xe4, 0xf2, 0x56, 0xb4, 0x11, 0x17, 0xcf, 0x0a, 0xf0, 0xf5, 0x8b, - 0x3a, 0xfd, 0x26, 0xe9, 0x35, 0x59, 0xdb, 0x7a, 0xb1, 0xa6, 0x4d, 0x0a, - 0x27, 0x99, 0xb3, 0x77, 0xfb, 0xdf, 0x71, 0x93, 0x3d, 0x77, 0x52, 0x71, - 0x9e, 0x4f, 0xac, 0x65, 0xee, 0xc4, 0x1c, 0xbe, 0x57, 0x02, 0x58, 0xe5, - 0xc3, 0xf6, 0xb4, 0xf0, 0xdd, 0xe6, 0xcb, 0x9a, 0x67, 0x06, 0xbd, 0x67, - 0x2b, 0x2d, 0x00, 0x85, 0x1e, 0xfa, 0x6e, 0xe8, 0x21, 0xe0, 0x13, 0x0b, - 0xeb, 0xa4, 0x2d, 0x0d, 0x5e, 0x03, 0xda, 0x3e, 0xa9, 0xfe, 0xb8, 0x37, - 0x8d, 0xbf, 0xe0, 0xbc, 0x40, 0x06, 0xa4, 0x8b, 0x4f, 0xd8, 0xf2, 0xc7, - 0x7a, 0xe7, 0x34, 0xfc, 0x8e, 0xf7, 0x1e, 0xae, 0xbb, 0x66, 0x53, 0xf6, - 0x1d, 0xd0, 0x3b, 0x79, 0x31, 0xd0, 0x4b, 0x28, 0xd6, 0x74, 0x49, 0xf6, - 0xac, 0x87, 0xe4, 0x6d, 0xe0, 0xca, 0xa1, 0xaf, 0xf4, 0x7a, 0xa3, 0x59, - 0xc4, 0xc7, 0x0d, 0xd8, 0xe7, 0x45, 0x8b, 0xf7, 0x2f, 0x51, 0xe6, 0x3b, - 0x29, 0x37, 0xfe, 0x19, 0x30, 0xac, 0xaf, 0x6e, 0xde, 0xad, 0x2c, 0x03, - 0x66, 0x05, 0x6b, 0xc7, 0xbc, 0xb8, 0xcc, 0xd8, 0xee, 0x2a, 0xd4, 0x1e, - 0x45, 0xeb, 0xbf, 0x5d, 0xd6, 0x59, 0x37, 0x61, 0xb7, 0xba, 0x0b, 0x41, - 0xce, 0x59, 0x4a, 0x2d, 0x2c, 0x23, 0x86, 0xd7, 0x2c, 0xb5, 0x43, 0x69, - 0x8b, 0x4c, 0xd5, 0x10, 0x93, 0xd0, 0xf5, 0xa6, 0x92, 0xcb, 0xf2, 0x03, - 0xad, 0x87, 0x36, 0x6b, 0xcc, 0xec, 0x57, 0x5f, 0xa4, 0x5d, 0x69, 0xca, - 0x23, 0x27, 0x90, 0x97, 0xc7, 0x1f, 0x46, 0xce, 0x81, 0xbc, 0x4e, 0x94, - 0xd0, 0xc9, 0xd3, 0x46, 0x36, 0x7e, 0xbd, 0x68, 0x79, 0x7d, 0x80, 0xce, - 0x67, 0xe2, 0xf1, 0x18, 0x39, 0xd1, 0xad, 0xe3, 0x4c, 0x41, 0xc7, 0x9b, - 0x21, 0x73, 0x46, 0x75, 0xa1, 0xc6, 0x40, 0x01, 0x8a, 0x0a, 0xc7, 0x1c, - 0x11, 0x19, 0x5c, 0x44, 0x5c, 0x41, 0x1c, 0x1e, 0x5c, 0x47, 0x74, 0x3b, - 0x41, 0x78, 0x25, 0xd1, 0x13, 0x11, 0x69, 0x3b, 0xc1, 0xfb, 0x10, 0xd9, - 0x89, 0x7e, 0x8c, 0x38, 0x07, 0xa3, 0x78, 0x4e, 0xe1, 0x6f, 0x0f, 0x6a, - 0x2b, 0x13, 0x35, 0xf2, 0x16, 0xf0, 0x80, 0xe5, 0x9e, 0xad, 0xe0, 0xbb, - 0xfb, 0xa4, 0x2b, 0x86, 0x3d, 0x84, 0x8f, 0x82, 0x8e, 0x9d, 0xa0, 0xc7, - 0x3b, 0x9f, 0x38, 0xa2, 0x27, 0x44, 0x86, 0x16, 0xa5, 0x5f, 0xe9, 0x3d, - 0x51, 0x29, 0x66, 0xb8, 0xd6, 0x0d, 0x78, 0xee, 0xc3, 0x9a, 0xde, 0xe7, - 0xdd, 0x2b, 0x15, 0x6e, 0xd2, 0x8d, 0x39, 0x03, 0xef, 0xa8, 0xa7, 0x32, - 0xa6, 0x0c, 0xd5, 0x3d, 0xd8, 0xc1, 0xf5, 0x43, 0x78, 0x92, 0x57, 0x8f, - 0x36, 0x85, 0x9a, 0xb8, 0x00, 0xa9, 0x46, 0x47, 0x78, 0x3f, 0x43, 0x18, - 0xf6, 0xb5, 0xdd, 0x1a, 0xc6, 0x1c, 0xa1, 0xfc, 0xbc, 0x39, 0xa5, 0xfe, - 0xb7, 0x7b, 0x97, 0xd6, 0x9a, 0x42, 0xfb, 0x0a, 0xf6, 0x7f, 0x45, 0xfb, - 0x8a, 0xa8, 0xa4, 0xef, 0x2b, 0xf8, 0x5e, 0xe1, 0x77, 0x90, 0x8b, 0x7f, - 0xed, 0x0e, 0x2f, 0xde, 0xbb, 0x32, 0x67, 0xf3, 0x0e, 0xc3, 0x95, 0x8b, - 0x76, 0xc9, 0x78, 0xf0, 0x96, 0x3a, 0x33, 0xad, 0xf3, 0x73, 0x11, 0xb2, - 0xbf, 0xdc, 0xd0, 0x3d, 0x9b, 0x5c, 0x6a, 0xc4, 0xe4, 0xca, 0x6a, 0x97, - 0x5c, 0x5e, 0xf6, 0x6c, 0xfe, 0xf2, 0x32, 0xed, 0xdc, 0x94, 0xef, 0xad, - 0x5a, 0x58, 0x4b, 0xe3, 0xaf, 0x5f, 0xde, 0x59, 0xbd, 0xb5, 0xee, 0x3c, - 0xdf, 0x7c, 0x00, 0xb4, 0xf4, 0x4b, 0xc4, 0x72, 0x75, 0xff, 0x95, 0x47, - 0xee, 0x2b, 0xc9, 0x94, 0x14, 0xaa, 0x43, 0xe8, 0x01, 0x91, 0x9c, 0xa3, - 0xcc, 0x41, 0xd0, 0x7f, 0xf5, 0x33, 0xa8, 0x4d, 0x52, 0x70, 0x9e, 0x21, - 0x7d, 0x8f, 0xf8, 0x33, 0xd1, 0x7e, 0x69, 0xb7, 0xbe, 0xdc, 0xe7, 0xe5, - 0x2a, 0xd3, 0xeb, 0x53, 0xad, 0x20, 0x5f, 0xbf, 0x0e, 0xdc, 0xe3, 0xb0, - 0x53, 0xda, 0xa6, 0x0d, 0x9b, 0x35, 0x65, 0x6d, 0x34, 0x55, 0x2b, 0x09, - 0xe3, 0x43, 0x06, 0x67, 0x7e, 0x08, 0x9e, 0xd3, 0x90, 0x47, 0xa7, 0xae, - 0x85, 0x72, 0x0a, 0xba, 0x5d, 0x9c, 0x97, 0x42, 0xf3, 0x57, 0x80, 0x2f, - 0x27, 0xb3, 0xcd, 0x49, 0x9c, 0x75, 0x1c, 0x76, 0x3b, 0xda, 0x2f, 0x5d, - 0x3c, 0x27, 0x03, 0x1a, 0xef, 0x97, 0xe2, 0xc9, 0x79, 0x39, 0x58, 0x25, - 0x9d, 0xc8, 0x25, 0x76, 0x2a, 0x9d, 0x97, 0xb1, 0xe4, 0x2a, 0x6a, 0x27, - 0xcf, 0x1f, 0xb3, 0x52, 0x3c, 0x05, 0x1c, 0x55, 0xde, 0x03, 0x0c, 0xc1, - 0x6e, 0xc6, 0x74, 0x5f, 0x33, 0xab, 0xe3, 0x0e, 0xe7, 0xdf, 0x84, 0x9e, - 0x86, 0x4a, 0x7b, 0x00, 0x57, 0x40, 0x0f, 0x34, 0x83, 0x7a, 0x79, 0xa5, - 0x8a, 0x7e, 0xcf, 0x8e, 0xb0, 0xf6, 0x52, 0xea, 0x9e, 0x01, 0xa9, 0x57, - 0xc7, 0x4c, 0xa5, 0x58, 0x53, 0x51, 0x17, 0x5c, 0xa3, 0x7f, 0x27, 0x54, - 0xd4, 0x1a, 0x90, 0xd5, 0x6a, 0x09, 0x7d, 0xb3, 0xf2, 0xef, 0x35, 0x4a, - 0x62, 0x5a, 0x5e, 0xdc, 0xcb, 0x29, 0xf2, 0x8d, 0xfa, 0xb3, 0xf9, 0x59, - 0xd0, 0x98, 0x4b, 0x9a, 0x72, 0x14, 0xf4, 0xe1, 0x7d, 0x05, 0x36, 0xbe, - 0xc8, 0x1a, 0x2e, 0x87, 0xb5, 0xac, 0x1c, 0x3e, 0x33, 0x03, 0x1a, 0x7a, - 0x65, 0xe8, 0x77, 0xe9, 0x63, 0x07, 0x30, 0xc7, 0xef, 0x14, 0xec, 0xf5, - 0x31, 0xbc, 0x13, 0x36, 0x81, 0x27, 0xe5, 0x30, 0x80, 0xa7, 0x09, 0x5a, - 0x62, 0x5e, 0x6f, 0xb2, 0x3f, 0x29, 0xf5, 0x93, 0xf7, 0xc9, 0xec, 0xca, - 0x7d, 0xc0, 0xff, 0x36, 0xfa, 0x02, 0xe4, 0xb7, 0x15, 0x9e, 0xc5, 0xfa, - 0x8f, 0xe7, 0x74, 0xf4, 0x6b, 0xdf, 0x58, 0xe4, 0x3c, 0x9f, 0xfb, 0xb0, - 0x1f, 0x3d, 0x46, 0x35, 0x27, 0xc5, 0x2a, 0xcf, 0x82, 0xee, 0x50, 0x4f, - 0x15, 0x4e, 0xce, 0xf8, 0x3a, 0xee, 0x97, 0x7c, 0xbc, 0xc4, 0xfe, 0x02, - 0x79, 0x62, 0x79, 0xc2, 0xa9, 0xa4, 0x4c, 0x47, 0x11, 0x57, 0x5a, 0x98, - 0x1b, 0xbc, 0xb9, 0x98, 0x58, 0x8b, 0xe8, 0x6d, 0xb3, 0x5c, 0x3b, 0xea, - 0xdf, 0x1d, 0x10, 0xd7, 0x5b, 0x32, 0x05, 0x1b, 0x1b, 0x5a, 0x1c, 0x47, - 0x2d, 0xfc, 0x5d, 0xd4, 0x92, 0x77, 0xfa, 0x32, 0x98, 0xf4, 0x6d, 0xa3, - 0xab, 0xc5, 0x26, 0xa0, 0xe7, 0x2a, 0x74, 0x5f, 0x85, 0x1d, 0x20, 0x56, - 0xbf, 0x74, 0xc3, 0x3e, 0x26, 0x5b, 0x6a, 0xcc, 0x1e, 0xf9, 0x8b, 0x5a, - 0x2a, 0xbd, 0x01, 0xfb, 0x79, 0x07, 0xbd, 0xc0, 0x06, 0x7a, 0xd5, 0xcb, - 0xe8, 0xeb, 0x56, 0x2a, 0xfb, 0x41, 0x3f, 0x6b, 0x4a, 0x7e, 0x27, 0x74, - 0xad, 0xd3, 0x61, 0x1d, 0xbb, 0x43, 0xdf, 0xed, 0xca, 0xfe, 0x7e, 0xf6, - 0x9a, 0xec, 0xcb, 0x79, 0x0f, 0x7d, 0x05, 0x7a, 0xdc, 0x30, 0xb9, 0x1e, - 0xec, 0x63, 0x2f, 0x10, 0xd8, 0x0f, 0x69, 0xa1, 0xfd, 0x70, 0x0f, 0x61, - 0xfa, 0xb5, 0x9f, 0x14, 0x34, 0x3e, 0xda, 0xec, 0x8b, 0x7d, 0x9e, 0x9f, - 0xe9, 0x3a, 0xcb, 0xbc, 0x24, 0x81, 0xfd, 0xbe, 0xef, 0xb2, 0xaf, 0x73, - 0x46, 0x11, 0xbb, 0x9b, 0xae, 0x3c, 0x67, 0xdf, 0xea, 0x77, 0x7b, 0xab, - 0x81, 0x9c, 0x28, 0xc7, 0xfd, 0x72, 0xac, 0x99, 0x82, 0x4f, 0x50, 0x86, - 0x56, 0x8b, 0x0c, 0x45, 0xfe, 0xa8, 0x2a, 0xf2, 0x62, 0x95, 0x6b, 0x5a, - 0x86, 0x09, 0x27, 0xd2, 0xa5, 0xef, 0xd2, 0x0b, 0xf2, 0x1d, 0x39, 0xb8, - 0x24, 0x72, 0x06, 0xeb, 0x6b, 0x55, 0xfa, 0xea, 0x38, 0xea, 0xd7, 0x6d, - 0x52, 0x5f, 0x46, 0x4f, 0x56, 0x95, 0x59, 0xe7, 0x5e, 0xe6, 0x9b, 0x98, - 0x5c, 0xd6, 0x77, 0xb2, 0x22, 0x23, 0x67, 0xa3, 0x12, 0x3d, 0x8b, 0xe6, - 0x0f, 0xb2, 0x3f, 0x37, 0x1a, 0xdc, 0xd1, 0x7a, 0x3e, 0x5f, 0xae, 0x60, - 0x6f, 0x75, 0x48, 0xc7, 0xc9, 0x72, 0xa3, 0x28, 0x85, 0x1a, 0xcf, 0xc2, - 0x73, 0x39, 0x89, 0xb5, 0x8c, 0xcc, 0x9d, 0x1c, 0x97, 0xa7, 0x71, 0x06, - 0xfa, 0x3f, 0x9c, 0x31, 0x25, 0xa5, 0x33, 0x98, 0x6f, 0x5c, 0x95, 0xe5, - 0xd5, 0xa2, 0xd4, 0x6b, 0xe7, 0x5d, 0xaf, 0x8f, 0x20, 0x3e, 0x7c, 0x2f, - 0xb7, 0xf6, 0xb2, 0xfb, 0xd9, 0xcf, 0xa0, 0x57, 0xb5, 0xf0, 0x0d, 0x99, - 0x35, 0xe6, 0x66, 0x6f, 0xbd, 0x33, 0x6e, 0xed, 0x61, 0xa7, 0x65, 0xa1, - 0x9a, 0x91, 0xf2, 0xc9, 0x71, 0x7d, 0xd7, 0xd0, 0x91, 0x3d, 0xfc, 0xc4, - 0x35, 0xe4, 0x8a, 0x69, 0x7d, 0x67, 0x7c, 0x5d, 0x1e, 0xb2, 0x17, 0xe4, - 0x90, 0xb5, 0x4f, 0x8e, 0xa1, 0xbe, 0xfe, 0x1c, 0x7a, 0xfd, 0x64, 0x1f, - 0xf5, 0x08, 0x7a, 0x2d, 0xf6, 0xa0, 0xae, 0x4c, 0xd9, 0x9f, 0x36, 0x9f, - 0x65, 0x97, 0xd0, 0x60, 0x9e, 0xfc, 0x2f, 0x37, 0x87, 0xbc, 0x77, 0x0d, - 0xbd, 0x63, 0x4e, 0xc3, 0x19, 0x1e, 0x5c, 0x8d, 0x70, 0x63, 0xe6, 0x73, - 0x84, 0x5b, 0x36, 0x7c, 0x38, 0x03, 0x70, 0x11, 0xb9, 0x60, 0x47, 0x61, - 0x23, 0xd3, 0xe0, 0x13, 0x31, 0x7e, 0xa2, 0xc7, 0xaf, 0x83, 0x3b, 0x91, - 0x5b, 0x6f, 0xee, 0x7f, 0xd5, 0xdf, 0xff, 0xb4, 0xbf, 0xff, 0xe2, 0x8d, - 0xfd, 0x41, 0x7e, 0xfd, 0xd0, 0x95, 0x16, 0xba, 0x5e, 0xad, 0x78, 0xf0, - 0x0b, 0x3e, 0x5d, 0x17, 0x6f, 0xd0, 0x15, 0xc0, 0x43, 0x9e, 0x9a, 0x67, - 0xc6, 0x66, 0xc6, 0xe8, 0x21, 0xc8, 0xd1, 0x95, 0xbc, 0x0d, 0xdf, 0xa8, - 0xa6, 0x26, 0x4b, 0xfa, 0x4e, 0x4d, 0xc9, 0x46, 0x7c, 0x41, 0xa6, 0xad, - 0xd4, 0xe4, 0x9c, 0x44, 0x60, 0xcb, 0x8c, 0x2d, 0x11, 0xa9, 0x33, 0xe6, - 0xe0, 0x59, 0xb0, 0xb7, 0xa6, 0xf5, 0x4a, 0x0b, 0xad, 0x91, 0x17, 0x48, - 0xa3, 0x47, 0x6b, 0x6c, 0xf8, 0x26, 0xad, 0x1e, 0xbc, 0x47, 0xeb, 0x95, - 0x4a, 0x0b, 0xfc, 0xd9, 0xa8, 0x0f, 0x1f, 0x6d, 0x81, 0xa7, 0x3d, 0xb3, - 0xae, 0xa0, 0x3d, 0x93, 0xb6, 0x9f, 0x80, 0x6f, 0x48, 0xac, 0x33, 0x7b, - 0xf8, 0xc8, 0xdd, 0xc3, 0xae, 0xc4, 0x50, 0x6f, 0xb4, 0x63, 0xed, 0x72, - 0x8d, 0xb5, 0x88, 0x1a, 0x6c, 0x97, 0x11, 0xd8, 0x2c, 0x75, 0xe7, 0xdd, - 0x0d, 0x3e, 0xa4, 0x6b, 0x02, 0x57, 0x0e, 0xd9, 0xa4, 0xe5, 0x3f, 0xdd, - 0x17, 0xe3, 0x23, 0x76, 0x59, 0x46, 0xcd, 0x76, 0x9c, 0x5f, 0x6f, 0x6a, - 0x9c, 0x69, 0xd2, 0x72, 0x7a, 0x74, 0xc8, 0xfc, 0x73, 0xf0, 0x39, 0x55, - 0x33, 0xa4, 0x6e, 0xa5, 0x12, 0xe7, 0x80, 0x63, 0x0f, 0x74, 0x53, 0x1f, - 0x27, 0x3d, 0x22, 0x07, 0x61, 0xdf, 0x75, 0x9d, 0x17, 0x69, 0xc7, 0xa9, - 0xe9, 0x12, 0x6a, 0x9d, 0x3f, 0xd6, 0xb9, 0xcd, 0x75, 0xaf, 0x21, 0xbf, - 0x4d, 0x6f, 0xb2, 0x3d, 0x75, 0xd6, 0xb3, 0x3d, 0x75, 0x16, 0x3d, 0xf0, - 0xf1, 0x98, 0x74, 0xac, 0xc1, 0x7f, 0x5e, 0xd8, 0xe9, 0xd5, 0x73, 0x2f, - 0x24, 0x8d, 0xfc, 0x49, 0xc4, 0xbb, 0xe3, 0x51, 0xb1, 0x8e, 0xeb, 0x7c, - 0x00, 0x79, 0x4f, 0xc9, 0xdc, 0x29, 0xc6, 0x54, 0x4b, 0x86, 0x8f, 0x53, - 0x1f, 0xac, 0x6b, 0x96, 0x27, 0x8a, 0xf0, 0x91, 0x79, 0xc4, 0x05, 0xb5, - 0xf6, 0xae, 0x14, 0x2d, 0xca, 0xa1, 0x57, 0xba, 0xd6, 0xd0, 0x8f, 0xaf, - 0x21, 0x36, 0xac, 0x25, 0xa4, 0x0d, 0xbe, 0xa5, 0xce, 0xc6, 0x8d, 0xf2, - 0xd2, 0x0f, 0xe1, 0x0f, 0xfc, 0x0d, 0x07, 0xb5, 0xe5, 0xd9, 0x84, 0x41, - 0xdf, 0x52, 0x67, 0x69, 0xe7, 0x28, 0xa7, 0xce, 0xd2, 0xce, 0x49, 0x47, - 0xe0, 0x2f, 0x78, 0x3f, 0x3b, 0xae, 0xef, 0xa9, 0xaf, 0xd9, 0xe4, 0xe5, - 0x6f, 0xc4, 0xa9, 0xb1, 0x46, 0x24, 0x3f, 0xd2, 0x87, 0x5a, 0x66, 0xbb, - 0x63, 0x0f, 0x4f, 0x5e, 0x96, 0x4f, 0xca, 0xd7, 0xed, 0x9f, 0x80, 0x2f, - 0xf2, 0xd1, 0xca, 0x17, 0x79, 0xea, 0x95, 0x36, 0xcd, 0x57, 0xc0, 0x0f, - 0x04, 0x0d, 0x7e, 0x06, 0x8f, 0x27, 0x80, 0xff, 0x31, 0xc4, 0x80, 0x01, - 0x3c, 0x0f, 0xe0, 0x89, 0x94, 0x76, 0x96, 0xbc, 0x93, 0xd7, 0x77, 0x50, - 0x37, 0x06, 0x7c, 0xce, 0xe2, 0xfd, 0x15, 0x99, 0x5b, 0x72, 0x8f, 0x22, - 0xaf, 0xf2, 0x0e, 0xbd, 0xdf, 0xbb, 0x0f, 0xde, 0xcc, 0xfb, 0x2b, 0xe2, - 0xc9, 0x27, 0x65, 0xd6, 0x05, 0xef, 0xab, 0x9b, 0x65, 0xd1, 0x1a, 0x3b, - 0x12, 0xba, 0x0e, 0x3f, 0xd8, 0x60, 0x9c, 0xa0, 0x8c, 0xde, 0x11, 0x67, - 0x89, 0xf7, 0x5f, 0x1e, 0xbe, 0xd9, 0x46, 0x10, 0x37, 0x5a, 0xf7, 0xd8, - 0x80, 0x1b, 0x00, 0x1c, 0xe9, 0xda, 0xa0, 0xfc, 0x10, 0x73, 0x76, 0xb5, - 0xc4, 0x9a, 0xd6, 0x7d, 0x93, 0xf2, 0x0c, 0xea, 0x80, 0x57, 0xed, 0x5b, - 0xe4, 0x3a, 0xcb, 0x5a, 0xa8, 0xde, 0x98, 0x81, 0x4f, 0xb6, 0x21, 0x96, - 0x99, 0x72, 0xb9, 0xd2, 0x2e, 0x75, 0xd4, 0x3b, 0x2b, 0xab, 0x8c, 0x85, - 0xa4, 0xbd, 0x0b, 0xf3, 0x5e, 0xfc, 0x62, 0xac, 0xbd, 0x5c, 0x41, 0x9e, - 0x85, 0x6f, 0x5f, 0xae, 0xc4, 0xf1, 0x1c, 0xc0, 0xd3, 0xc2, 0x33, 0x89, - 0x67, 0x1a, 0xcf, 0x71, 0x3c, 0xc7, 0xf1, 0xb4, 0xb0, 0x37, 0x81, 0x67, - 0xd0, 0x33, 0x10, 0xd7, 0x4d, 0xbe, 0xcb, 0xfa, 0x3c, 0xd4, 0x8a, 0x16, - 0x73, 0x5a, 0xd4, 0xce, 0xa3, 0x8f, 0x70, 0xc6, 0x75, 0xad, 0x87, 0xfc, - 0xf6, 0x91, 0x6b, 0x5a, 0xec, 0xcb, 0x4b, 0xc6, 0x9e, 0x51, 0xe6, 0x85, - 0x1a, 0xf2, 0xc2, 0x7f, 0xec, 0x40, 0xff, 0x68, 0xee, 0xd5, 0x77, 0x47, - 0x4b, 0xf8, 0xe6, 0x3b, 0x7a, 0xde, 0xf8, 0x3c, 0xf2, 0x14, 0xe3, 0xa7, - 0x8b, 0x3d, 0x05, 0xc4, 0xf1, 0xed, 0xf0, 0xbf, 0x1c, 0xe2, 0x36, 0xde, - 0x97, 0x37, 0x76, 0x78, 0x39, 0x15, 0xf5, 0xbb, 0xda, 0x7c, 0x5f, 0x63, - 0x63, 0xcf, 0x56, 0xbd, 0x41, 0x0f, 0x70, 0xa4, 0x6a, 0xcb, 0xf0, 0xc1, - 0x37, 0xed, 0xa3, 0xba, 0xb6, 0xa3, 0x2e, 0x9e, 0x46, 0x8d, 0x9a, 0x5f, - 0x64, 0x0d, 0xf3, 0x14, 0xfa, 0x12, 0xf4, 0x67, 0x71, 0xf6, 0xe4, 0xcc, - 0x05, 0xba, 0x16, 0x8d, 0x4b, 0x17, 0xf3, 0xc0, 0x15, 0x9c, 0x07, 0xbe, - 0x56, 0x5c, 0xc8, 0xec, 0x41, 0xd4, 0x84, 0xae, 0x1b, 0xb5, 0xf6, 0x48, - 0xf2, 0x11, 0xc6, 0x1c, 0xc1, 0x7e, 0x53, 0xbc, 0x7b, 0x75, 0xc4, 0xdd, - 0x19, 0xfd, 0xfb, 0x30, 0x8c, 0x6b, 0x1c, 0x7b, 0x6f, 0x13, 0xef, 0xb7, - 0x5c, 0xde, 0x69, 0x8b, 0xec, 0x59, 0xf4, 0x6a, 0x5a, 0x65, 0xb5, 0xe2, - 0xfb, 0x49, 0x1f, 0x1f, 0xd7, 0x95, 0xff, 0xdb, 0xc6, 0x4e, 0xc8, 0x08, - 0xfe, 0x00, 0x1d, 0x1f, 0x43, 0xfd, 0x7c, 0x01, 0x7a, 0x79, 0x15, 0x3a, - 0x79, 0xad, 0x42, 0x5b, 0x1f, 0x83, 0xdd, 0x43, 0x86, 0x33, 0xfa, 0x0c, - 0x7d, 0xf6, 0x85, 0x0a, 0x62, 0x27, 0xe3, 0x9f, 0xfa, 0x52, 0x9c, 0xf5, - 0x21, 0xf3, 0xa0, 0x87, 0x67, 0xc0, 0x83, 0x93, 0x60, 0x6d, 0x87, 0xa6, - 0xa7, 0xae, 0xef, 0xc1, 0x28, 0x27, 0xd8, 0x20, 0x7f, 0x23, 0xd0, 0x30, - 0x5f, 0x8c, 0xeb, 0x7b, 0x78, 0xc5, 0x39, 0xf2, 0x31, 0x2e, 0xce, 0x62, - 0xb0, 0xaf, 0x0f, 0xfb, 0x3a, 0x5b, 0x70, 0xdd, 0xbe, 0x89, 0x07, 0xe5, - 0xf3, 0xc0, 0xf5, 0xcd, 0x75, 0x7f, 0xca, 0x2c, 0xdd, 0xb8, 0x1b, 0x66, - 0xfe, 0xa5, 0x6e, 0x32, 0xd8, 0x1f, 0xe8, 0x67, 0xc0, 0xef, 0x05, 0x52, - 0x0b, 0xe8, 0x23, 0x20, 0x7f, 0xea, 0x68, 0x92, 0xf1, 0x09, 0xf8, 0x6d, - 0xa9, 0x55, 0x3a, 0x44, 0xf5, 0xb3, 0x37, 0x66, 0xad, 0xdc, 0x7a, 0xe6, - 0x2f, 0xfa, 0x67, 0xa2, 0x9f, 0x3e, 0xc1, 0xba, 0x59, 0xe7, 0x19, 0xc0, - 0x74, 0x6f, 0xa2, 0xed, 0xe7, 0x7c, 0x38, 0xae, 0xa7, 0xa5, 0x84, 0x3a, - 0x34, 0xbf, 0x88, 0x8a, 0x1e, 0xf1, 0x5b, 0x65, 0xf9, 0xbb, 0x16, 0xef, - 0xf0, 0xc6, 0x92, 0x73, 0xa0, 0xb1, 0x64, 0xe6, 0x78, 0x6f, 0x06, 0x1c, - 0xbb, 0x36, 0xe1, 0x98, 0xf2, 0x71, 0x4c, 0x49, 0xf9, 0xd4, 0x34, 0x7c, - 0x2d, 0x87, 0xfc, 0x3e, 0x64, 0x3e, 0x28, 0x9f, 0x41, 0x73, 0x8d, 0xb9, - 0x33, 0xe3, 0xd0, 0x93, 0xeb, 0xee, 0xb1, 0xf7, 0x83, 0xee, 0x97, 0x91, - 0x5b, 0x83, 0x9a, 0xa7, 0x9c, 0x88, 0x20, 0x87, 0x1d, 0xd6, 0xbf, 0xc3, - 0x96, 0x4c, 0x13, 0xf6, 0xaa, 0x8c, 0xb1, 0x34, 0xda, 0x7b, 0xe4, 0xb7, - 0x05, 0xe4, 0x2a, 0xf2, 0xd9, 0x23, 0x65, 0xd3, 0x78, 0x20, 0x82, 0xba, - 0xc6, 0x59, 0xa4, 0x1f, 0xc9, 0x70, 0x24, 0xdb, 0x8e, 0x9a, 0xd4, 0x95, - 0xef, 0xd9, 0xfc, 0x77, 0x09, 0x0b, 0x72, 0xa1, 0x61, 0xe2, 0x79, 0x0e, - 0x7a, 0xf8, 0x3d, 0xbc, 0xff, 0x53, 0x3f, 0xea, 0x3e, 0xac, 0xe4, 0x60, - 0xbb, 0x69, 0x5d, 0xcf, 0xb0, 0x8e, 0xa8, 0x23, 0xdf, 0x2a, 0xe4, 0x1a, - 0xd4, 0x55, 0x93, 0xac, 0x5d, 0x9f, 0x59, 0xb9, 0x2a, 0xaf, 0x2d, 0xf1, - 0x77, 0x50, 0xe6, 0xe5, 0x7d, 0x8c, 0x07, 0xe6, 0x7c, 0x06, 0x73, 0xab, - 0x8c, 0x65, 0xf8, 0x6e, 0xc2, 0x81, 0xfa, 0x51, 0x23, 0xa0, 0xd6, 0xbe, - 0x6c, 0xa5, 0xc1, 0xe7, 0x55, 0xb9, 0xb0, 0x14, 0x95, 0x15, 0x8b, 0x75, - 0x91, 0x24, 0x1d, 0xc0, 0x5e, 0x58, 0xfd, 0x07, 0xcf, 0x26, 0x08, 0x8f, - 0x9e, 0xa7, 0x84, 0xba, 0xee, 0x41, 0xbd, 0xf7, 0x47, 0xe9, 0x99, 0x34, - 0xb5, 0xf6, 0x79, 0x45, 0xb9, 0x40, 0x7f, 0xd2, 0xbf, 0x51, 0xb0, 0x36, - 0x78, 0x0a, 0x36, 0xcb, 0xda, 0x9d, 0xfd, 0x00, 0xde, 0x1b, 0x5c, 0x27, - 0xef, 0x78, 0x2e, 0x0f, 0x41, 0x36, 0xf4, 0x7b, 0xde, 0x89, 0x21, 0x8f, - 0x2a, 0xfa, 0x7a, 0x59, 0xc7, 0x82, 0x72, 0xb5, 0x88, 0x9c, 0x82, 0x18, - 0x60, 0xef, 0x82, 0x2d, 0xce, 0x40, 0x97, 0x93, 0x80, 0xdb, 0x94, 0x4b, - 0xd6, 0xcb, 0xba, 0x2e, 0x53, 0xa7, 0x6f, 0xde, 0xdf, 0x14, 0xe0, 0x3f, - 0x6a, 0x1d, 0xb6, 0x05, 0x1f, 0x52, 0xeb, 0x71, 0x3c, 0x11, 0x8f, 0xd7, - 0xd1, 0x5f, 0x54, 0x78, 0x3f, 0x84, 0xde, 0xa0, 0xc2, 0xbb, 0x93, 0x34, - 0x9e, 0xe3, 0xbc, 0x2f, 0xf2, 0xe3, 0x1a, 0xf1, 0x93, 0x8e, 0x20, 0xbe, - 0xb0, 0x96, 0x64, 0x7c, 0x09, 0xea, 0x49, 0xcf, 0x16, 0x8e, 0x55, 0x19, - 0x43, 0x68, 0xd7, 0x43, 0x88, 0x5b, 0xb4, 0x05, 0xaf, 0x96, 0x5c, 0xad, - 0x79, 0x32, 0x9b, 0x6b, 0x9e, 0xd7, 0x39, 0x62, 0xaf, 0x58, 0xb0, 0x31, - 0xca, 0x0e, 0x6b, 0x3a, 0x07, 0x9c, 0x93, 0x9c, 0x7e, 0x52, 0x66, 0xaf, - 0x48, 0x6e, 0x75, 0x5c, 0x9e, 0xd3, 0x71, 0x2b, 0x88, 0x59, 0xac, 0x21, - 0xf9, 0xfb, 0x71, 0x5a, 0x9e, 0x3d, 0x79, 0x55, 0x9c, 0xe7, 0x19, 0xb7, - 0xc6, 0x12, 0x9d, 0x06, 0x63, 0x95, 0x2b, 0x0d, 0xe4, 0xa6, 0x07, 0x6d, - 0xfe, 0x5b, 0x80, 0x08, 0x7a, 0x3a, 0x57, 0xda, 0x27, 0x52, 0x76, 0xd2, - 0x18, 0x3a, 0xd0, 0x69, 0x30, 0x37, 0x8e, 0x99, 0x8f, 0x4b, 0x70, 0x1f, - 0xd5, 0x21, 0x8f, 0xeb, 0xbb, 0x0a, 0xb8, 0xed, 0xe2, 0x07, 0xfa, 0x77, - 0x94, 0x6b, 0x19, 0xca, 0x1a, 0xdf, 0xeb, 0x9c, 0x2f, 0xc5, 0xae, 0x65, - 0xda, 0xa4, 0x7c, 0x9b, 0xeb, 0x1e, 0x9a, 0x98, 0xd8, 0xe1, 0xfd, 0x7b, - 0x91, 0x23, 0xb7, 0x79, 0xb1, 0xa0, 0xe0, 0x7f, 0xaf, 0xe1, 0x49, 0xdb, - 0x66, 0xbe, 0x65, 0x7e, 0xa4, 0xde, 0xf0, 0x5c, 0xe5, 0x3b, 0x73, 0xef, - 0x02, 0x72, 0x2f, 0xf3, 0xe5, 0x76, 0xc9, 0xf3, 0x77, 0x3e, 0xa5, 0xe7, - 0x4b, 0x5e, 0x2d, 0xed, 0xc3, 0xd5, 0x66, 0x65, 0xae, 0xc6, 0x1a, 0xea, - 0x02, 0x72, 0xd9, 0x28, 0x6c, 0x95, 0x39, 0xed, 0x28, 0xf2, 0x39, 0x7f, - 0x9f, 0xc6, 0xda, 0x32, 0xf7, 0xa5, 0xd2, 0x49, 0xd5, 0xfa, 0xbb, 0xd2, - 0xd5, 0x38, 0xef, 0xa3, 0xce, 0x8d, 0x42, 0xef, 0xbf, 0xc3, 0xde, 0x62, - 0x58, 0xdb, 0x88, 0xf3, 0x02, 0x65, 0xef, 0xfd, 0x7e, 0x2d, 0x7d, 0x9e, - 0x0f, 0xb0, 0x0e, 0xf8, 0x3c, 0xe4, 0xb2, 0xd7, 0xbe, 0xca, 0xdc, 0xfd, - 0x6f, 0xca, 0x1a, 0x4b, 0x3f, 0x6e, 0xd0, 0xb7, 0xf1, 0xbd, 0x1a, 0x91, - 0xe5, 0x38, 0xf9, 0x87, 0xbc, 0x0c, 0xfa, 0xce, 0x56, 0x72, 0xd8, 0x2c, - 0x83, 0x3f, 0x80, 0x0c, 0x28, 0xcb, 0x40, 0x06, 0x7c, 0x9f, 0x86, 0xbe, - 0xd8, 0x33, 0x0c, 0xe9, 0x3e, 0xb2, 0xdc, 0xf4, 0xce, 0x2e, 0x57, 0x5b, - 0x69, 0x26, 0xbd, 0xd4, 0xe9, 0x39, 0xc9, 0x6b, 0xfd, 0x2e, 0x48, 0xbe, - 0x76, 0x4e, 0xf6, 0xd4, 0x16, 0xe4, 0x21, 0xeb, 0x01, 0xf0, 0x7b, 0xc9, - 0x2d, 0x5a, 0xba, 0x57, 0x99, 0x2c, 0xe0, 0xec, 0xe2, 0xff, 0x74, 0x6e, - 0xb5, 0xbf, 0x6d, 0x55, 0x67, 0xfc, 0xf1, 0xb5, 0x9d, 0xa4, 0xa1, 0x09, - 0xb7, 0xae, 0x93, 0xb8, 0x69, 0x0a, 0x76, 0x7c, 0xdb, 0x46, 0x24, 0xad, - 0x6e, 0x43, 0x46, 0xa3, 0x2e, 0x53, 0x4c, 0x12, 0xba, 0x74, 0xeb, 0x44, - 0xda, 0x75, 0x5d, 0x37, 0xd0, 0x64, 0x9c, 0xb4, 0x14, 0x98, 0x54, 0x28, - 0xac, 0x43, 0x08, 0xa9, 0xc6, 0x6d, 0x35, 0xa6, 0xa5, 0x71, 0xfa, 0x46, - 0x10, 0x5f, 0xb0, 0x92, 0xb4, 0x65, 0x52, 0x84, 0x5b, 0x04, 0xdb, 0x3e, - 0xb0, 0xd1, 0xa5, 0x8c, 0x3f, 0x60, 0xfb, 0x30, 0x26, 0xb1, 0x29, 0x2b, - 0xb0, 0xb1, 0x7d, 0xea, 0x07, 0x26, 0x75, 0xda, 0x8a, 0xf7, 0xfb, 0x3d, - 0xe7, 0x5e, 0xc7, 0x36, 0x41, 0x48, 0x8b, 0x14, 0xf9, 0x9e, 0x97, 0x7b, - 0xee, 0xb9, 0xe7, 0x79, 0x7f, 0x9e, 0xdf, 0xed, 0x59, 0x27, 0x9f, 0xc0, - 0xef, 0x38, 0x35, 0x67, 0x4b, 0xda, 0xee, 0x97, 0x9f, 0x6a, 0x2e, 0x9f, - 0xf1, 0x49, 0x00, 0x3e, 0xa9, 0xc1, 0x16, 0x48, 0x8b, 0x13, 0xbb, 0x21, - 0xf4, 0x29, 0xc3, 0xa0, 0x75, 0xdc, 0xf8, 0xcd, 0xb6, 0x19, 0xdf, 0x74, - 0x06, 0xbe, 0xbb, 0xbb, 0xad, 0xc5, 0xcf, 0xf9, 0x1a, 0xff, 0xf6, 0x7d, - 0xaf, 0x86, 0xd6, 0x2f, 0xd3, 0xd8, 0xcf, 0x9b, 0xaa, 0x67, 0x1d, 0xf0, - 0x12, 0x73, 0xd3, 0x31, 0xcd, 0x3f, 0x84, 0xa7, 0xa8, 0xa3, 0xae, 0x40, - 0x47, 0x0d, 0x50, 0x77, 0x0d, 0xce, 0xb9, 0xcc, 0x0f, 0x44, 0xe5, 0x0f, - 0x93, 0xd4, 0xc3, 0x71, 0xf9, 0xfd, 0xe4, 0xb3, 0xd8, 0x4f, 0xa2, 0xc0, - 0x1c, 0xe5, 0xf5, 0xe9, 0xac, 0x62, 0x92, 0x86, 0xd5, 0x07, 0x7e, 0x5a, - 0xed, 0x40, 0xdc, 0xca, 0xad, 0x0d, 0xab, 0xbe, 0x39, 0xa2, 0xb5, 0xdd, - 0xb8, 0xd5, 0x21, 0xd7, 0xcf, 0x1b, 0x1d, 0x1b, 0x9e, 0x8a, 0x06, 0x86, - 0xe7, 0x69, 0x97, 0x92, 0xb1, 0x8c, 0x55, 0x2f, 0x07, 0xa3, 0xcc, 0x3d, - 0xa7, 0xa8, 0x9f, 0x61, 0x0b, 0xbb, 0xed, 0x8c, 0xd5, 0xe0, 0xd9, 0x9f, - 0x58, 0x8d, 0x9e, 0x3d, 0xe2, 0xe9, 0x59, 0x8e, 0xa5, 0x40, 0x53, 0xda, - 0xa2, 0xc4, 0xf4, 0x88, 0x95, 0x84, 0xcd, 0xc3, 0xf5, 0x02, 0xd7, 0x8f, - 0xcb, 0xd1, 0x85, 0xc3, 0xf0, 0xbf, 0xbb, 0xed, 0xbd, 0xb4, 0xab, 0xf6, - 0x00, 0xf1, 0x38, 0x78, 0xfe, 0x86, 0x9a, 0xb5, 0x1e, 0xf6, 0xd6, 0xe2, - 0x38, 0xe4, 0x7c, 0x8a, 0xf5, 0xda, 0x7a, 0xe6, 0x73, 0x74, 0xaf, 0xd5, - 0x73, 0xf7, 0x94, 0x9f, 0x7b, 0x32, 0xef, 0x78, 0x58, 0x30, 0xfc, 0xc2, - 0x17, 0xfa, 0x76, 0x84, 0xcf, 0xe4, 0xf3, 0x9a, 0x65, 0x68, 0x3f, 0xf4, - 0xcb, 0x14, 0xff, 0xb3, 0x5e, 0xed, 0x0a, 0xf1, 0x4a, 0xb4, 0x7d, 0x05, - 0xdb, 0xf4, 0x35, 0x6f, 0xbd, 0xad, 0xad, 0xd2, 0x18, 0xad, 0x98, 0xcf, - 0xdc, 0x0a, 0xdb, 0x71, 0xc9, 0x2e, 0xf0, 0xb7, 0x54, 0x8a, 0x38, 0x75, - 0xb2, 0xd7, 0x5e, 0x5f, 0xb3, 0xc6, 0x16, 0xf4, 0x19, 0x9f, 0x20, 0x38, - 0x15, 0xf0, 0x7c, 0x8b, 0xbb, 0xe9, 0x37, 0x79, 0xd7, 0x0d, 0x9a, 0x93, - 0x89, 0x5b, 0xed, 0x35, 0xef, 0x71, 0x77, 0xd9, 0x0e, 0xc7, 0x2d, 0xea, - 0xce, 0x60, 0x54, 0x9a, 0xc9, 0x43, 0x25, 0xf5, 0xe3, 0x43, 0x8e, 0xc1, - 0x5c, 0x44, 0x9d, 0xf1, 0x56, 0xe6, 0xec, 0xdf, 0xd1, 0x73, 0x6b, 0xa2, - 0x4f, 0x80, 0x6b, 0xf0, 0xc9, 0xe7, 0xf2, 0xbd, 0xcc, 0xf5, 0x62, 0xfd, - 0x46, 0xae, 0xef, 0x7a, 0xe7, 0x9c, 0x70, 0xb3, 0xd6, 0x7d, 0x92, 0x39, - 0x6f, 0xf8, 0x6f, 0xc8, 0x01, 0xef, 0x35, 0xa3, 0x3d, 0x4f, 0x9b, 0xf0, - 0x45, 0xeb, 0xf8, 0xb6, 0xa1, 0x4b, 0x6d, 0xc3, 0x89, 0x3c, 0xf9, 0x93, - 0x7c, 0xe9, 0xf3, 0xa3, 0xaf, 0xf3, 0xc8, 0xa3, 0xd4, 0xb3, 0xfd, 0x72, - 0x26, 0xcf, 0xb3, 0x49, 0x69, 0x4d, 0x6b, 0xe3, 0xd9, 0x71, 0xc5, 0x64, - 0x75, 0x4e, 0x25, 0x5e, 0xce, 0xca, 0xa0, 0x5c, 0x71, 0x79, 0x66, 0x89, - 0x42, 0x3a, 0xd8, 0x54, 0xf1, 0xfe, 0xfb, 0xf5, 0xcc, 0xc2, 0xea, 0x33, - 0xc6, 0x30, 0xf7, 0x79, 0x8f, 0xde, 0xcd, 0x7a, 0xb6, 0xe9, 0x2a, 0xfa, - 0x7c, 0x53, 0xcf, 0x29, 0x0c, 0x9d, 0xc8, 0xfa, 0x7e, 0x38, 0xc2, 0x7b, - 0xf8, 0x5c, 0xfa, 0x7c, 0x7c, 0x16, 0x79, 0xaf, 0x13, 0x16, 0xbb, 0x57, - 0x82, 0x3b, 0x20, 0xfa, 0x3b, 0x58, 0x47, 0x0e, 0x40, 0x56, 0x37, 0x1a, - 0x0c, 0xcc, 0x98, 0xf1, 0x35, 0xd2, 0xd6, 0x55, 0x9c, 0x23, 0x62, 0x15, - 0xf8, 0xd1, 0x27, 0x5e, 0xba, 0x8d, 0xf5, 0xd2, 0x9e, 0xbf, 0xde, 0x87, - 0xf5, 0x1d, 0xaf, 0xae, 0x3e, 0xb9, 0x8d, 0xbc, 0x3a, 0xa2, 0xf5, 0x41, - 0xde, 0x43, 0x39, 0xe6, 0x99, 0x91, 0x2e, 0xef, 0xe3, 0x7e, 0xb6, 0xb7, - 0xd4, 0xd0, 0x31, 0xe9, 0xed, 0xcf, 0x1f, 0x0f, 0x4b, 0xb8, 0x95, 0x3a, - 0x2e, 0x2a, 0xc9, 0x29, 0xc6, 0x2c, 0xb0, 0x5d, 0x63, 0x5c, 0xeb, 0xcb, - 0x75, 0x71, 0xfa, 0xff, 0xd4, 0xc5, 0x69, 0xeb, 0x23, 0xe5, 0x9d, 0xb0, - 0xe6, 0xb1, 0xbe, 0x98, 0xae, 0x85, 0x2a, 0xba, 0xfa, 0xb5, 0xfb, 0x68, - 0x99, 0x8e, 0x3f, 0xc9, 0xd3, 0x5e, 0xa5, 0x34, 0xa7, 0xfc, 0xb7, 0x49, - 0x9e, 0x2d, 0xf7, 0x78, 0x85, 0x7b, 0x1c, 0x5c, 0x74, 0x89, 0x83, 0xf9, - 0x96, 0xca, 0xf0, 0xa9, 0x3c, 0x75, 0x4c, 0x93, 0xcc, 0x4d, 0xfb, 0x7a, - 0x66, 0xd4, 0xf3, 0x71, 0x73, 0x6b, 0xeb, 0x54, 0xcf, 0xc0, 0xbb, 0x71, - 0x86, 0x3d, 0xfb, 0xd2, 0x21, 0xb3, 0xe7, 0x69, 0x77, 0x93, 0xe8, 0x8b, - 0x06, 0x66, 0xe7, 0x59, 0x9b, 0x24, 0x16, 0x65, 0x50, 0x58, 0xf7, 0x1f, - 0xb6, 0x4f, 0x40, 0xde, 0x62, 0xf2, 0xe1, 0x24, 0x7d, 0xfa, 0x3a, 0xf8, - 0xc6, 0xcd, 0x35, 0xe7, 0xbb, 0xbd, 0xec, 0x13, 0x56, 0xd3, 0xbd, 0xa3, - 0x4d, 0x1a, 0xc9, 0xe7, 0x8e, 0x7d, 0x5d, 0xe8, 0x83, 0xf1, 0x3a, 0x83, - 0x58, 0x80, 0xb1, 0x47, 0x5c, 0x63, 0x8f, 0xd9, 0x02, 0xfb, 0x9a, 0xbc, - 0xbc, 0x52, 0x93, 0xf2, 0x0a, 0xf9, 0x2d, 0xad, 0xfe, 0xf7, 0x80, 0xea, - 0xac, 0xdc, 0x64, 0xb7, 0xc1, 0xb1, 0xd8, 0x31, 0xe5, 0x3d, 0xa9, 0xe2, - 0xbd, 0x98, 0xef, 0x4b, 0xb6, 0x19, 0xdf, 0xca, 0x56, 0x7d, 0x13, 0xd6, - 0x79, 0xb4, 0x2b, 0x5c, 0x9f, 0xbc, 0x41, 0x1e, 0xa1, 0xce, 0xf3, 0xe7, - 0xf9, 0xf4, 0xf0, 0xdb, 0x9c, 0x4f, 0xfe, 0xaf, 0xc4, 0x22, 0xf8, 0xb2, - 0xea, 0xf7, 0xf9, 0x72, 0xc7, 0xb1, 0x4a, 0x9b, 0x40, 0xb9, 0xab, 0xac, - 0x4f, 0xda, 0x12, 0x99, 0x5a, 0xa6, 0xcb, 0x50, 0x2f, 0xf7, 0xff, 0x3c, - 0x73, 0xbb, 0x90, 0xb7, 0x95, 0x68, 0x73, 0x4c, 0x69, 0x93, 0x06, 0x6d, - 0x22, 0x4a, 0x1b, 0xc6, 0x7b, 0x4f, 0x79, 0xfc, 0xd6, 0x84, 0xf3, 0x62, - 0xae, 0x16, 0xba, 0x6e, 0x1f, 0x75, 0xfe, 0x33, 0x6d, 0x5a, 0x1f, 0x74, - 0xa8, 0xfb, 0x56, 0x43, 0x9f, 0xb1, 0xbd, 0x59, 0xfd, 0x11, 0x13, 0x6f, - 0xc5, 0x35, 0x0f, 0x1a, 0x84, 0x7e, 0x9e, 0x9d, 0x84, 0xaf, 0x46, 0xdc, - 0x5b, 0x15, 0xad, 0x1e, 0xf7, 0xce, 0xeb, 0x55, 0xa5, 0x0d, 0x65, 0x80, - 0x7a, 0x73, 0x0d, 0xd6, 0xdb, 0x13, 0xed, 0x01, 0x7f, 0xbd, 0x82, 0xfe, - 0x8d, 0x1a, 0x4f, 0x04, 0x21, 0xf3, 0x37, 0x26, 0x5b, 0xbd, 0x18, 0xce, - 0x41, 0x1b, 0x71, 0xeb, 0x64, 0x84, 0x31, 0x05, 0xda, 0x5d, 0x52, 0x37, - 0x85, 0xf8, 0x15, 0x7a, 0x7c, 0x51, 0xed, 0x51, 0x0f, 0xc6, 0xef, 0x20, - 0xce, 0x0f, 0xd7, 0x87, 0x71, 0x5f, 0xb7, 0xc1, 0x22, 0x44, 0x37, 0xe9, - 0x99, 0xce, 0x4e, 0x26, 0x62, 0x87, 0xc4, 0xeb, 0x1b, 0x73, 0x55, 0x1f, - 0x2c, 0xef, 0xeb, 0x01, 0xd9, 0x53, 0xb6, 0x17, 0x8c, 0xa3, 0xe1, 0xc3, - 0x4f, 0x1b, 0x7b, 0x90, 0x2b, 0xf4, 0x28, 0x3e, 0x2a, 0x38, 0xb0, 0x80, - 0xb3, 0xa4, 0x4f, 0xba, 0x04, 0x3f, 0xdc, 0xc5, 0x19, 0xd2, 0xef, 0x2e, - 0x1d, 0x3f, 0xe9, 0xa6, 0x58, 0x1f, 0x83, 0x3e, 0x38, 0x2e, 0xc3, 0x88, - 0x0b, 0x86, 0x83, 0xcd, 0xcc, 0x2b, 0xc3, 0x37, 0xcc, 0x7a, 0xb9, 0xc7, - 0x1e, 0xe6, 0x4c, 0xe5, 0xec, 0x3c, 0xf7, 0x4e, 0xd9, 0x36, 0xb1, 0xf7, - 0xec, 0x24, 0xf7, 0x6b, 0xf2, 0x10, 0x6c, 0x5b, 0x53, 0x2e, 0x7e, 0x79, - 0x16, 0x7d, 0xf8, 0xed, 0x87, 0x3c, 0x70, 0x2e, 0x7e, 0xe7, 0x97, 0xe4, - 0xbd, 0xf3, 0xbe, 0x6d, 0x0f, 0xc8, 0xbb, 0x4e, 0xe9, 0xf8, 0x09, 0x77, - 0x2d, 0xcf, 0xc0, 0xcd, 0xb2, 0x66, 0xed, 0x38, 0x6e, 0x4e, 0x4a, 0xa5, - 0x45, 0x77, 0x71, 0xad, 0xa5, 0xb4, 0xa4, 0xfc, 0x7f, 0x80, 0x33, 0xbc, - 0x76, 0xaf, 0x25, 0x86, 0x7e, 0xa4, 0xcd, 0xe7, 0x6b, 0x7f, 0x95, 0xb6, - 0xc0, 0xd7, 0x7f, 0xe4, 0x47, 0xf2, 0xe5, 0x92, 0xec, 0x54, 0xfd, 0xbf, - 0xd2, 0x7d, 0x95, 0xba, 0xdf, 0xf7, 0x6f, 0xa9, 0xdf, 0xc9, 0x8b, 0x31, - 0x8d, 0x0f, 0x36, 0x4d, 0xd5, 0xea, 0x84, 0x1f, 0x78, 0x75, 0x85, 0x95, - 0x78, 0xef, 0x80, 0xa7, 0x17, 0x52, 0xea, 0x3b, 0xa7, 0x6c, 0xea, 0x07, - 0xee, 0xa7, 0x51, 0xc6, 0x67, 0x6e, 0x83, 0x26, 0xbe, 0x0e, 0x66, 0xdc, - 0xe7, 0xeb, 0x8e, 0x66, 0xcf, 0x17, 0xb6, 0xa4, 0xf3, 0x2c, 0x7d, 0x27, - 0x07, 0x7a, 0xb4, 0x45, 0xd2, 0x63, 0x41, 0x49, 0x9e, 0x6d, 0x89, 0x19, - 0x5f, 0x97, 0xfc, 0x07, 0x79, 0xd3, 0x3e, 0xb6, 0x37, 0xa0, 0xff, 0x4e, - 0xe1, 0xb3, 0x0d, 0x3f, 0x43, 0x9e, 0xf7, 0xf9, 0x63, 0x76, 0x0d, 0x8f, - 0xee, 0xf0, 0x78, 0x94, 0xe3, 0x96, 0xa9, 0x7f, 0x60, 0x6e, 0xe7, 0x59, - 0xee, 0xd1, 0xdc, 0xd7, 0x79, 0xd6, 0xc4, 0xeb, 0xd5, 0xf7, 0xf5, 0x94, - 0xef, 0xc3, 0x78, 0x97, 0x62, 0xc3, 0xb0, 0xf6, 0xce, 0x7e, 0xf8, 0x74, - 0x3d, 0xb4, 0x39, 0xb4, 0xdf, 0x1b, 0xdd, 0x9d, 0x42, 0x7e, 0x4f, 0x78, - 0x3c, 0x47, 0x7d, 0x13, 0xf1, 0xf4, 0xcd, 0xb2, 0x7d, 0x19, 0x36, 0xf8, - 0x13, 0xe6, 0x44, 0x2a, 0xec, 0xcb, 0x43, 0xe6, 0xdd, 0xaa, 0xec, 0xcb, - 0x9d, 0xde, 0x3a, 0xfe, 0x98, 0xaf, 0x57, 0xfc, 0xb6, 0xaf, 0x57, 0x6a, - 0x7d, 0x5a, 0x9f, 0xf6, 0xd5, 0xb8, 0xaf, 0xca, 0x98, 0x2f, 0xb7, 0x62, - 0xde, 0x25, 0x83, 0x98, 0x8d, 0x3e, 0x65, 0x22, 0x6b, 0x30, 0xd3, 0xd6, - 0x19, 0x8b, 0xb8, 0x0f, 0xe7, 0x67, 0x32, 0x14, 0xb9, 0xad, 0xb1, 0xf5, - 0xa9, 0x99, 0x51, 0xcd, 0xf3, 0xcc, 0xba, 0x9e, 0xde, 0x89, 0xee, 0x86, - 0x5c, 0xcd, 0x47, 0x96, 0x31, 0x45, 0x4f, 0x1e, 0x1b, 0x82, 0x1d, 0x4a, - 0x69, 0xbd, 0xec, 0x71, 0xec, 0xb7, 0x5f, 0xf1, 0x5c, 0xab, 0x9c, 0xe7, - 0x64, 0x97, 0x5d, 0xd2, 0xda, 0x4d, 0xc3, 0x40, 0xf6, 0x58, 0xc3, 0x69, - 0x9f, 0xef, 0xc9, 0x4f, 0x4f, 0x1e, 0x1b, 0x9f, 0x2e, 0x0d, 0x86, 0xb6, - 0x75, 0xdb, 0x39, 0x59, 0x0f, 0x9a, 0x0f, 0xca, 0xa3, 0x8a, 0x1d, 0x7e, - 0x0d, 0xe3, 0xfb, 0x18, 0x5f, 0x26, 0x42, 0x8a, 0x09, 0x4e, 0xc4, 0x26, - 0x20, 0x8b, 0x19, 0x37, 0xd1, 0x35, 0x14, 0x5c, 0xcd, 0xdc, 0x0d, 0x62, - 0x66, 0xfa, 0x59, 0xc4, 0x14, 0x3c, 0x2b, 0x87, 0xdc, 0x8d, 0xee, 0xa2, - 0x64, 0x3d, 0x4c, 0x3e, 0x6b, 0x42, 0xf5, 0x32, 0xe1, 0x86, 0x1a, 0x86, - 0x8a, 0x46, 0x06, 0x46, 0x82, 0xa9, 0x55, 0x27, 0x9d, 0x68, 0xc3, 0xce, - 0x22, 0x64, 0xbc, 0x08, 0xfd, 0x5f, 0x8c, 0x05, 0x86, 0x15, 0x9b, 0xf6, - 0x55, 0x19, 0x6a, 0xa5, 0x9f, 0x4f, 0x7d, 0xf2, 0x35, 0xb9, 0x61, 0x6f, - 0x96, 0x1b, 0x5d, 0xc4, 0x63, 0xf6, 0xa2, 0x4d, 0x5d, 0xd2, 0x8f, 0xbe, - 0x24, 0xfa, 0x1a, 0x94, 0x1f, 0x35, 0x3e, 0x83, 0xce, 0xba, 0x61, 0x53, - 0x57, 0xdd, 0xc5, 0x5f, 0xbc, 0xeb, 0x9f, 0x41, 0x13, 0x62, 0x3b, 0xb6, - 0xa0, 0x4d, 0x1d, 0x67, 0xd7, 0xf4, 0xb7, 0xa3, 0x7d, 0x2f, 0xd6, 0xa8, - 0xd3, 0xf7, 0xb3, 0x9c, 0x6d, 0xa6, 0xce, 0x59, 0x35, 0x67, 0x4d, 0x4d, - 0xfb, 0xdd, 0x16, 0x83, 0x4f, 0xb8, 0x45, 0x7a, 0x67, 0x53, 0xb2, 0xab, - 0xad, 0xba, 0xfd, 0xcf, 0x9a, 0x76, 0xb3, 0xac, 0x6a, 0x21, 0x19, 0x9e, - 0x68, 0xad, 0xee, 0xf7, 0xf9, 0xc9, 0x6f, 0xb7, 0xe1, 0x7d, 0x13, 0x30, - 0x78, 0x49, 0x8d, 0xa5, 0x6e, 0x44, 0xf9, 0xac, 0xbf, 0xd6, 0xdc, 0xc3, - 0x6b, 0xde, 0xc3, 0x7b, 0x99, 0xd7, 0xfb, 0x37, 0xfb, 0x71, 0x0f, 0x73, - 0x02, 0xcc, 0x6b, 0x90, 0x67, 0x57, 0x8a, 0xb3, 0x38, 0xe7, 0xf3, 0xf9, - 0x86, 0x74, 0x99, 0xf7, 0x7c, 0xbd, 0x12, 0x2b, 0x63, 0xd5, 0x76, 0xe6, - 0xfd, 0x9c, 0x30, 0x69, 0xa7, 0x35, 0xa9, 0xd8, 0x75, 0xd0, 0xf9, 0x20, - 0xe8, 0xfc, 0x40, 0x90, 0x71, 0x61, 0xa3, 0x47, 0x6b, 0x47, 0x86, 0x8b, - 0x6f, 0x43, 0xc6, 0xc9, 0xa3, 0xf0, 0x29, 0x8a, 0x96, 0x87, 0xcf, 0xe8, - 0x83, 0x4d, 0x73, 0x25, 0xa8, 0x79, 0x07, 0xc4, 0xf7, 0x73, 0xd7, 0x64, - 0x78, 0x92, 0x39, 0x01, 0xf2, 0x33, 0xe3, 0xfa, 0x14, 0xc6, 0x6e, 0x62, - 0xae, 0x0b, 0x19, 0x1e, 0x05, 0xbf, 0x86, 0xc4, 0x99, 0xda, 0x22, 0xd9, - 0xb1, 0x51, 0xf5, 0x01, 0x3a, 0x61, 0xa3, 0x4e, 0xb8, 0x23, 0x72, 0xf2, - 0xf2, 0xdd, 0x90, 0x55, 0xc6, 0xfd, 0x9a, 0xd3, 0x28, 0x85, 0xd5, 0x37, - 0xa7, 0xcf, 0xc1, 0x3c, 0x9c, 0xa9, 0x31, 0x1b, 0xb9, 0x7d, 0x24, 0x26, - 0xcd, 0x23, 0x32, 0x3d, 0x63, 0x2b, 0xde, 0x25, 0x25, 0xb7, 0x4b, 0xa4, - 0x5d, 0x66, 0x5f, 0x1c, 0xba, 0x8a, 0xbe, 0x7c, 0x2e, 0x62, 0xce, 0x72, - 0x74, 0x1d, 0x63, 0xe2, 0xe4, 0x54, 0xe5, 0x1a, 0x8a, 0x91, 0xc1, 0xd8, - 0xa5, 0x16, 0x23, 0x33, 0x8c, 0x8f, 0x3f, 0x2a, 0xa5, 0xa2, 0x7c, 0x26, - 0xe7, 0xb2, 0x76, 0x4b, 0x1e, 0xe1, 0xde, 0xfe, 0xe3, 0xf1, 0xf2, 0x4b, - 0x58, 0x2f, 0x2e, 0x9d, 0xaf, 0x8f, 0x6a, 0x5c, 0x7f, 0xa2, 0x2a, 0x86, - 0x35, 0xf9, 0x02, 0x13, 0xc7, 0x5e, 0x93, 0x89, 0x05, 0xd2, 0x87, 0x36, - 0x3e, 0x20, 0x3f, 0x77, 0xba, 0xed, 0xc7, 0xb4, 0xd6, 0x98, 0x48, 0xb1, - 0x3e, 0xd3, 0xe8, 0x24, 0xed, 0x39, 0x09, 0xf5, 0x7f, 0x03, 0xd7, 0x8c, - 0x6b, 0x73, 0x6e, 0xb7, 0xfb, 0x98, 0xf8, 0x38, 0x90, 0x8d, 0xa9, 0xfa, - 0xc0, 0xad, 0xd2, 0xb5, 0x7d, 0x9c, 0x63, 0x70, 0x20, 0x12, 0x20, 0xad, - 0x3e, 0xb8, 0x8b, 0xf8, 0x99, 0xea, 0xfc, 0xdf, 0xfd, 0x47, 0xf6, 0xf6, - 0x25, 0x5e, 0x64, 0x0c, 0x1b, 0x76, 0x0e, 0xac, 0x33, 0xef, 0x9a, 0xcd, - 0xae, 0x11, 0xad, 0x9f, 0x1d, 0xfd, 0xbb, 0x43, 0x3c, 0x44, 0x22, 0x56, - 0x6f, 0x31, 0x0f, 0x4e, 0x1d, 0xc7, 0x9a, 0x0a, 0x73, 0x6e, 0xc4, 0xf2, - 0x37, 0xc8, 0xa5, 0x1e, 0x4b, 0xee, 0x0f, 0xa5, 0xe2, 0x96, 0x6c, 0x8a, - 0x9f, 0x15, 0x3c, 0x93, 0xf5, 0x95, 0x85, 0x44, 0x96, 0xf3, 0x43, 0x53, - 0x5c, 0x2f, 0xae, 0xf1, 0x4a, 0x72, 0x53, 0xa9, 0xf4, 0x94, 0x2b, 0x81, - 0xe4, 0xd6, 0x8f, 0x4b, 0xac, 0x85, 0x5b, 0xaf, 0x7f, 0x11, 0x4e, 0x41, - 0xbf, 0x1d, 0x98, 0x30, 0x98, 0xc3, 0x89, 0xa3, 0x9d, 0x0b, 0x6c, 0xa7, - 0x77, 0x99, 0xf6, 0x61, 0xb4, 0xeb, 0x3c, 0xac, 0xd3, 0x0f, 0x8f, 0x76, - 0x16, 0x9e, 0x58, 0x67, 0xe2, 0xef, 0x25, 0xc5, 0x7f, 0xbd, 0x53, 0x15, - 0xd3, 0xa4, 0x02, 0x63, 0xf9, 0xd1, 0xc0, 0x68, 0xde, 0xea, 0x69, 0x00, - 0xad, 0xe6, 0x5d, 0xe6, 0x6a, 0xfc, 0x9c, 0x15, 0xf3, 0xfd, 0x22, 0x4f, - 0x2a, 0x46, 0x8a, 0x35, 0x45, 0x4b, 0x7d, 0xa1, 0x83, 0xf3, 0xcc, 0xf1, - 0x47, 0x54, 0x1f, 0x1c, 0x5a, 0x68, 0x96, 0x9c, 0xbd, 0x56, 0x72, 0x2a, - 0xe3, 0x51, 0xd5, 0x01, 0x96, 0xb3, 0x15, 0x7d, 0xdc, 0xf7, 0x43, 0x8a, - 0x8b, 0x78, 0x23, 0xdf, 0x8e, 0x36, 0x73, 0xcd, 0xdb, 0x6b, 0xfa, 0x2b, - 0xeb, 0xb2, 0x09, 0xdb, 0xb2, 0x6a, 0x6b, 0xb2, 0xec, 0xab, 0xad, 0xc5, - 0x9e, 0x92, 0x6b, 0xe4, 0x9b, 0xa2, 0x9f, 0x73, 0x77, 0xbd, 0x9c, 0xfb, - 0xf7, 0xb1, 0x26, 0xd7, 0x96, 0x74, 0x68, 0xa0, 0xa1, 0xe7, 0xc4, 0x64, - 0xf0, 0xe6, 0x72, 0xfe, 0x14, 0xed, 0x85, 0x72, 0xad, 0x1c, 0x63, 0xcf, - 0xc0, 0x17, 0xc9, 0xc1, 0xaf, 0xc8, 0x7a, 0xdf, 0x1f, 0x70, 0xbc, 0x7c, - 0xff, 0x97, 0xec, 0xa9, 0x51, 0xeb, 0xec, 0x56, 0x55, 0x9d, 0xfd, 0x7b, - 0xb8, 0x97, 0x35, 0xf6, 0x6c, 0xa9, 0x0e, 0xbc, 0x5b, 0x47, 0x9c, 0x48, - 0x79, 0x3e, 0x75, 0xbc, 0xea, 0x72, 0x5d, 0x6b, 0xa7, 0xb7, 0x56, 0x10, - 0x7a, 0x7e, 0x7c, 0xd2, 0x9f, 0x73, 0x5c, 0xea, 0x7b, 0x13, 0xb1, 0xa0, - 0xc5, 0x39, 0x46, 0xdf, 0x0f, 0xb9, 0xc7, 0xa1, 0xc7, 0xa9, 0xf3, 0xf9, - 0xde, 0x0e, 0x7c, 0x3d, 0xea, 0x02, 0xea, 0x73, 0xb5, 0x01, 0xf1, 0x1c, - 0x74, 0xfd, 0x70, 0xd1, 0x7c, 0xeb, 0xf5, 0xf5, 0x60, 0x62, 0x3a, 0xa3, - 0xba, 0x01, 0xfe, 0x5e, 0xf1, 0x0d, 0xe6, 0x83, 0x5e, 0x94, 0x40, 0x65, - 0x9d, 0x86, 0xb1, 0x19, 0x6b, 0x1a, 0x4d, 0xd0, 0x0d, 0x22, 0x57, 0xc0, - 0x1b, 0x57, 0xe7, 0xc9, 0xaf, 0xc1, 0x56, 0x13, 0x5f, 0x2d, 0x6e, 0xb7, - 0xa4, 0x55, 0x6b, 0x9f, 0x39, 0x27, 0x42, 0xff, 0x64, 0x30, 0xd9, 0x0b, - 0x3f, 0x5b, 0xb1, 0x07, 0xcc, 0x57, 0x8e, 0x23, 0x1e, 0xab, 0xcc, 0xb1, - 0x40, 0xbe, 0xc6, 0xd8, 0x9f, 0x81, 0x5f, 0xb9, 0x5c, 0xf7, 0xc8, 0x15, - 0x4e, 0x6a, 0x6e, 0x73, 0x76, 0xbe, 0x49, 0x75, 0xec, 0x6c, 0x61, 0x04, - 0xe7, 0x22, 0x9b, 0xad, 0x81, 0x9c, 0xd7, 0x1f, 0x96, 0x42, 0x81, 0x6d, - 0xe9, 0xa8, 0xd3, 0x73, 0xf7, 0x6b, 0x3b, 0xb6, 0xcc, 0xc1, 0x57, 0x2c, - 0x2c, 0x38, 0xf8, 0xef, 0xc2, 0x7f, 0x0f, 0xfe, 0x77, 0xcb, 0xd0, 0x14, - 0xfd, 0x57, 0xd6, 0x72, 0x9a, 0x6a, 0x9e, 0x4f, 0x1f, 0xa9, 0x43, 0x71, - 0x60, 0x39, 0x2f, 0xce, 0xc9, 0x15, 0x6a, 0xe5, 0x84, 0x79, 0x52, 0x5f, - 0x47, 0x30, 0x5f, 0xea, 0xd7, 0xfa, 0x2a, 0x6b, 0x58, 0x96, 0x57, 0xf7, - 0x22, 0x4f, 0x37, 0xca, 0xa1, 0x82, 0x5f, 0xbb, 0x8a, 0xc9, 0xa3, 0xe5, - 0xda, 0x95, 0xa4, 0x83, 0x03, 0xb7, 0x1e, 0xcc, 0x4c, 0x2a, 0x9e, 0xc0, - 0xb2, 0x06, 0xae, 0x3d, 0x38, 0xb1, 0xf0, 0xee, 0x83, 0xcb, 0x98, 0x70, - 0x8c, 0x2d, 0xac, 0x84, 0x19, 0x22, 0x96, 0xee, 0x33, 0xf2, 0x10, 0x0d, - 0x27, 0xf6, 0xed, 0xc7, 0x3c, 0xc4, 0xd9, 0x6d, 0xb0, 0x97, 0xf1, 0xcb, - 0x7e, 0x3c, 0x4a, 0x1c, 0x29, 0xef, 0xab, 0xc4, 0x7e, 0x84, 0x70, 0xfe, - 0x12, 0xb0, 0x9c, 0x2c, 0xf6, 0x71, 0xa1, 0xdd, 0xf8, 0x81, 0xc4, 0x99, - 0x26, 0x2a, 0xb0, 0x47, 0x3e, 0xd6, 0xf4, 0x65, 0xac, 0x95, 0x96, 0xdf, - 0x14, 0x1f, 0x96, 0x5f, 0x16, 0x47, 0x21, 0xdf, 0x13, 0x58, 0xf3, 0x80, - 0xfc, 0xa2, 0xb8, 0x4f, 0xde, 0x2a, 0x8e, 0xc9, 0x9b, 0xc5, 0xdd, 0x88, - 0xa9, 0x46, 0x88, 0xf5, 0xf4, 0xb0, 0xd2, 0x83, 0x32, 0x7e, 0x4e, 0x31, - 0x80, 0x37, 0xe9, 0xf7, 0x1c, 0x55, 0x3f, 0x9b, 0xf8, 0xfa, 0xc4, 0xaf, - 0x18, 0xcf, 0x13, 0x9b, 0x59, 0x28, 0xfa, 0x18, 0x8e, 0x89, 0x0e, 0x3c, - 0xdb, 0xe6, 0xb7, 0x29, 0xc3, 0xe7, 0x22, 0x81, 0x91, 0x73, 0xa1, 0xc0, - 0x03, 0xfa, 0x9d, 0x0b, 0xeb, 0x9d, 0x25, 0x39, 0xe9, 0x3a, 0xe4, 0xcd, - 0xfe, 0x61, 0xc8, 0xc2, 0x08, 0x54, 0xfd, 0x2e, 0x67, 0xad, 0x80, 0xa4, - 0xa9, 0x4f, 0xe0, 0x67, 0x26, 0x4f, 0xbb, 0x92, 0xc9, 0xcf, 0x05, 0x0c, - 0x1e, 0xcd, 0x46, 0xbb, 0x07, 0xed, 0x57, 0xbd, 0xf6, 0x0e, 0xc9, 0xcc, - 0x48, 0xea, 0x43, 0xf5, 0x87, 0x5f, 0xf1, 0xfa, 0xfa, 0xd1, 0x07, 0xce, - 0xbc, 0xc0, 0xbe, 0x0b, 0x5e, 0x1f, 0xcf, 0x84, 0xb5, 0xfa, 0xb8, 0xf2, - 0x55, 0xc6, 0x1e, 0x13, 0xfd, 0xae, 0x41, 0x6b, 0xf1, 0x4b, 0xed, 0x46, - 0xb7, 0x11, 0x13, 0xf8, 0x8f, 0x76, 0xc6, 0x60, 0x05, 0xc8, 0xd7, 0x5d, - 0xd0, 0x89, 0x7f, 0xd9, 0xbc, 0xdc, 0xb6, 0x06, 0x3e, 0xad, 0xc0, 0x68, - 0x7f, 0x2a, 0x9d, 0x0b, 0xff, 0xf2, 0xf0, 0xbc, 0x07, 0xf1, 0x6e, 0x38, - 0xab, 0x3c, 0x71, 0xe3, 0x71, 0xc8, 0x76, 0x93, 0xac, 0x3d, 0x43, 0x7a, - 0x75, 0x43, 0x57, 0xa7, 0x20, 0xb7, 0xae, 0xcc, 0x17, 0x43, 0x81, 0xe1, - 0x7c, 0x4a, 0x0c, 0x9e, 0xda, 0x92, 0x74, 0x34, 0x25, 0xa7, 0xfa, 0x12, - 0x5d, 0xcc, 0x43, 0x66, 0x7a, 0x5d, 0xb9, 0x58, 0xa4, 0x3d, 0xce, 0xca, - 0xa5, 0xbe, 0x84, 0x5b, 0x10, 0xe2, 0x62, 0x5c, 0xb9, 0x04, 0xd9, 0xfc, - 0xdd, 0xb9, 0xdd, 0xf2, 0x68, 0x5e, 0xfd, 0xe0, 0xee, 0xb0, 0xbc, 0x20, - 0x17, 0xfb, 0x5e, 0xb8, 0x79, 0xd1, 0x7d, 0x04, 0x67, 0x4a, 0x3e, 0xcc, - 0x74, 0x98, 0x7d, 0x2b, 0x0e, 0x49, 0x98, 0x0f, 0xd1, 0x9a, 0x9a, 0x53, - 0x2f, 0x43, 0xfb, 0x23, 0x5e, 0x5c, 0x0e, 0x9f, 0x3b, 0xe0, 0x9a, 0x7a, - 0x4a, 0xc0, 0xdf, 0x67, 0x18, 0x7e, 0x0c, 0xef, 0xf3, 0x69, 0xe3, 0xaf, - 0xd3, 0x1e, 0x18, 0x9a, 0x69, 0x96, 0xd0, 0x85, 0xaf, 0x80, 0xae, 0x21, - 0x39, 0xd8, 0x5b, 0x2a, 0x7d, 0xc7, 0x0d, 0xc5, 0x27, 0x10, 0xa3, 0x60, - 0xff, 0xb2, 0xe6, 0x74, 0x0b, 0x68, 0xd2, 0x20, 0xd1, 0xd3, 0xfe, 0xf3, - 0xea, 0x3d, 0x2c, 0xc3, 0x99, 0x35, 0xc6, 0x96, 0xf9, 0xd8, 0x06, 0x7f, - 0x3d, 0x83, 0x29, 0xeb, 0xb4, 0x7a, 0x03, 0xde, 0x77, 0x12, 0x5e, 0x7b, - 0x6b, 0xe0, 0xfe, 0x50, 0xab, 0x84, 0x9c, 0x67, 0xd7, 0x13, 0x1b, 0xb9, - 0x98, 0xf7, 0xfb, 0xe1, 0x27, 0x86, 0x7c, 0x7f, 0x58, 0xb6, 0x2d, 0x9f, - 0xb5, 0x6c, 0xeb, 0x5c, 0xf8, 0xae, 0xb7, 0x66, 0xca, 0x9b, 0x8b, 0x98, - 0x23, 0xb6, 0x5a, 0xed, 0x93, 0x99, 0xfb, 0x5f, 0x79, 0xba, 0x37, 0xf1, - 0x9a, 0xe2, 0x64, 0xcb, 0xf7, 0x70, 0x1c, 0x31, 0x64, 0x51, 0xef, 0x89, - 0xed, 0x01, 0x7d, 0xd3, 0xb1, 0x7b, 0xec, 0x39, 0x2b, 0x18, 0x30, 0xfe, - 0x48, 0x9d, 0xfc, 0x28, 0x0a, 0xbb, 0xcd, 0x6f, 0x58, 0x98, 0xff, 0x72, - 0x6f, 0x7b, 0x7e, 0x0a, 0xfb, 0x12, 0x2f, 0x26, 0xad, 0x34, 0xf6, 0xc7, - 0x33, 0x20, 0x06, 0xd4, 0x02, 0x9d, 0xda, 0xf1, 0x7e, 0x88, 0x9f, 0x7a, - 0xfd, 0xf7, 0x5f, 0x03, 0x1d, 0xc6, 0xfd, 0x1b, 0x5c, 0x98, 0x58, 0xcc, - 0x85, 0x0c, 0x7a, 0x18, 0xd8, 0x4a, 0xb9, 0xf5, 0xb1, 0xb1, 0x3e, 0x9e, - 0x8e, 0x18, 0xa5, 0x18, 0xfc, 0x40, 0xca, 0x04, 0x79, 0xb3, 0x0d, 0xfd, - 0xab, 0x6e, 0xa5, 0xf4, 0xd5, 0xfd, 0xbe, 0x8f, 0xcb, 0xd8, 0xee, 0x89, - 0xfc, 0x3e, 0x83, 0xcd, 0xb3, 0x96, 0x24, 0xd5, 0x91, 0xb4, 0x4f, 0x62, - 0xbf, 0x43, 0xa1, 0x44, 0x21, 0x2b, 0x31, 0x99, 0x83, 0xbe, 0xb8, 0x0a, - 0xd9, 0x7f, 0xab, 0xc8, 0xef, 0x6d, 0x53, 0x72, 0x28, 0x0f, 0x83, 0x3e, - 0xa3, 0xdf, 0x7e, 0x41, 0xef, 0x0f, 0xc8, 0x6c, 0x3e, 0xd1, 0x35, 0x07, - 0xfe, 0x9b, 0xcb, 0x13, 0x5f, 0xd4, 0x1d, 0x1f, 0xc1, 0x8a, 0x8b, 0xf9, - 0x8d, 0xb0, 0x0f, 0x92, 0xba, 0x08, 0xff, 0xe7, 0x62, 0xb1, 0x0b, 0x7c, - 0x86, 0xf1, 0xa2, 0x83, 0x5f, 0xe8, 0xcc, 0x62, 0x1f, 0xe4, 0x9c, 0x7b, - 0xb1, 0x65, 0x7e, 0x33, 0xce, 0x8e, 0x38, 0x22, 0xc5, 0x8f, 0x7f, 0x86, - 0xf3, 0xf5, 0xdf, 0x7b, 0xbb, 0xda, 0xe9, 0x39, 0xdd, 0x17, 0xec, 0x32, - 0x62, 0x80, 0x4c, 0xaf, 0xb1, 0xdb, 0x43, 0x91, 0x16, 0x19, 0xba, 0x87, - 0x76, 0xbc, 0x55, 0x63, 0x44, 0xe5, 0xc5, 0x08, 0xc7, 0x7f, 0xbb, 0xde, - 0xd0, 0x2f, 0x5c, 0xd3, 0x7e, 0x1b, 0xbf, 0xcd, 0xd2, 0xe6, 0xf0, 0xd7, - 0xc6, 0xef, 0xb5, 0xf5, 0xac, 0xef, 0xb6, 0x39, 0x49, 0x3c, 0xeb, 0xd7, - 0x5e, 0xbe, 0x00, 0xd7, 0x73, 0xbc, 0x67, 0x9d, 0xf7, 0x5c, 0xae, 0xdb, - 0x8c, 0x75, 0x9a, 0xbc, 0x67, 0x35, 0x6b, 0x7e, 0xd2, 0x3c, 0x0b, 0x31, - 0x6e, 0xfe, 0x4f, 0xeb, 0x79, 0x86, 0xfc, 0xde, 0xb8, 0xba, 0xfd, 0xc7, - 0xf5, 0xc4, 0xcd, 0xb5, 0x39, 0xcd, 0x8a, 0xf1, 0xbc, 0xd1, 0xda, 0x8a, - 0x6b, 0x3e, 0x93, 0x73, 0x4c, 0x3e, 0x7c, 0xb6, 0xc8, 0xf5, 0xd9, 0x4e, - 0xc9, 0x31, 0xcd, 0x67, 0x18, 0x2c, 0xdf, 0x6c, 0xfe, 0x3e, 0x99, 0x38, - 0xa7, 0xf8, 0xba, 0xe9, 0x9c, 0xc5, 0xef, 0x5e, 0xf8, 0xbd, 0x1c, 0x7d, - 0x89, 0x51, 0x19, 0xc7, 0xf9, 0x5d, 0x82, 0x4f, 0xb5, 0x68, 0xbe, 0x8b, - 0xc5, 0xdf, 0x01, 0x9c, 0x4b, 0x08, 0x32, 0x46, 0x19, 0xa5, 0x4c, 0xe1, - 0xfc, 0xc6, 0x6c, 0x79, 0xaf, 0x8f, 0xf2, 0xdc, 0x27, 0x97, 0xcb, 0xf2, - 0x9c, 0x85, 0x3c, 0x53, 0x96, 0xb3, 0x90, 0x69, 0xc3, 0xd7, 0xfb, 0x11, - 0x63, 0xa4, 0x62, 0xb0, 0x57, 0xea, 0x43, 0xbc, 0x0c, 0xbe, 0xb6, 0xbd, - 0x6f, 0xa5, 0x02, 0x9a, 0xc3, 0xc9, 0xcc, 0xd4, 0x79, 0xdf, 0x01, 0xe0, - 0xfa, 0xf2, 0x73, 0x32, 0x34, 0xd3, 0x88, 0x7d, 0x6f, 0xe8, 0xe0, 0x99, - 0x65, 0x2e, 0xf3, 0xdf, 0xe7, 0x45, 0xe2, 0x4d, 0xe9, 0xcf, 0xf2, 0x9a, - 0x71, 0xde, 0x7a, 0xcc, 0xe9, 0x07, 0x9d, 0x1b, 0xb1, 0x3e, 0xf7, 0xb8, - 0xd2, 0x3c, 0x8e, 0x87, 0x2a, 0xf0, 0xa9, 0x3e, 0xbd, 0x57, 0xeb, 0x33, - 0x33, 0xbd, 0x8d, 0xde, 0xfb, 0xf1, 0x1c, 0xc8, 0xf7, 0x31, 0xf0, 0x2d, - 0x7d, 0x62, 0xf2, 0x4b, 0x4a, 0xcf, 0x61, 0x36, 0x4f, 0xfe, 0x0d, 0x69, - 0x0e, 0x23, 0x03, 0xdb, 0xb2, 0x57, 0xe7, 0xc7, 0x96, 0xe5, 0xbb, 0x23, - 0xa0, 0x71, 0x77, 0x26, 0xbf, 0x4a, 0x3a, 0x55, 0x07, 0x75, 0x78, 0xbc, - 0x0d, 0x7b, 0xa1, 0x58, 0xee, 0x03, 0x72, 0xb4, 0xd8, 0x0f, 0x3a, 0xc4, - 0xe4, 0x29, 0xf8, 0xcd, 0xcf, 0x14, 0xef, 0x90, 0xa5, 0x08, 0xf6, 0x55, - 0x96, 0xb1, 0x41, 0xf9, 0xf1, 0xdc, 0x06, 0xef, 0x3a, 0xe1, 0x2e, 0x59, - 0xdb, 0xb1, 0x07, 0xca, 0x13, 0xe5, 0x8a, 0xf3, 0x82, 0x88, 0x45, 0xb8, - 0xee, 0x11, 0xa3, 0xdb, 0xb0, 0x6e, 0x21, 0x42, 0xf9, 0xe5, 0xde, 0x42, - 0x9e, 0xcc, 0x32, 0xae, 0xe2, 0x3b, 0x1b, 0x9b, 0x94, 0xae, 0x3a, 0x8b, - 0x84, 0xe2, 0x40, 0x97, 0xcf, 0xc0, 0x5f, 0xc7, 0x97, 0x4b, 0xff, 0x3b, - 0x0a, 0xea, 0x51, 0xd8, 0xca, 0x3c, 0x6c, 0x65, 0x1e, 0x36, 0x12, 0xb2, - 0xf0, 0x56, 0x1e, 0x36, 0x32, 0x0f, 0x1b, 0x09, 0x7d, 0xf6, 0x06, 0x62, - 0xbb, 0xab, 0xe0, 0x21, 0xe3, 0x6b, 0x1f, 0xa6, 0xaf, 0x8d, 0xbf, 0xff, - 0x01, 0x88, 0x97, 0xee, 0xe9, 0xc4, 0x71, 0x00, 0x00, 0x00 }; + 0xec, 0x5b, 0x5d, 0x70, 0x5c, 0xd7, 0x5d, 0xff, 0xdf, 0xb3, 0x2b, 0x69, + 0x2d, 0x4b, 0xf2, 0x95, 0xbc, 0x71, 0x56, 0xa9, 0x92, 0xec, 0x5a, 0x57, + 0xd2, 0xa6, 0x12, 0xe1, 0xca, 0x6c, 0x12, 0x75, 0xd8, 0x69, 0xb6, 0xbb, + 0xb2, 0xa3, 0xb4, 0x66, 0x46, 0x49, 0x0d, 0xcd, 0xb4, 0x65, 0x10, 0xbb, + 0x0e, 0xa4, 0x0f, 0x0c, 0xc6, 0x40, 0x26, 0x80, 0xc1, 0xcb, 0x4a, 0x71, + 0x94, 0x74, 0xad, 0xdd, 0xda, 0x0a, 0x86, 0x69, 0x61, 0x94, 0xd5, 0x87, + 0x53, 0x66, 0xad, 0x4d, 0xcb, 0x4b, 0x99, 0xd6, 0xb1, 0xea, 0xb8, 0x26, + 0x0f, 0x3c, 0xa4, 0x94, 0xce, 0x64, 0x20, 0x33, 0x35, 0xb2, 0x63, 0xfb, + 0x81, 0x8f, 0xc0, 0x4c, 0x49, 0x20, 0x6e, 0x2e, 0xbf, 0xdf, 0xb9, 0xf7, + 0xca, 0x2b, 0x45, 0xd0, 0x3c, 0xf0, 0x78, 0xcf, 0x8c, 0xe6, 0xde, 0x7b, + 0xce, 0xff, 0xfc, 0xcf, 0xff, 0xfb, 0xe3, 0xac, 0xfd, 0x3b, 0x1d, 0xd2, + 0x2e, 0xde, 0xe8, 0xc4, 0x5f, 0xea, 0xc8, 0x33, 0x47, 0x47, 0xef, 0x1f, + 0xbd, 0x9f, 0xdf, 0x21, 0xc3, 0x08, 0xf3, 0x69, 0x48, 0x30, 0x82, 0x11, + 0x8c, 0x60, 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, + 0x60, 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, + 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, + 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, 0x23, + 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, 0x23, 0x18, + 0xc1, 0x08, 0x46, 0x30, 0xfe, 0x3f, 0x47, 0x48, 0xc4, 0xe4, 0xb3, 0xd3, + 0xfb, 0x93, 0x88, 0x4a, 0xc7, 0x8f, 0x66, 0x2d, 0x89, 0x84, 0xd2, 0x97, + 0x9e, 0x2e, 0x58, 0x22, 0x99, 0xfa, 0x70, 0x3c, 0x27, 0x3f, 0x71, 0x8a, + 0xd1, 0xb0, 0x70, 0xfe, 0xee, 0xf4, 0xad, 0xe3, 0xe7, 0x1f, 0x4a, 0xbc, + 0xb3, 0x10, 0x92, 0x88, 0x99, 0x7e, 0x63, 0xd4, 0x1c, 0x94, 0x48, 0x1f, + 0xf6, 0x7c, 0x6d, 0x68, 0x6d, 0x97, 0x74, 0xf9, 0xb8, 0x44, 0x6a, 0xe5, + 0x84, 0x7d, 0x40, 0x86, 0xcd, 0x8b, 0x12, 0x96, 0x0c, 0xce, 0x58, 0xa9, + 0x8b, 0x94, 0xca, 0x06, 0x71, 0x48, 0xa9, 0x1e, 0x91, 0x2b, 0x21, 0x42, + 0x7d, 0xcb, 0xc8, 0x56, 0x3e, 0x70, 0x32, 0x61, 0x9c, 0x6b, 0xe1, 0xbd, + 0xe1, 0xcf, 0x47, 0x44, 0xa5, 0x13, 0xc9, 0x6c, 0x68, 0x42, 0x6a, 0xf3, + 0x8e, 0x33, 0x63, 0x7f, 0x0c, 0x38, 0x7a, 0x64, 0xc6, 0x72, 0xbf, 0xb3, + 0xf6, 0xc7, 0xcd, 0x71, 0xb9, 0x13, 0x73, 0x21, 0x51, 0xd6, 0x5d, 0xf8, + 0x8b, 0x1b, 0xb9, 0xd3, 0x5f, 0x36, 0xb2, 0x8b, 0x1d, 0x52, 0xaa, 0x38, + 0x52, 0xb0, 0x25, 0x93, 0xb5, 0x77, 0x60, 0xfd, 0x03, 0xa7, 0xb0, 0xb1, + 0x67, 0xd8, 0xcc, 0x49, 0x8b, 0x64, 0xa2, 0x31, 0xc0, 0xcc, 0x1b, 0xb9, + 0xb3, 0x7f, 0xdd, 0x21, 0xed, 0xa0, 0x27, 0xc5, 0xef, 0x0f, 0x9c, 0x90, + 0x65, 0x61, 0x9d, 0xe7, 0xe3, 0xbb, 0x41, 0xbc, 0x7c, 0x27, 0xce, 0x2b, + 0xce, 0xf9, 0xa1, 0x98, 0x7c, 0xb3, 0x11, 0x95, 0x6f, 0x34, 0x4c, 0x79, + 0xa5, 0xd1, 0x27, 0x17, 0x1a, 0x8e, 0xf3, 0x0d, 0xdb, 0x71, 0xde, 0xc0, + 0xdf, 0x7f, 0xd8, 0x1b, 0x3c, 0x60, 0x14, 0x8d, 0xf1, 0xc6, 0x57, 0x3b, + 0xa4, 0x2b, 0x11, 0x17, 0xd5, 0x21, 0xd3, 0x95, 0x98, 0xcc, 0x54, 0xca, + 0xc6, 0x63, 0x67, 0xe7, 0x8c, 0xc9, 0xb3, 0x55, 0x9c, 0x19, 0xc6, 0x9c, + 0x14, 0x4b, 0xf6, 0xcb, 0x46, 0xae, 0x31, 0x6b, 0x3c, 0x7e, 0xb6, 0x0b, + 0x34, 0xf2, 0xfc, 0x3d, 0x46, 0xf6, 0xf4, 0x2d, 0xc9, 0xda, 0x94, 0x71, + 0xc2, 0xfc, 0x3c, 0xc4, 0x9e, 0x2d, 0x93, 0xe6, 0x56, 0x8f, 0x5e, 0xc7, + 0x51, 0x69, 0xe7, 0x78, 0x36, 0x65, 0x99, 0x25, 0x21, 0x7d, 0x7a, 0xee, + 0x82, 0x4b, 0xf3, 0x8a, 0x91, 0x3d, 0xdb, 0x61, 0xe4, 0xce, 0x84, 0x41, + 0x87, 0xf4, 0x85, 0x84, 0xfb, 0x06, 0x62, 0x79, 0xa9, 0xe3, 0x0c, 0x31, + 0x55, 0x9a, 0x72, 0x05, 0xcd, 0xa0, 0xe5, 0x9b, 0x15, 0xf0, 0x50, 0x01, + 0x0f, 0x15, 0xf2, 0x16, 0x97, 0xf3, 0x43, 0x3e, 0x6f, 0x8e, 0xf3, 0x77, + 0x36, 0x69, 0x4f, 0xc4, 0x33, 0xca, 0xe7, 0xd3, 0x71, 0xfe, 0xdd, 0x26, + 0xaf, 0xe4, 0xc7, 0x71, 0x5e, 0xb1, 0x63, 0xa0, 0xdd, 0xb9, 0xa0, 0xac, + 0x32, 0x78, 0xb1, 0x80, 0x9f, 0xb2, 0x9e, 0x03, 0x0f, 0xb3, 0xe0, 0x6f, + 0x05, 0xbc, 0x55, 0x41, 0xc7, 0x4f, 0x3b, 0xaf, 0x68, 0xe4, 0x86, 0x36, + 0xe4, 0x15, 0xa7, 0x8c, 0xf3, 0x4b, 0x0a, 0xb2, 0xde, 0x29, 0xf9, 0x05, + 0x53, 0xa6, 0x96, 0xfc, 0xfd, 0xbe, 0x1d, 0x1c, 0x91, 0x83, 0x95, 0x1e, + 0xc8, 0x86, 0xb2, 0x4c, 0xd8, 0x22, 0x0e, 0x64, 0x54, 0x4a, 0x2a, 0x11, + 0x23, 0x6f, 0x1f, 0xd7, 0xfa, 0x5f, 0xb2, 0x24, 0x93, 0xb7, 0x29, 0x47, + 0x89, 0xe7, 0xed, 0x62, 0x2c, 0x0c, 0x7b, 0x5b, 0xb2, 0x8a, 0x66, 0x58, + 0x28, 0xc7, 0x44, 0xec, 0xf7, 0x21, 0xcb, 0x27, 0xcb, 0x92, 0xf9, 0x74, + 0xd9, 0x97, 0xb1, 0x2b, 0xdf, 0xcf, 0x94, 0x3f, 0xd5, 0x29, 0xed, 0xea, + 0x9e, 0x16, 0xf9, 0x0d, 0xec, 0x25, 0xee, 0x4d, 0x7b, 0xb1, 0xcf, 0x85, + 0x73, 0xf7, 0x26, 0x9e, 0x10, 0x21, 0x6c, 0xa9, 0xbf, 0x45, 0xfb, 0x88, + 0x18, 0x59, 0xab, 0x18, 0x0b, 0x01, 0x2e, 0x2f, 0xa5, 0x51, 0x6f, 0xae, + 0x25, 0x6b, 0xdd, 0x0a, 0xcd, 0xd8, 0x89, 0x78, 0x49, 0x6e, 0x85, 0x2e, + 0xdb, 0x7a, 0x6e, 0x47, 0xd6, 0x72, 0x64, 0x19, 0xd8, 0x9f, 0x83, 0x3f, + 0x5c, 0x04, 0x47, 0x5f, 0x2a, 0xeb, 0xf9, 0x4e, 0xec, 0x4f, 0xb6, 0x00, + 0x67, 0xbb, 0x24, 0x92, 0x35, 0xcc, 0x5f, 0x76, 0xe7, 0xbb, 0x5d, 0xbc, + 0xa5, 0xfe, 0x76, 0x8d, 0x5b, 0xe4, 0x65, 0x77, 0xfe, 0x0e, 0x17, 0x77, + 0xe9, 0x3e, 0xcc, 0x03, 0xff, 0xe0, 0xc4, 0x90, 0xa1, 0xe7, 0x7b, 0xe9, + 0x4f, 0xbf, 0x5e, 0xbe, 0x15, 0x5a, 0xb6, 0x1d, 0xc9, 0x8d, 0x0e, 0x4e, + 0x0c, 0x1a, 0x2e, 0xbe, 0x13, 0xee, 0xbe, 0xbb, 0x5d, 0x7c, 0x83, 0x13, + 0x49, 0xc3, 0xc5, 0xb7, 0x54, 0xd6, 0x7b, 0x25, 0x5f, 0x26, 0xec, 0xe0, + 0x84, 0x65, 0xdc, 0x2d, 0x53, 0xdd, 0x83, 0x13, 0x7b, 0x0d, 0x75, 0xcf, + 0x4e, 0x97, 0x8f, 0x84, 0x4f, 0xc3, 0x4e, 0x4d, 0x03, 0xcf, 0xd5, 0xf3, + 0x03, 0x59, 0xab, 0x74, 0xdf, 0x4e, 0x7d, 0x3e, 0xcf, 0xd4, 0x73, 0xf7, + 0x91, 0x2e, 0x9e, 0x5d, 0x18, 0xdd, 0x74, 0xee, 0xcf, 0xdc, 0x96, 0xcf, + 0x76, 0x67, 0xf2, 0x3c, 0x89, 0x84, 0xd3, 0xe1, 0xd1, 0x99, 0xf2, 0x11, + 0xc9, 0x56, 0xe2, 0x32, 0x3d, 0xb2, 0x43, 0xa6, 0xcc, 0xfe, 0xa9, 0x83, + 0xc2, 0xd8, 0x13, 0x19, 0x2d, 0x78, 0x3a, 0xcc, 0x89, 0x21, 0xd3, 0xe0, + 0xf1, 0x60, 0x5d, 0x22, 0x06, 0xe0, 0xfb, 0xeb, 0x61, 0x79, 0xbe, 0x61, + 0x48, 0xab, 0xf6, 0xcf, 0x84, 0xb9, 0x06, 0x3b, 0x7c, 0xb6, 0x42, 0x3b, + 0xa6, 0xcd, 0x4a, 0xa6, 0x06, 0x3b, 0xbd, 0xa0, 0x7d, 0xb5, 0x9d, 0x7a, + 0x2d, 0x16, 0x05, 0xae, 0x98, 0xb6, 0xcc, 0x9a, 0xb4, 0x49, 0x66, 0x52, + 0x8a, 0x5c, 0xf7, 0x7c, 0x27, 0xb6, 0x28, 0xdf, 0x85, 0x0d, 0x88, 0x99, + 0x4d, 0x71, 0x9e, 0xf0, 0x4d, 0xb0, 0xa6, 0xeb, 0x77, 0x21, 0xf8, 0x5d, + 0x21, 0x45, 0x58, 0x29, 0xea, 0x58, 0xd1, 0x80, 0x2d, 0x36, 0xee, 0xee, + 0x74, 0x63, 0x5d, 0x04, 0xfe, 0xd9, 0x01, 0x1f, 0xbf, 0x07, 0xfe, 0xd7, + 0x67, 0x64, 0xcf, 0x38, 0x0e, 0x62, 0x4f, 0x54, 0x09, 0xfd, 0x0f, 0xbe, + 0xde, 0xe0, 0x5a, 0x07, 0xe6, 0xc5, 0x9c, 0xb6, 0xbb, 0xc1, 0x9f, 0xe3, + 0x4c, 0xd8, 0x71, 0x29, 0xd9, 0xbb, 0xb0, 0xaf, 0x45, 0xba, 0x2d, 0xda, + 0x3b, 0x7d, 0x7a, 0x27, 0xce, 0x33, 0xf8, 0xdd, 0x85, 0xf3, 0x3a, 0x31, + 0x17, 0x9b, 0xa6, 0x1f, 0xa7, 0x18, 0xb3, 0xdc, 0xf8, 0x29, 0x72, 0x15, + 0xb4, 0x72, 0x8f, 0x86, 0x8b, 0xb4, 0xa5, 0x53, 0x72, 0xa3, 0xdc, 0x2b, + 0x57, 0xa2, 0xe4, 0x1f, 0x38, 0x2b, 0x88, 0x87, 0x51, 0x03, 0xf4, 0x93, + 0x6e, 0xc6, 0xbf, 0xdd, 0xde, 0xb7, 0x71, 0xaf, 0x7b, 0x86, 0x98, 0xa1, + 0x74, 0x97, 0xe4, 0xf4, 0x9c, 0x28, 0x35, 0xba, 0xd3, 0x5b, 0xef, 0x32, + 0x0e, 0x9c, 0x51, 0x32, 0xf4, 0x20, 0x62, 0x16, 0xce, 0xba, 0x6c, 0x39, + 0xce, 0x65, 0xfb, 0xc7, 0xf0, 0x79, 0x25, 0x2d, 0xd6, 0x7a, 0x97, 0xb4, + 0x43, 0x9e, 0x15, 0xa3, 0x49, 0x86, 0x31, 0x39, 0x51, 0xe1, 0x9e, 0xa2, + 0x84, 0x2d, 0xc2, 0x10, 0xfe, 0x47, 0x80, 0x0b, 0x49, 0x1b, 0x7c, 0xf1, + 0xa2, 0x1d, 0x25, 0xbd, 0xbb, 0x5c, 0xf8, 0x6e, 0x9c, 0x41, 0xda, 0xe9, + 0x7b, 0x8e, 0xf6, 0xbd, 0x6c, 0x48, 0x65, 0xc6, 0xe7, 0xe1, 0x49, 0x23, + 0x94, 0x77, 0xb6, 0x1b, 0xa1, 0x5f, 0xa6, 0x87, 0x8a, 0xa6, 0xd2, 0xba, + 0x16, 0xc9, 0x95, 0xef, 0x95, 0x19, 0x1b, 0xe7, 0x59, 0x61, 0xd0, 0xcc, + 0x38, 0x33, 0x50, 0x0c, 0x29, 0x78, 0x58, 0x0f, 0x65, 0xe5, 0xd3, 0xfa, + 0x16, 0xce, 0x2b, 0x1a, 0x61, 0x8b, 0x67, 0xfc, 0xb2, 0x27, 0x1f, 0xda, + 0x9d, 0x2d, 0xd9, 0x72, 0x07, 0xbf, 0x41, 0x47, 0xbb, 0xa6, 0x23, 0x94, + 0xd6, 0xba, 0x33, 0x54, 0xda, 0x8f, 0xff, 0x04, 0xdd, 0x84, 0x07, 0x7c, + 0x70, 0xaf, 0x85, 0xbd, 0x11, 0xd0, 0xd8, 0xd9, 0x44, 0x7f, 0x3b, 0xe1, + 0x21, 0xab, 0x88, 0x77, 0x86, 0xe6, 0xdb, 0x70, 0xf9, 0xf6, 0x65, 0xf5, + 0x2a, 0x64, 0xf5, 0xbe, 0x33, 0xb4, 0x8f, 0x38, 0x52, 0xc0, 0x01, 0xb9, + 0x9b, 0x8c, 0x57, 0x8c, 0x51, 0xe6, 0x06, 0x2e, 0xf8, 0x81, 0x0a, 0xa5, + 0x3b, 0x24, 0x67, 0xea, 0x1c, 0x00, 0xd8, 0x31, 0xd1, 0x31, 0xde, 0x22, + 0x8f, 0xde, 0xb7, 0x95, 0xd0, 0x76, 0x93, 0xaf, 0x32, 0x0f, 0xfc, 0x31, + 0x68, 0x5b, 0x4b, 0x28, 0xcd, 0x5a, 0x07, 0x64, 0x2e, 0x91, 0x96, 0xf4, + 0x1b, 0xb2, 0x5c, 0x56, 0x7b, 0x5a, 0x65, 0x97, 0x4c, 0x42, 0x46, 0xb5, + 0x31, 0xe4, 0xaf, 0x91, 0x0e, 0x09, 0xdd, 0xcf, 0x3c, 0x10, 0x03, 0xad, + 0x6b, 0x09, 0x53, 0x6e, 0x39, 0x6a, 0x10, 0xfb, 0x47, 0xa0, 0x87, 0x43, + 0xd4, 0xa9, 0xf2, 0xe0, 0x08, 0x13, 0xa2, 0xcc, 0x7b, 0x5a, 0x85, 0xb8, + 0xb9, 0x36, 0x1c, 0x33, 0x85, 0xf3, 0xc8, 0x95, 0x93, 0xdc, 0x4b, 0xfe, + 0xdc, 0x3d, 0x1f, 0xe6, 0xcf, 0x5f, 0xa7, 0xcc, 0x28, 0x3b, 0xd8, 0x18, + 0x78, 0xcc, 0xda, 0xbf, 0xe0, 0xc9, 0xe6, 0x4e, 0xb9, 0x62, 0x8a, 0x51, + 0xb3, 0xef, 0x68, 0x92, 0x1f, 0x79, 0xee, 0xde, 0xc2, 0x33, 0x71, 0x6c, + 0xcf, 0xf7, 0xe1, 0x2a, 0xcf, 0x74, 0xcf, 0x9e, 0xb1, 0xd6, 0x12, 0x61, + 0xd9, 0x2c, 0x5f, 0xe8, 0x52, 0x0a, 0x65, 0xda, 0x46, 0xab, 0xe4, 0x51, + 0x8f, 0xd8, 0xfb, 0x10, 0x54, 0x1e, 0x57, 0x32, 0xfa, 0x20, 0x71, 0xfe, + 0x23, 0x79, 0x1a, 0x8b, 0x2b, 0x43, 0xf2, 0x3a, 0xf7, 0xfb, 0xfa, 0xe2, + 0x5c, 0xb3, 0x6d, 0xbf, 0xea, 0xd9, 0xf6, 0xfb, 0xce, 0xe8, 0x3e, 0x5f, + 0xef, 0x90, 0xd7, 0x87, 0xf6, 0x08, 0xf4, 0xfc, 0x7f, 0xed, 0xa1, 0xad, + 0x44, 0xb6, 0xec, 0x29, 0x6e, 0xb3, 0x67, 0xb7, 0xc8, 0x2f, 0xd1, 0x87, + 0xba, 0xbd, 0x98, 0xe1, 0xfb, 0x94, 0x8f, 0x07, 0xba, 0xd1, 0xb6, 0xca, + 0xb9, 0xed, 0x7c, 0x91, 0x38, 0x88, 0x8b, 0x7b, 0x09, 0xe3, 0xe7, 0x54, + 0xa8, 0x43, 0xb6, 0xcd, 0xab, 0x18, 0x13, 0x78, 0x57, 0x88, 0x43, 0xcd, + 0xf9, 0x95, 0x73, 0x26, 0xbe, 0xc7, 0xf1, 0xb4, 0x24, 0x5f, 0xa7, 0x3f, + 0x71, 0x3f, 0xf3, 0xed, 0x4d, 0x2f, 0x7e, 0x76, 0x4c, 0x85, 0xd3, 0x51, + 0xc4, 0x4f, 0x99, 0x2c, 0x95, 0x8f, 0xa3, 0x26, 0x92, 0xe2, 0x5d, 0x69, + 0xda, 0x47, 0xc7, 0x18, 0x62, 0xe4, 0x64, 0xa9, 0xce, 0xba, 0x08, 0x61, + 0x0c, 0xfb, 0x90, 0xa3, 0x23, 0x6a, 0x2e, 0x52, 0xfc, 0x58, 0x9a, 0x71, + 0x39, 0x2e, 0xf1, 0xfa, 0x3b, 0xa8, 0x3b, 0x4c, 0xc9, 0x6a, 0x5b, 0xfb, + 0xb3, 0x5e, 0xd2, 0x5b, 0x42, 0x0d, 0x11, 0x4e, 0x4b, 0x58, 0xa5, 0x5b, + 0x23, 0xd3, 0xa9, 0x0e, 0xd4, 0x5a, 0x13, 0xbd, 0x6a, 0xf5, 0x60, 0x6f, + 0x68, 0x75, 0xcf, 0x54, 0x4b, 0xba, 0xd8, 0xab, 0xe6, 0x44, 0x16, 0xcb, + 0xa2, 0x50, 0xd7, 0xc4, 0x0e, 0x0b, 0xbe, 0x57, 0x3f, 0xfb, 0x59, 0x95, + 0x0e, 0x41, 0xb7, 0x72, 0x6c, 0x29, 0x15, 0x66, 0x0d, 0x19, 0x9f, 0x94, + 0x63, 0xa8, 0x1b, 0x9f, 0x91, 0xe9, 0x32, 0xe8, 0xd2, 0x7c, 0xc7, 0xc0, + 0x6f, 0x1f, 0x70, 0x93, 0xf6, 0x28, 0x62, 0xac, 0x4b, 0x3b, 0x68, 0xce, + 0xe4, 0x58, 0x27, 0xa5, 0x98, 0x57, 0xde, 0x81, 0xfd, 0xd0, 0x5f, 0xfe, + 0x59, 0x96, 0xad, 0x1d, 0x92, 0x77, 0xe3, 0x03, 0xed, 0x15, 0x6b, 0x37, + 0xbd, 0xb5, 0x6b, 0x58, 0xa3, 0xfd, 0xee, 0x6c, 0xd2, 0xe1, 0x97, 0x75, + 0xad, 0x73, 0xd9, 0xe6, 0x3b, 0x61, 0xff, 0x76, 0xd4, 0x85, 0x7d, 0x7d, + 0x74, 0xd9, 0xfa, 0xdc, 0x2e, 0x69, 0x37, 0xa9, 0x37, 0x9c, 0x13, 0x65, + 0x8c, 0xc5, 0xfa, 0x15, 0x0f, 0xd7, 0x5b, 0xc0, 0xd5, 0x41, 0xba, 0x31, + 0xc2, 0x58, 0x07, 0x7d, 0xa8, 0x79, 0xf2, 0x1b, 0xb1, 0x86, 0xb0, 0xdf, + 0xf1, 0x70, 0x7d, 0xab, 0x09, 0x17, 0xd7, 0xf8, 0xe4, 0x99, 0x38, 0xbb, + 0x9d, 0xbc, 0x91, 0x1f, 0xea, 0x80, 0xfa, 0x48, 0x1a, 0x93, 0x88, 0xed, + 0x93, 0x0d, 0x5d, 0xdb, 0x19, 0xb9, 0x0a, 0x6a, 0xae, 0xc6, 0x8b, 0xa0, + 0x11, 0xb5, 0x58, 0x63, 0xd0, 0xab, 0xb7, 0x69, 0x47, 0x6b, 0xda, 0x1e, + 0x19, 0x77, 0x4a, 0xda, 0xae, 0x2e, 0xb9, 0x76, 0x65, 0x51, 0x37, 0x97, + 0x64, 0x6f, 0xbd, 0xba, 0xcb, 0xfd, 0xbf, 0xdb, 0xa6, 0x84, 0xb4, 0x3e, + 0x99, 0xdf, 0x68, 0x63, 0x77, 0x22, 0xae, 0x3b, 0xef, 0x32, 0xcf, 0x4c, + 0x32, 0x07, 0x4d, 0x32, 0x77, 0x18, 0x5e, 0x3c, 0x8c, 0x37, 0xe1, 0x88, + 0x03, 0xc7, 0x8a, 0x67, 0xbf, 0x73, 0x1e, 0x2e, 0xbf, 0xfe, 0xf4, 0x63, + 0xea, 0x9f, 0xdf, 0xb5, 0x79, 0x5d, 0x99, 0xee, 0x77, 0xab, 0x8e, 0xc7, + 0xb0, 0x75, 0xd0, 0x1f, 0x9f, 0x52, 0xb0, 0xaf, 0x5c, 0xdd, 0xd5, 0x07, + 0x7c, 0x1f, 0xb6, 0xc7, 0x57, 0x5f, 0xb7, 0x6e, 0xfd, 0xed, 0xca, 0x80, + 0x3a, 0xcd, 0x90, 0xef, 0x4c, 0x98, 0xb4, 0x34, 0x26, 0xb0, 0x5f, 0x8e, + 0x30, 0x37, 0xe6, 0xc1, 0xc7, 0x61, 0x73, 0xd8, 0x9c, 0x26, 0xee, 0xa8, + 0x00, 0x27, 0x6a, 0xc9, 0x74, 0x9b, 0xa7, 0xe7, 0x6f, 0xf3, 0x7c, 0xe0, + 0xde, 0xc9, 0x6f, 0x3c, 0xbf, 0xed, 0xd1, 0x73, 0xa3, 0xcb, 0xa5, 0xc7, + 0x5f, 0x1f, 0x34, 0x37, 0x7f, 0xaf, 0xf4, 0x7a, 0xf2, 0xc4, 0xfb, 0x33, + 0x1e, 0x5d, 0xd4, 0x4d, 0x33, 0x4d, 0xd4, 0xcb, 0xbb, 0xc0, 0xa3, 0x6b, + 0x8d, 0xa2, 0x4a, 0xa3, 0x76, 0x49, 0x31, 0x67, 0x25, 0xc6, 0x32, 0x62, + 0x41, 0x27, 0x09, 0x7b, 0x0a, 0xbb, 0x6e, 0x96, 0xa9, 0xe7, 0x5b, 0x88, + 0xd5, 0xd4, 0xfb, 0x7b, 0x32, 0x53, 0xee, 0xb7, 0x5b, 0x0d, 0xfa, 0x6b, + 0x22, 0xb9, 0x22, 0xc3, 0xf6, 0x8a, 0xae, 0xa1, 0x12, 0xf1, 0x13, 0x42, + 0xd9, 0xde, 0x92, 0x01, 0x5d, 0xdb, 0xbc, 0x27, 0x16, 0xe4, 0x32, 0x59, + 0x81, 0x8f, 0xed, 0xfb, 0x57, 0x47, 0xd7, 0xa4, 0x08, 0x6f, 0xd7, 0xb7, + 0xc1, 0xf5, 0xba, 0xc6, 0x43, 0x7c, 0xcd, 0xb8, 0x0c, 0x69, 0xdb, 0xe7, + 0xe3, 0xb3, 0x64, 0xb6, 0xe1, 0xe3, 0x0c, 0x23, 0x2e, 0x23, 0x06, 0xec, + 0xfb, 0xbc, 0x67, 0x2f, 0x7c, 0xff, 0xbe, 0xc3, 0x5a, 0x48, 0xa5, 0xbf, + 0xea, 0xcd, 0x7d, 0x8f, 0x32, 0xc0, 0xb7, 0x2f, 0xf7, 0x17, 0xbd, 0x78, + 0x53, 0x34, 0x32, 0x0d, 0xca, 0x80, 0xb6, 0x02, 0xfd, 0x6b, 0xfb, 0x84, + 0xcf, 0x54, 0x3e, 0x89, 0x98, 0xd5, 0xed, 0xd6, 0x0f, 0xe8, 0xaf, 0x32, + 0x0d, 0xce, 0xad, 0xb5, 0x65, 0xed, 0x16, 0xcf, 0x97, 0x0e, 0x62, 0x6e, + 0x12, 0x7f, 0x94, 0x1d, 0x61, 0x0e, 0xe1, 0x3d, 0xe3, 0xc1, 0xc9, 0x58, + 0x16, 0xb9, 0x2b, 0x73, 0x68, 0x1c, 0xdf, 0x86, 0xd7, 0x67, 0x69, 0xb9, + 0x57, 0x51, 0xab, 0x40, 0x9e, 0x03, 0xe0, 0x27, 0x2e, 0xe3, 0x0d, 0xe8, + 0x7c, 0x23, 0x9e, 0x6d, 0xc0, 0x14, 0x6f, 0xc3, 0xb8, 0xb1, 0x6f, 0xbc, + 0xf1, 0xa6, 0xc3, 0x78, 0xf0, 0x57, 0xda, 0x5f, 0xe2, 0xa0, 0xdd, 0xef, + 0xd5, 0x32, 0xc6, 0x63, 0x95, 0x09, 0xe3, 0xf1, 0x0a, 0xf7, 0xa8, 0xaf, + 0xf5, 0x88, 0x15, 0xcf, 0x2a, 0xd4, 0xa9, 0xfb, 0xba, 0x70, 0xe6, 0x09, + 0xd8, 0x46, 0xd1, 0x98, 0x1c, 0xda, 0x25, 0xf9, 0x64, 0x0f, 0x68, 0x7e, + 0x08, 0xcf, 0x56, 0xcc, 0xff, 0x3c, 0xe6, 0x61, 0x47, 0x49, 0xfa, 0xc7, + 0x0e, 0xdd, 0x5b, 0x4e, 0x99, 0xa4, 0x71, 0xc0, 0xb3, 0xad, 0x37, 0x4d, + 0xd7, 0x96, 0x9e, 0xc6, 0xf7, 0x4e, 0xcc, 0x7f, 0x01, 0x4f, 0xe4, 0xb2, + 0x7d, 0xfe, 0x3c, 0x7d, 0x70, 0x0c, 0xf3, 0x0f, 0x00, 0xc7, 0x1f, 0xe0, + 0xfd, 0x5e, 0xbc, 0xff, 0xde, 0x96, 0xbd, 0xbf, 0xcb, 0xb3, 0x31, 0x9f, + 0xdd, 0x32, 0xef, 0xc7, 0x6f, 0x9e, 0x27, 0xd2, 0xbd, 0x0a, 0xc6, 0x57, + 0x23, 0xb2, 0x7b, 0xa5, 0x5d, 0x54, 0xcd, 0x8d, 0xe1, 0xaa, 0x66, 0x4a, + 0xcf, 0x0a, 0xe3, 0xf7, 0x0f, 0xb0, 0xc7, 0x12, 0xb5, 0x0a, 0xa5, 0x51, + 0xb7, 0xda, 0x47, 0x9f, 0x39, 0xba, 0x77, 0x81, 0xcf, 0xe2, 0xd1, 0xd1, + 0x3a, 0x61, 0xf8, 0x7e, 0xec, 0xe8, 0xde, 0xfa, 0x3f, 0x00, 0x16, 0x72, + 0xa9, 0xf8, 0xf8, 0x09, 0x7f, 0x7e, 0xcb, 0x99, 0x5a, 0xb6, 0x38, 0x93, + 0x7e, 0xff, 0xcc, 0xd1, 0x6c, 0x95, 0x75, 0x42, 0x22, 0x26, 0xba, 0x16, + 0x2f, 0x1e, 0x2d, 0x20, 0x3f, 0x86, 0x34, 0x2d, 0xfe, 0x3a, 0xd7, 0xa8, + 0x87, 0xed, 0x68, 0x23, 0x5d, 0xcd, 0x78, 0x98, 0x67, 0x88, 0xe7, 0x18, + 0xf0, 0x24, 0x81, 0x87, 0xf9, 0xc6, 0xa5, 0x37, 0xbe, 0xb0, 0x1d, 0x6d, + 0xc4, 0xc5, 0xb3, 0x7c, 0x7c, 0x3d, 0xa2, 0x56, 0x7e, 0x48, 0x7a, 0x4d, + 0xd6, 0xb6, 0x6e, 0xac, 0x69, 0x91, 0xfc, 0x69, 0xe6, 0xec, 0x7d, 0xde, + 0x37, 0xca, 0x18, 0xf4, 0xdc, 0x71, 0xc5, 0x79, 0x3e, 0xb1, 0x96, 0x62, + 0xb9, 0x82, 0xef, 0x45, 0x1f, 0x56, 0x79, 0xb0, 0x9d, 0x4d, 0x7c, 0xb7, + 0x78, 0xb2, 0xe6, 0x99, 0x7e, 0xef, 0xd9, 0x4c, 0x0b, 0x40, 0xa1, 0x87, + 0xee, 0x0d, 0x3d, 0xf8, 0x7c, 0x62, 0x61, 0x95, 0xb4, 0x25, 0xc1, 0xab, + 0x4f, 0xdb, 0x47, 0xd5, 0x1f, 0xf7, 0x26, 0xf1, 0xe7, 0x9f, 0xe7, 0xcb, + 0x80, 0x74, 0xf1, 0x09, 0x5b, 0xfe, 0x50, 0xef, 0x9c, 0x84, 0xdf, 0xf1, + 0x1e, 0xc4, 0x71, 0x96, 0x6d, 0xca, 0xbe, 0x0d, 0x7a, 0x27, 0x2f, 0x06, + 0x7a, 0x09, 0xc5, 0x9a, 0x2e, 0xce, 0x9e, 0xf5, 0x49, 0xb9, 0x0a, 0x5c, + 0x19, 0xf4, 0x95, 0x6e, 0x6f, 0x34, 0x85, 0xf8, 0xb8, 0x06, 0xfb, 0xbc, + 0x6c, 0xf1, 0x3e, 0x26, 0xcc, 0x7c, 0x27, 0xa5, 0xfa, 0xbf, 0x00, 0x86, + 0xf5, 0xd5, 0xed, 0xbb, 0x96, 0x05, 0xc0, 0x2c, 0x62, 0xed, 0x84, 0x1b, + 0x97, 0x19, 0xdb, 0x1d, 0x85, 0xda, 0xa3, 0x60, 0xfd, 0xb7, 0xc3, 0x3a, + 0xeb, 0x36, 0xec, 0x76, 0x77, 0x21, 0xc8, 0x39, 0xf3, 0x89, 0xd9, 0x05, + 0xc4, 0xf0, 0xaa, 0xa5, 0x76, 0x2b, 0x6d, 0x91, 0x89, 0x2a, 0x62, 0x12, + 0xba, 0xde, 0x44, 0x7c, 0x41, 0xfe, 0x53, 0xeb, 0xa1, 0xc5, 0x1a, 0x36, + 0x7b, 0xd4, 0xe7, 0x68, 0x57, 0x9a, 0xf2, 0xd0, 0x29, 0xe4, 0xe5, 0x91, + 0xc7, 0x90, 0x73, 0x20, 0xaf, 0x53, 0x45, 0x74, 0xf2, 0xb4, 0x91, 0x37, + 0x7e, 0xab, 0x60, 0xb9, 0x7d, 0x80, 0xce, 0x67, 0xe2, 0xf2, 0x18, 0x3a, + 0xd5, 0xa1, 0xe3, 0x4c, 0x5e, 0xc7, 0x9b, 0x7e, 0x73, 0x52, 0xb5, 0xa3, + 0xc6, 0x40, 0x01, 0x8a, 0x0a, 0xc7, 0x1c, 0x14, 0xd9, 0x3b, 0x87, 0xb8, + 0x82, 0x38, 0xbc, 0x77, 0x15, 0xd1, 0xed, 0x14, 0xe1, 0x95, 0x84, 0x4f, + 0x85, 0xa4, 0xe5, 0x14, 0xef, 0x43, 0x64, 0x0f, 0xfa, 0x31, 0xe2, 0xdc, + 0x1b, 0xc6, 0x73, 0x1c, 0x7f, 0xfb, 0x51, 0x5b, 0x99, 0xa8, 0x91, 0xb7, + 0x81, 0x07, 0x2c, 0xf7, 0x6c, 0x07, 0x6f, 0x76, 0x4b, 0x7b, 0x04, 0x7b, + 0x08, 0x1f, 0x06, 0x1d, 0x7b, 0x40, 0x8f, 0x7b, 0x3e, 0x71, 0x84, 0x4f, + 0x89, 0xf4, 0xcf, 0x49, 0x8f, 0xd2, 0x7b, 0xc2, 0x52, 0x48, 0x71, 0xad, + 0x03, 0xf0, 0xdc, 0x87, 0x35, 0xbd, 0xcf, 0xbd, 0x57, 0xca, 0xdf, 0xa6, + 0x1b, 0x73, 0x06, 0xde, 0x51, 0x4f, 0xa5, 0x4c, 0xe9, 0xaf, 0xb9, 0xb0, + 0x7b, 0x57, 0xbf, 0xd4, 0xcd, 0xbb, 0x29, 0x65, 0xb9, 0xb4, 0x29, 0xd4, + 0xc4, 0x79, 0x48, 0x35, 0x3c, 0xc8, 0xfb, 0x19, 0xc2, 0xb0, 0xaf, 0x35, + 0x35, 0x8c, 0x39, 0x48, 0xf9, 0xb9, 0x73, 0x4a, 0xfd, 0x6f, 0xf7, 0x2e, + 0xcd, 0x35, 0x85, 0xf6, 0x15, 0xec, 0xff, 0x43, 0xed, 0x2b, 0xa2, 0xe2, + 0x9e, 0xaf, 0xe0, 0x7b, 0x91, 0xdf, 0x7e, 0x2e, 0xfe, 0xed, 0xbb, 0xdc, + 0x78, 0xef, 0xc8, 0xb4, 0xcd, 0x3b, 0x0c, 0x47, 0x2e, 0xdb, 0x45, 0xe3, + 0x91, 0x4d, 0x75, 0x66, 0x52, 0xe7, 0xe7, 0x02, 0x64, 0xbf, 0x5e, 0xd7, + 0x3d, 0x9b, 0x5c, 0xa9, 0x47, 0xe4, 0xea, 0x52, 0xbb, 0xac, 0x2f, 0xb8, + 0x36, 0xbf, 0xbe, 0x40, 0x3b, 0x37, 0xe5, 0xed, 0x25, 0x0b, 0x6b, 0x49, + 0xfc, 0xf5, 0xc8, 0xf5, 0xa5, 0xcd, 0x75, 0xe7, 0x85, 0xc6, 0xc3, 0xa0, + 0xa5, 0x47, 0x42, 0x96, 0xa3, 0xfb, 0xaf, 0x1c, 0x72, 0x5f, 0x51, 0xc6, + 0x25, 0x5f, 0xe9, 0x47, 0x0f, 0x88, 0xe4, 0x1c, 0x66, 0x0e, 0x82, 0xfe, + 0x2b, 0x9f, 0x40, 0x6d, 0x92, 0x80, 0xf3, 0xf4, 0xeb, 0x7b, 0xc5, 0x4f, + 0x85, 0x7b, 0xa4, 0xd5, 0xfa, 0xa3, 0x6e, 0x37, 0x57, 0x99, 0x6e, 0x9f, + 0x6a, 0xf9, 0xf9, 0xfa, 0x75, 0xe0, 0x1e, 0x81, 0x9d, 0xd2, 0x36, 0x6d, + 0xd8, 0xac, 0x29, 0xcb, 0x43, 0x89, 0x6a, 0x51, 0x18, 0x1f, 0x52, 0x38, + 0xd3, 0xc0, 0xbe, 0x24, 0xe4, 0xb1, 0x43, 0xd7, 0x42, 0x19, 0x05, 0xdd, + 0xce, 0xcd, 0x48, 0xbe, 0xf1, 0x9b, 0x98, 0xcf, 0xc8, 0x54, 0x63, 0x0c, + 0x67, 0x9d, 0xa4, 0xdd, 0xf6, 0x48, 0x3b, 0xcf, 0x49, 0x81, 0xc6, 0x87, + 0xa4, 0x70, 0x7a, 0x46, 0x0e, 0x57, 0x48, 0x27, 0xef, 0x19, 0x13, 0xc9, + 0x9c, 0x0c, 0xc7, 0x97, 0x50, 0x3b, 0xb9, 0xfe, 0x98, 0x96, 0xc2, 0x19, + 0xe0, 0xa8, 0xf0, 0x1e, 0xa0, 0x1f, 0x76, 0x33, 0xac, 0xfb, 0x9a, 0x29, + 0x1d, 0x77, 0x38, 0xff, 0x43, 0xe8, 0xa9, 0xbf, 0xb8, 0x1f, 0x70, 0x79, + 0xf4, 0x40, 0x93, 0xa8, 0x97, 0x17, 0x2b, 0xe8, 0xf7, 0xec, 0x10, 0x6b, + 0x2f, 0xa5, 0xee, 0xef, 0x93, 0x5a, 0x65, 0xd8, 0x54, 0x8a, 0x35, 0x15, + 0x75, 0xc1, 0x35, 0xfa, 0x77, 0x4c, 0x85, 0xad, 0x3e, 0x59, 0xaa, 0x14, + 0xd1, 0x37, 0x2b, 0xef, 0x5e, 0x03, 0x16, 0x60, 0xb9, 0x71, 0x2f, 0xa3, + 0xc8, 0x37, 0xea, 0xcf, 0xc6, 0x27, 0x41, 0x63, 0x26, 0x6e, 0xca, 0x71, + 0xd0, 0x87, 0xf7, 0x45, 0xd8, 0xf8, 0x1c, 0x6b, 0xb8, 0x0c, 0xd6, 0xd2, + 0x72, 0xe4, 0xec, 0x24, 0x68, 0xe8, 0x92, 0xfe, 0x3f, 0xa1, 0x8f, 0x3d, + 0x81, 0x39, 0x7e, 0x27, 0x60, 0xaf, 0x5f, 0xc4, 0x3b, 0x61, 0x63, 0x78, + 0x52, 0x0e, 0x7d, 0x78, 0x9a, 0xa0, 0x25, 0xe2, 0xf6, 0x26, 0x87, 0xe2, + 0x52, 0x3b, 0xfd, 0xa0, 0x4c, 0x2d, 0x3e, 0x08, 0xfc, 0x3f, 0x42, 0x5f, + 0x80, 0xfc, 0xb6, 0xc8, 0xb3, 0x58, 0xff, 0xf1, 0x9c, 0x9d, 0x3d, 0xda, + 0x37, 0xe6, 0x38, 0xcf, 0xe7, 0x41, 0xec, 0x47, 0x8f, 0x51, 0xc9, 0x48, + 0xa1, 0xc2, 0xb3, 0xa0, 0x3b, 0xd4, 0x53, 0xf9, 0xd3, 0x93, 0x9e, 0x8e, + 0x7b, 0x24, 0x17, 0x2d, 0xb2, 0xbf, 0x40, 0x9e, 0x58, 0x18, 0xcd, 0x96, + 0x13, 0x66, 0x56, 0x11, 0x57, 0x52, 0x98, 0x1b, 0xdc, 0xb9, 0x88, 0x58, + 0x73, 0xe8, 0x6d, 0xd3, 0x5c, 0x3b, 0xee, 0xdd, 0x1d, 0x10, 0xd7, 0x9b, + 0x32, 0x0e, 0x1b, 0xeb, 0x9f, 0x1b, 0x41, 0x2d, 0xfc, 0x16, 0x6a, 0xc9, + 0x84, 0x27, 0x83, 0x31, 0xcf, 0x36, 0xda, 0x9b, 0x6c, 0x02, 0x7a, 0xae, + 0x40, 0xf7, 0x15, 0xd8, 0x01, 0x62, 0xf5, 0x2b, 0x1b, 0xf6, 0x31, 0xd6, + 0x54, 0x63, 0x76, 0xca, 0xdf, 0x54, 0x13, 0xc9, 0x35, 0xd8, 0xcf, 0x75, + 0xf4, 0x02, 0x6b, 0xe8, 0x55, 0xd7, 0xd1, 0xd7, 0x2d, 0x96, 0x0f, 0x81, + 0x7e, 0xd6, 0x94, 0xfc, 0x8e, 0xe9, 0x5a, 0xa7, 0xcd, 0x7a, 0xe1, 0x2e, + 0x7d, 0xb7, 0x2b, 0x4f, 0xf4, 0xb0, 0xd7, 0x64, 0x5f, 0xce, 0x7b, 0xe9, + 0xab, 0xd0, 0xe3, 0x9a, 0xc9, 0x75, 0x7f, 0x1f, 0x7b, 0x01, 0xdf, 0x7e, + 0x48, 0x0b, 0xed, 0x87, 0x7b, 0x08, 0xd3, 0xa3, 0xfd, 0x24, 0xaf, 0xf1, + 0xd1, 0x66, 0xeb, 0xdd, 0xae, 0x9f, 0xe9, 0x3a, 0xcb, 0xbc, 0x22, 0xbe, + 0xfd, 0xbe, 0xe7, 0xb0, 0xaf, 0xcb, 0x0e, 0x21, 0x76, 0x37, 0x1c, 0x79, + 0xc1, 0xde, 0xec, 0x77, 0x07, 0x2a, 0xbe, 0x9c, 0x28, 0xc7, 0x43, 0x72, + 0xa2, 0x91, 0x80, 0x4f, 0x50, 0x86, 0x56, 0x93, 0x0c, 0x45, 0xbe, 0x5e, + 0x11, 0x79, 0xb9, 0xc2, 0x35, 0x2d, 0xc3, 0x58, 0x36, 0xd4, 0xce, 0xbb, + 0x75, 0xd8, 0xe5, 0xdf, 0xcb, 0xe1, 0x79, 0x91, 0xb3, 0x58, 0x5f, 0xae, + 0xd0, 0x57, 0x47, 0x50, 0xbf, 0xee, 0x94, 0xda, 0x02, 0x7a, 0xb2, 0x8a, + 0x4c, 0x65, 0x1f, 0x60, 0xbe, 0x89, 0xc8, 0xba, 0xbe, 0x93, 0x15, 0x19, + 0x3c, 0x17, 0x96, 0xf0, 0x39, 0x34, 0x7f, 0x90, 0xfd, 0xf9, 0x21, 0xff, + 0x8e, 0xd6, 0xf5, 0xf9, 0x52, 0x19, 0x7b, 0x2b, 0xfd, 0x3a, 0x4e, 0x96, + 0xea, 0x05, 0xc9, 0x57, 0x79, 0x16, 0x9e, 0x0b, 0x71, 0xac, 0xa5, 0x64, + 0xfa, 0xf4, 0x88, 0x3c, 0x8b, 0x33, 0xd0, 0xff, 0xe1, 0x8c, 0x71, 0x29, + 0x9e, 0xc5, 0x7c, 0xfd, 0x9a, 0x2c, 0x2c, 0x15, 0xa4, 0x56, 0xbd, 0xd0, + 0x74, 0xf7, 0x8e, 0xef, 0x85, 0xe6, 0x5e, 0xf6, 0x10, 0xfb, 0x19, 0xf4, + 0xaa, 0x16, 0xbe, 0x21, 0xb3, 0xfa, 0xf4, 0xd4, 0xe6, 0x3b, 0xe3, 0xe6, + 0x1e, 0x76, 0x42, 0x66, 0x2b, 0x29, 0x29, 0x9d, 0x1e, 0xd1, 0x77, 0x0d, + 0x6d, 0xe9, 0xea, 0xd3, 0x37, 0x90, 0x2b, 0x26, 0xf4, 0x9d, 0xf1, 0x2d, + 0x79, 0xd4, 0x9e, 0x95, 0x27, 0xad, 0x83, 0x72, 0x02, 0xf5, 0xf5, 0xa7, + 0xd1, 0xeb, 0xc7, 0xbb, 0xa9, 0x47, 0xd0, 0x6b, 0xb1, 0x07, 0x75, 0x64, + 0xdc, 0xfe, 0xb8, 0xf9, 0x3c, 0x24, 0x7b, 0xb5, 0xce, 0x3c, 0xf9, 0x5f, + 0x4e, 0x06, 0x79, 0xef, 0x06, 0x7a, 0xc7, 0x8c, 0x86, 0x33, 0x5c, 0xb8, + 0x2a, 0xe1, 0x86, 0xcd, 0x17, 0x08, 0xb7, 0x60, 0x78, 0x70, 0x06, 0xe0, + 0x42, 0x72, 0xd1, 0x0e, 0xc3, 0x46, 0x26, 0xc0, 0x27, 0x62, 0xfc, 0x68, + 0xa7, 0x57, 0x07, 0xef, 0x40, 0x6e, 0xbd, 0xbd, 0xff, 0x35, 0x6f, 0xff, + 0xb3, 0xde, 0xfe, 0xcb, 0x1b, 0xfb, 0xfd, 0xfc, 0xfa, 0x13, 0x47, 0x9a, + 0xe8, 0x7a, 0xad, 0xec, 0xc2, 0xcf, 0x7a, 0x74, 0x5d, 0xde, 0xa0, 0xcb, + 0x87, 0x87, 0x3c, 0x35, 0xcf, 0x8c, 0xcd, 0x8c, 0xd1, 0xfd, 0x90, 0xa3, + 0x23, 0x39, 0x1b, 0xbe, 0x51, 0x49, 0x8c, 0x15, 0xf5, 0x9d, 0x9a, 0x92, + 0xb5, 0xe8, 0xac, 0x4c, 0x58, 0x89, 0xb1, 0x69, 0x09, 0xc1, 0x96, 0x19, + 0x5b, 0x42, 0x52, 0x63, 0xcc, 0xc1, 0x33, 0x6f, 0x6f, 0x4f, 0xeb, 0xd5, + 0x26, 0x5a, 0x43, 0x2f, 0x91, 0x46, 0x97, 0xd6, 0xc8, 0xc0, 0x6d, 0x5a, + 0x5d, 0x78, 0x97, 0xd6, 0xab, 0xe5, 0x26, 0xf8, 0x73, 0x61, 0x0f, 0x3e, + 0xdc, 0x04, 0x4f, 0x7b, 0x66, 0x5d, 0x41, 0x7b, 0x26, 0x6d, 0x3f, 0x0b, + 0xdf, 0x90, 0xc8, 0x8e, 0x74, 0xf5, 0xe8, 0x7d, 0x03, 0x8e, 0x44, 0x50, + 0x6f, 0xb4, 0x62, 0x6d, 0xbd, 0xca, 0x5a, 0x44, 0xed, 0x6d, 0x95, 0x41, + 0xd8, 0x2c, 0x75, 0xe7, 0xde, 0x0d, 0x3e, 0xaa, 0x6b, 0x02, 0x47, 0x9e, + 0xb4, 0x49, 0xcb, 0x8f, 0x9d, 0x97, 0xa3, 0x83, 0x76, 0x49, 0x86, 0xcc, + 0x56, 0x9c, 0x5f, 0x6b, 0x68, 0x9c, 0x49, 0xd2, 0xb2, 0x32, 0xd4, 0x6f, + 0x7e, 0x0f, 0x7c, 0x8e, 0x57, 0x0d, 0xa9, 0x59, 0x89, 0xd8, 0x79, 0xe0, + 0xd8, 0x0f, 0xdd, 0xd4, 0x46, 0x48, 0x8f, 0xc8, 0x61, 0xd8, 0x77, 0x4d, + 0xe7, 0x45, 0xda, 0x71, 0x62, 0xa2, 0x88, 0x5a, 0xe7, 0x2f, 0x75, 0x6e, + 0x73, 0x9c, 0x1b, 0xc8, 0x6f, 0x13, 0x5b, 0x6c, 0x4f, 0x9d, 0x73, 0x6d, + 0x4f, 0x9d, 0x43, 0x0f, 0x7c, 0x32, 0x22, 0x6d, 0xcb, 0xf0, 0x9f, 0x97, + 0xf6, 0xb8, 0xf5, 0xdc, 0x4b, 0xfc, 0xdd, 0x09, 0xf1, 0xee, 0x64, 0x58, + 0xac, 0x93, 0x3a, 0x1f, 0x40, 0xde, 0xe3, 0x32, 0x7d, 0x86, 0x31, 0xd5, + 0x92, 0x81, 0x93, 0xd4, 0x07, 0xeb, 0x9a, 0x85, 0xd1, 0x02, 0x7c, 0x64, + 0x06, 0x71, 0x41, 0x2d, 0xdf, 0x94, 0x82, 0x45, 0x39, 0x74, 0x49, 0xfb, + 0x32, 0xfa, 0xf1, 0x65, 0xc4, 0x86, 0xe5, 0x98, 0xb4, 0xc0, 0xb7, 0xd4, + 0xb9, 0xa8, 0x51, 0x9a, 0x7f, 0x17, 0xfe, 0xc0, 0xdf, 0x70, 0x50, 0x5b, + 0x9e, 0x8b, 0x19, 0xf4, 0x2d, 0x75, 0x8e, 0x76, 0x8e, 0x72, 0xea, 0x1c, + 0xed, 0x9c, 0x74, 0xf8, 0xfe, 0x82, 0xf7, 0x73, 0x23, 0xfa, 0x9e, 0xfa, + 0x86, 0x4d, 0x5e, 0x7e, 0x20, 0xd9, 0x2a, 0x6b, 0x44, 0xf2, 0x23, 0xdd, + 0xa8, 0x65, 0x76, 0x65, 0xed, 0x81, 0xb1, 0x75, 0xf9, 0xa8, 0x7c, 0xdd, + 0xf9, 0x11, 0xf8, 0x22, 0x1f, 0xcd, 0x7c, 0x91, 0xa7, 0x2e, 0x69, 0xd1, + 0x7c, 0xf9, 0xfc, 0x40, 0xd0, 0xe0, 0x67, 0xef, 0xc9, 0x18, 0xf0, 0x7f, + 0x11, 0x31, 0xa0, 0x0f, 0xcf, 0x27, 0xf0, 0x44, 0x4a, 0x3b, 0x47, 0xde, + 0xc9, 0xeb, 0x75, 0xd4, 0x8d, 0x3e, 0x9f, 0x53, 0x78, 0x7f, 0x55, 0xa6, + 0xe7, 0x9d, 0xe3, 0xc8, 0xab, 0xbc, 0x43, 0xef, 0x71, 0xef, 0x83, 0xb7, + 0xf2, 0xfe, 0xaa, 0xb8, 0xf2, 0x49, 0x98, 0x35, 0xc1, 0xfb, 0xd2, 0x56, + 0x59, 0x34, 0xc7, 0x8e, 0x98, 0xae, 0xc3, 0x0f, 0xd7, 0x19, 0x27, 0x28, + 0xa3, 0xeb, 0x92, 0x9d, 0xe7, 0xfd, 0x97, 0x8b, 0x6f, 0xaa, 0xee, 0xc7, + 0x8d, 0xe6, 0x3d, 0x36, 0xe0, 0xfa, 0x00, 0x47, 0xba, 0xd6, 0x28, 0x3f, + 0xc4, 0x9c, 0xde, 0xa6, 0x58, 0xd3, 0xbc, 0x6f, 0x4c, 0x9e, 0x43, 0x1d, + 0xf0, 0x9a, 0xbd, 0x49, 0xae, 0x53, 0xac, 0x85, 0x6a, 0xf5, 0x49, 0xf8, + 0x64, 0x0b, 0x62, 0x99, 0x29, 0xeb, 0xe5, 0x56, 0xa9, 0xa1, 0xde, 0x59, + 0x5c, 0x62, 0x2c, 0x24, 0xed, 0xed, 0x98, 0x77, 0xe3, 0x17, 0x63, 0xed, + 0x7a, 0x19, 0x79, 0x16, 0xbe, 0xbd, 0x5e, 0x8e, 0xe2, 0xd9, 0x87, 0xa7, + 0x85, 0x67, 0x1c, 0xcf, 0x24, 0x9e, 0x23, 0x78, 0x8e, 0xe0, 0x69, 0x61, + 0x6f, 0x0c, 0x4f, 0xbf, 0x67, 0x20, 0xae, 0xdb, 0x7c, 0x97, 0xf4, 0x79, + 0xa8, 0x15, 0x2d, 0xe6, 0xb4, 0xb0, 0x9d, 0x43, 0x1f, 0x91, 0x1d, 0x61, + 0xad, 0xc7, 0x9a, 0xef, 0x03, 0xc7, 0xb4, 0xd8, 0x97, 0x17, 0x8d, 0xfd, + 0x43, 0xcc, 0x0b, 0x55, 0xe4, 0x85, 0xf7, 0x76, 0xa3, 0x7f, 0x34, 0x0f, + 0xe8, 0xbb, 0xa3, 0x79, 0x7c, 0xf3, 0x1d, 0x3d, 0x6f, 0x74, 0x06, 0x79, + 0x8a, 0xf1, 0xd3, 0xc1, 0x9e, 0x3c, 0xe2, 0xf8, 0x2e, 0xf8, 0x5f, 0x06, + 0x71, 0x1b, 0xef, 0x0b, 0x97, 0x76, 0xbb, 0x39, 0x15, 0xf9, 0x56, 0x6d, + 0xbd, 0xaf, 0xb1, 0xb1, 0x67, 0xbb, 0xde, 0xa0, 0x13, 0x38, 0x12, 0xd5, + 0x05, 0xf8, 0xe0, 0xf7, 0xed, 0xe3, 0xba, 0xb6, 0xa3, 0x2e, 0x9e, 0x45, + 0x8d, 0x9a, 0x9b, 0x63, 0x0d, 0x73, 0x0c, 0x7d, 0x09, 0xfa, 0xb3, 0x28, + 0x7b, 0x72, 0xe6, 0x02, 0x5d, 0x8b, 0x46, 0xa5, 0x9d, 0x79, 0xe0, 0x06, + 0xce, 0x03, 0x5f, 0x8b, 0x0e, 0x64, 0xf6, 0x08, 0x6a, 0x42, 0xc7, 0x09, + 0x5b, 0xfb, 0x25, 0xfe, 0x38, 0x63, 0x8e, 0x60, 0xbf, 0x29, 0xee, 0xbd, + 0x3a, 0xe2, 0xee, 0xa4, 0xfe, 0xbd, 0x18, 0xc6, 0x65, 0x63, 0xef, 0x1d, + 0xc0, 0xc5, 0x79, 0xde, 0x69, 0x8b, 0xec, 0x9f, 0x73, 0x6b, 0x5a, 0x65, + 0x35, 0xe3, 0xfb, 0x39, 0x0f, 0x1f, 0xd7, 0x95, 0xf7, 0xdb, 0xc6, 0x1e, + 0xc8, 0x08, 0xfe, 0x00, 0x1d, 0x9f, 0x40, 0xfd, 0x7c, 0x11, 0x7a, 0x79, + 0x0d, 0x3a, 0xb9, 0x54, 0xa6, 0xad, 0x0f, 0xc3, 0xee, 0x21, 0xc3, 0x49, + 0xe2, 0x1a, 0xd1, 0x67, 0x5f, 0x2c, 0x23, 0x76, 0x32, 0xfe, 0xa9, 0x5f, + 0x8d, 0xb2, 0x3e, 0x64, 0x1e, 0x74, 0xf1, 0xf4, 0xb9, 0x70, 0xe2, 0xaf, + 0xed, 0xd6, 0xf4, 0xd4, 0xf4, 0x3d, 0x18, 0xe5, 0x04, 0x1b, 0xe4, 0x6f, + 0x04, 0x1a, 0xe6, 0x0b, 0x51, 0x7d, 0x0f, 0xaf, 0x38, 0x47, 0x3e, 0x46, + 0x24, 0x3b, 0xe7, 0xef, 0xeb, 0xc6, 0xbe, 0x1d, 0x4d, 0xb8, 0xee, 0xdc, + 0xc2, 0x83, 0xf2, 0x78, 0xe0, 0xfa, 0xd6, 0xba, 0x3f, 0x61, 0x16, 0x37, + 0xee, 0x86, 0x99, 0x7f, 0xa9, 0x9b, 0x14, 0xf6, 0xfb, 0xfa, 0xe9, 0xf3, + 0x7a, 0x81, 0xc4, 0x6c, 0x51, 0x58, 0xab, 0x50, 0x47, 0x63, 0xf0, 0x6b, + 0x13, 0xf8, 0x6d, 0xa9, 0x96, 0xdb, 0x44, 0xf5, 0xb0, 0x37, 0x66, 0xad, + 0xdc, 0x7c, 0xe6, 0xaf, 0x78, 0x67, 0xa2, 0x9f, 0x3e, 0xc5, 0xba, 0x59, + 0xe7, 0x19, 0xc0, 0x74, 0x6c, 0xa1, 0xed, 0x17, 0x3d, 0x38, 0xae, 0x27, + 0xa5, 0x88, 0x3a, 0x34, 0x37, 0x87, 0x8a, 0x1e, 0xf1, 0x5b, 0xa5, 0xf9, + 0xbb, 0x16, 0xef, 0xf0, 0x86, 0xe3, 0xd3, 0xa0, 0xb1, 0x68, 0x66, 0x78, + 0x6f, 0x06, 0x1c, 0xbd, 0x5b, 0x70, 0x8c, 0x7b, 0x38, 0xc6, 0xa5, 0x74, + 0x66, 0x02, 0xbe, 0x96, 0x41, 0x7e, 0xef, 0x37, 0x1f, 0x91, 0x4f, 0xa0, + 0xb9, 0xc6, 0xdc, 0xd9, 0x11, 0xe8, 0xc9, 0x71, 0xf6, 0xdb, 0x87, 0x40, + 0xf7, 0x77, 0x90, 0x5b, 0xfd, 0x9a, 0xa7, 0x14, 0x0b, 0x21, 0x87, 0x1d, + 0xd1, 0xbf, 0xc3, 0x16, 0x4d, 0x13, 0xf6, 0xaa, 0x8c, 0xe1, 0x24, 0xda, + 0x7b, 0xe4, 0xb7, 0x59, 0xe4, 0x2a, 0xf2, 0xd9, 0x29, 0x25, 0xd3, 0x78, + 0x38, 0x84, 0xba, 0x26, 0x3b, 0x47, 0x3f, 0x92, 0x81, 0x50, 0xba, 0x15, + 0x35, 0xa9, 0x23, 0x6f, 0xdb, 0xfc, 0x77, 0x0a, 0xb3, 0x72, 0xb1, 0x6e, + 0xe2, 0xf9, 0x5d, 0xe8, 0xe1, 0x4f, 0xf1, 0xfe, 0x76, 0x0f, 0xea, 0x3e, + 0xac, 0x64, 0x60, 0xbb, 0x49, 0x5d, 0xcf, 0xb0, 0x8e, 0xa8, 0x21, 0xdf, + 0x2a, 0xe4, 0x1a, 0xd4, 0x55, 0x63, 0xac, 0x5d, 0x9f, 0x5b, 0xbc, 0x26, + 0x97, 0xe6, 0xf9, 0x3b, 0x28, 0xf3, 0xf2, 0x41, 0xc6, 0x03, 0x73, 0x26, + 0x85, 0xb9, 0x25, 0xc6, 0x32, 0x7c, 0x37, 0xe0, 0x40, 0x3d, 0xa8, 0x11, + 0x50, 0x6b, 0xaf, 0x5b, 0x49, 0xf0, 0x79, 0x4d, 0x2e, 0xce, 0x87, 0x65, + 0xd1, 0x62, 0x5d, 0x24, 0xf1, 0x2c, 0x60, 0x2f, 0x2e, 0xfd, 0x93, 0x6b, + 0x13, 0x84, 0x47, 0xcf, 0x53, 0x44, 0x5d, 0xf7, 0x88, 0xde, 0xfb, 0xd3, + 0xf4, 0x4c, 0x9a, 0x9a, 0xfb, 0xbc, 0x82, 0x5c, 0xa4, 0x3f, 0xe9, 0xdf, + 0x28, 0x58, 0x1b, 0x1c, 0x83, 0xcd, 0xb2, 0x76, 0x67, 0x3f, 0x80, 0xf7, + 0x3a, 0xd7, 0xc9, 0x3b, 0x9e, 0x0b, 0xfd, 0x90, 0x0d, 0xfd, 0x9e, 0x77, + 0x62, 0xc8, 0xa3, 0x8a, 0xbe, 0x5e, 0xd2, 0xb1, 0xa0, 0x54, 0x29, 0x20, + 0xa7, 0x20, 0x06, 0xd8, 0xbd, 0xb0, 0xc5, 0x49, 0xe8, 0x72, 0x0c, 0x70, + 0x5b, 0x72, 0xc9, 0x6a, 0x49, 0xd7, 0x65, 0x6a, 0xe5, 0xf6, 0xfd, 0x4d, + 0x1e, 0xfe, 0xa3, 0x56, 0x61, 0x5b, 0xf0, 0x21, 0xb5, 0x1a, 0xc5, 0x13, + 0xf1, 0x78, 0x15, 0xfd, 0x45, 0x99, 0xf7, 0x43, 0xe8, 0x0d, 0xca, 0xbc, + 0x3b, 0x49, 0xe2, 0x39, 0xc2, 0xfb, 0x22, 0x2f, 0xae, 0x11, 0x3f, 0xe9, + 0xf0, 0xe3, 0x0b, 0x6b, 0x49, 0xc6, 0x17, 0xbf, 0x9e, 0x74, 0x6d, 0xe1, + 0x44, 0x85, 0x31, 0x84, 0x76, 0xdd, 0x8f, 0xb8, 0x45, 0x5b, 0x70, 0x6b, + 0xc9, 0xa5, 0xaa, 0x2b, 0xb3, 0xe9, 0xc6, 0x05, 0x9d, 0x23, 0x0e, 0x88, + 0x05, 0x1b, 0xa3, 0xec, 0xb0, 0xa6, 0x73, 0xc0, 0x79, 0xc9, 0xe8, 0x27, + 0x65, 0xf6, 0xaa, 0x64, 0x96, 0x46, 0xe4, 0x05, 0x1d, 0xb7, 0xfc, 0x98, + 0xc5, 0x1a, 0x92, 0xbf, 0x1f, 0x27, 0xe5, 0xf9, 0xd3, 0xd7, 0x24, 0xfb, + 0x22, 0xe3, 0xd6, 0x70, 0x6c, 0x87, 0xc1, 0x58, 0xe5, 0x48, 0x1d, 0xb9, + 0xe9, 0x11, 0x9b, 0xff, 0x16, 0x20, 0x84, 0x9e, 0xce, 0x91, 0xd6, 0xd1, + 0x84, 0x1d, 0x37, 0xfa, 0x9f, 0xd8, 0x61, 0x30, 0x37, 0x0e, 0x9b, 0x4f, + 0x89, 0x7f, 0x1f, 0xd5, 0x26, 0x4f, 0xe9, 0xbb, 0x0a, 0xb8, 0xed, 0xdc, + 0xfb, 0xfa, 0x77, 0x94, 0x1b, 0x29, 0xca, 0x1a, 0xdf, 0xab, 0x9c, 0x2f, + 0x46, 0x6e, 0xa4, 0x5a, 0xa4, 0x74, 0x87, 0xe3, 0x3c, 0x39, 0xfa, 0xc0, + 0x6e, 0xf7, 0xdf, 0x8b, 0x3c, 0x7d, 0x87, 0x1b, 0x0b, 0x7e, 0xcd, 0xfb, + 0xfe, 0x3a, 0x9e, 0xb4, 0x6d, 0xe6, 0x5b, 0xe6, 0x47, 0xea, 0x0d, 0xcf, + 0x25, 0xbe, 0x33, 0xf7, 0xce, 0x22, 0xf7, 0x32, 0x5f, 0xee, 0x92, 0x1c, + 0x7f, 0xe7, 0x53, 0x7a, 0xbe, 0xe8, 0xd6, 0xd2, 0x1e, 0x5c, 0x75, 0x4a, + 0xa6, 0xab, 0xac, 0xa1, 0x2e, 0x22, 0x97, 0x0d, 0xc1, 0x56, 0x99, 0xd3, + 0x8e, 0x23, 0x9f, 0xf3, 0xf7, 0x69, 0xac, 0x2d, 0x70, 0x5f, 0x22, 0x19, + 0x57, 0xcd, 0xbf, 0x2b, 0xdd, 0x8c, 0xf2, 0x3e, 0xea, 0xfc, 0x10, 0xf4, + 0xfe, 0x15, 0xf6, 0x16, 0x03, 0xda, 0x46, 0xb2, 0x2f, 0x51, 0xf6, 0xee, + 0xef, 0xd7, 0xd2, 0xed, 0xfa, 0x00, 0xeb, 0x80, 0xcf, 0x40, 0x2e, 0x07, + 0xec, 0x6b, 0xcc, 0xdd, 0xff, 0xa6, 0xac, 0xe1, 0xe4, 0x53, 0x06, 0x7d, + 0x1b, 0xdf, 0x4b, 0x21, 0x59, 0x88, 0x92, 0x7f, 0xc8, 0xcb, 0xa0, 0xef, + 0x6c, 0x27, 0x87, 0xad, 0x32, 0xf8, 0x0b, 0xc8, 0x80, 0xb2, 0xf4, 0x65, + 0xc0, 0xf7, 0x09, 0xe8, 0x8b, 0x3d, 0x43, 0xbf, 0xee, 0x23, 0x4b, 0x0d, + 0xf7, 0xec, 0x52, 0xa5, 0x99, 0x66, 0xd2, 0x4b, 0x9d, 0x9e, 0x97, 0x9c, + 0xd6, 0xef, 0xac, 0xe4, 0xaa, 0xe7, 0x65, 0x7f, 0x75, 0x56, 0x1e, 0xb5, + 0x1e, 0x06, 0xbf, 0x57, 0x9c, 0x82, 0xa5, 0x7b, 0x95, 0xb1, 0x3c, 0xce, + 0x2e, 0x8c, 0xf4, 0xca, 0x4d, 0xd4, 0x1d, 0xcf, 0x2e, 0x9a, 0xf2, 0x3f, + 0x9d, 0x5b, 0x5f, 0x6c, 0x5b, 0xd5, 0x19, 0xff, 0x7c, 0x6d, 0x27, 0x69, + 0x68, 0xc2, 0xad, 0xeb, 0x24, 0x6e, 0x9a, 0x51, 0x3b, 0xbe, 0x6d, 0x23, + 0x92, 0xa2, 0xdb, 0x10, 0x68, 0xd4, 0x65, 0x8a, 0x71, 0x42, 0x17, 0xb6, + 0x22, 0xd2, 0xae, 0xab, 0x2a, 0x8d, 0x81, 0xe5, 0xa6, 0x7f, 0xd8, 0xc3, + 0x0a, 0x85, 0x75, 0x08, 0x21, 0xd5, 0xb8, 0xe9, 0xd6, 0x69, 0x21, 0x4e, + 0xff, 0x2d, 0x8c, 0x87, 0xcd, 0x4a, 0xd2, 0x96, 0x4d, 0x11, 0x2e, 0x88, + 0xb2, 0x3d, 0x6c, 0xa3, 0x4a, 0x01, 0xed, 0x79, 0x7b, 0x99, 0x34, 0x36, + 0x65, 0x05, 0x36, 0x5e, 0x36, 0xf5, 0x81, 0x07, 0xa6, 0xd1, 0x79, 0xbf, + 0xdf, 0x77, 0xee, 0x75, 0x6c, 0x13, 0x84, 0xb4, 0x48, 0x91, 0xef, 0x39, + 0xf7, 0xdc, 0x73, 0xce, 0x3d, 0xdf, 0xff, 0xef, 0xfb, 0xdd, 0x8c, 0x3d, + 0x28, 0x3f, 0xd2, 0x5c, 0x3e, 0xe3, 0x93, 0x00, 0x7c, 0x52, 0x83, 0x2d, + 0x90, 0x36, 0x27, 0x76, 0x53, 0xe8, 0x53, 0x86, 0x41, 0xeb, 0xb8, 0xf1, + 0x9b, 0x6d, 0x73, 0x7f, 0xcb, 0x59, 0xf8, 0xee, 0xee, 0x7d, 0x6d, 0x7e, + 0xce, 0xd7, 0xf8, 0xb7, 0x7f, 0xf2, 0x6a, 0x68, 0x83, 0x32, 0x83, 0xfd, + 0xbc, 0xa1, 0x7a, 0xd6, 0x01, 0x2f, 0x31, 0x37, 0x1d, 0xd3, 0xfc, 0x43, + 0x78, 0x9a, 0x3a, 0xea, 0x2a, 0x74, 0xd4, 0x10, 0x75, 0xd7, 0xf0, 0xbc, + 0xcb, 0xfc, 0x40, 0x54, 0xfe, 0x38, 0x45, 0x3d, 0x1c, 0x97, 0x3f, 0x4c, + 0x3d, 0x8b, 0xfd, 0x24, 0x8a, 0xcc, 0x51, 0xde, 0x98, 0xc9, 0xd1, 0x4f, + 0x52, 0x7f, 0x3e, 0xed, 0x3e, 0xad, 0x76, 0x20, 0x6e, 0xe5, 0xd7, 0x87, + 0x55, 0xdf, 0x1c, 0xd3, 0xda, 0x6e, 0xdc, 0xea, 0x92, 0x1b, 0x17, 0x8c, + 0x8e, 0x0d, 0x4f, 0x47, 0x03, 0x23, 0x0b, 0xb4, 0x4b, 0xc9, 0x58, 0xd6, + 0x6a, 0x94, 0x43, 0x51, 0xe6, 0x9e, 0x53, 0xd4, 0xcf, 0xb0, 0x85, 0xbd, + 0x76, 0xd6, 0x6a, 0xf2, 0xec, 0x4f, 0xac, 0x4e, 0xcf, 0x1e, 0xf3, 0xf4, + 0x2c, 0xef, 0xa5, 0x68, 0x03, 0x20, 0x93, 0x89, 0x99, 0x51, 0x2b, 0x09, + 0x9b, 0x87, 0xeb, 0x45, 0xce, 0x1f, 0x97, 0xe3, 0x8b, 0x47, 0xe1, 0x7f, + 0xf7, 0xda, 0x7b, 0x69, 0x57, 0xed, 0x21, 0xe2, 0x71, 0xb0, 0xfe, 0x97, + 0xea, 0xe6, 0x7a, 0xd4, 0x9b, 0x8b, 0xf7, 0x21, 0xe7, 0xd3, 0xac, 0xd7, + 0x36, 0x32, 0x9f, 0xa3, 0x7b, 0xad, 0x1d, 0xbb, 0xa7, 0xb2, 0xee, 0x64, + 0xc1, 0xf1, 0xb0, 0x61, 0xf8, 0x85, 0x2f, 0xf4, 0x8d, 0x08, 0xd7, 0xe4, + 0x7a, 0xad, 0x92, 0xde, 0x0f, 0xfd, 0x32, 0xcd, 0xff, 0x9c, 0x57, 0xbb, + 0x42, 0xbc, 0x12, 0xed, 0x5c, 0xc5, 0x36, 0x7d, 0xc5, 0x9b, 0xaf, 0xbf, + 0x5d, 0x9a, 0xa3, 0x55, 0xe3, 0x99, 0x5b, 0x61, 0x3b, 0x2e, 0xb9, 0x45, + 0xfe, 0x96, 0xcb, 0x11, 0xa7, 0x41, 0xf6, 0xda, 0x1b, 0xeb, 0xe6, 0xd8, + 0x86, 0x3e, 0xe3, 0x13, 0x04, 0xa7, 0x03, 0x9e, 0x6f, 0xb1, 0x89, 0x7e, + 0x93, 0x77, 0xdd, 0xa4, 0x39, 0x99, 0xb8, 0xd5, 0x59, 0xf7, 0x1e, 0x9b, + 0x2a, 0x76, 0x38, 0x6e, 0x51, 0x77, 0x36, 0x46, 0xa5, 0x95, 0x3c, 0x54, + 0x56, 0x3f, 0x3e, 0xe4, 0x18, 0xcc, 0x45, 0xd4, 0x39, 0xd2, 0xce, 0x9c, + 0xfd, 0x5b, 0x7a, 0x6e, 0x2d, 0xf4, 0x09, 0x70, 0x0d, 0x3e, 0xf9, 0x4c, + 0xbe, 0x97, 0xb9, 0x5e, 0xcc, 0xdf, 0xcc, 0xf9, 0x5d, 0xef, 0x9c, 0x13, + 0x6e, 0xce, 0xba, 0x5f, 0xb2, 0x17, 0x0c, 0xff, 0xa5, 0x1d, 0xf0, 0x5e, + 0x2b, 0xda, 0x0b, 0xb4, 0x09, 0x9f, 0x37, 0x8f, 0x6f, 0x1b, 0x7a, 0xd4, + 0x36, 0x9c, 0x2a, 0x90, 0x3f, 0xc9, 0x97, 0x3e, 0x3f, 0xfa, 0x3a, 0x8f, + 0x3c, 0x4a, 0x3d, 0x3b, 0x28, 0x67, 0x0b, 0x3c, 0x9b, 0x94, 0xd6, 0xb4, + 0x36, 0x9f, 0x3b, 0xa8, 0x98, 0xac, 0xee, 0xe9, 0xc4, 0x4b, 0x39, 0x19, + 0x96, 0xab, 0x2e, 0xcf, 0x2c, 0x51, 0xcc, 0x04, 0x5b, 0xaa, 0xde, 0x7f, + 0xbf, 0x9e, 0x59, 0x58, 0x7d, 0xc6, 0x18, 0xc6, 0x3e, 0xef, 0xd1, 0xbb, + 0x55, 0xcf, 0x36, 0x53, 0x43, 0x9f, 0xaf, 0xeb, 0x39, 0x85, 0xa1, 0x13, + 0x59, 0xdf, 0x0f, 0x47, 0xf8, 0x0c, 0xd7, 0xa5, 0xcf, 0xc7, 0xb5, 0xc8, + 0x7b, 0xdd, 0xb0, 0xd8, 0xfd, 0x12, 0xdc, 0x09, 0xd1, 0xdf, 0xc9, 0x3a, + 0x72, 0x00, 0xb2, 0xba, 0xd9, 0x60, 0x60, 0xc6, 0x8d, 0xaf, 0x91, 0xb1, + 0xae, 0xe1, 0x1c, 0x11, 0xab, 0xc0, 0x8f, 0x3e, 0xf5, 0x93, 0xdb, 0x98, + 0x2f, 0xe3, 0xf9, 0xeb, 0x03, 0x98, 0xdf, 0xf1, 0xea, 0xea, 0x53, 0xdb, + 0xc9, 0xab, 0xa3, 0x5a, 0x1f, 0xe4, 0x33, 0x94, 0x63, 0x9e, 0x19, 0xe9, + 0xf2, 0x1e, 0x9e, 0x67, 0x7b, 0x5b, 0x1d, 0x1d, 0x93, 0xde, 0xfe, 0xfc, + 0xfb, 0x61, 0x09, 0xb7, 0x53, 0xc7, 0x45, 0x25, 0x39, 0xcd, 0x98, 0x05, + 0xb6, 0x6b, 0x9c, 0x73, 0x7d, 0xb1, 0x2e, 0xce, 0xfc, 0x9f, 0xba, 0x38, + 0x63, 0x7d, 0xa4, 0xbc, 0x13, 0xd6, 0x3c, 0xd6, 0xe7, 0xd3, 0xb5, 0x58, + 0x43, 0x57, 0xbf, 0x76, 0x1f, 0xad, 0xd0, 0xf1, 0x87, 0x05, 0xda, 0xab, + 0x94, 0xe6, 0x94, 0xff, 0x3e, 0xc5, 0xb3, 0xe5, 0x1e, 0xaf, 0x72, 0x8f, + 0xc3, 0x4b, 0x8a, 0x83, 0x7c, 0x58, 0x65, 0xf8, 0x74, 0x81, 0x3a, 0xa6, + 0x45, 0xe6, 0x67, 0x7c, 0x3d, 0x33, 0xe6, 0xf9, 0xb8, 0xf9, 0xf5, 0x0d, + 0xaa, 0x67, 0xe0, 0xdd, 0x38, 0x23, 0x9e, 0x7d, 0xe9, 0x92, 0xb9, 0x0b, + 0xb4, 0xbb, 0x49, 0xf4, 0x45, 0x03, 0x73, 0x0b, 0xac, 0x4d, 0x12, 0x8b, + 0x32, 0x2c, 0xac, 0xfb, 0x8f, 0xd8, 0xa7, 0x20, 0x6f, 0x31, 0x79, 0x7f, + 0x8a, 0x3e, 0x7d, 0x03, 0x7c, 0xe3, 0xd6, 0xba, 0xf3, 0xdd, 0x51, 0xf1, + 0x09, 0x6b, 0xe9, 0x1e, 0xef, 0x90, 0x66, 0xf2, 0xb9, 0x63, 0xdf, 0x10, + 0xfa, 0x60, 0xbc, 0xce, 0x22, 0x16, 0x60, 0xec, 0x11, 0xd7, 0xd8, 0x63, + 0xae, 0xc8, 0xbe, 0x16, 0x2f, 0xaf, 0xd4, 0xa2, 0xbc, 0x42, 0x7e, 0xcb, + 0xa8, 0xff, 0x3d, 0xa4, 0x3a, 0x2b, 0x3f, 0xd5, 0x6b, 0x70, 0x2c, 0x76, + 0x4c, 0x79, 0x4f, 0x6a, 0x78, 0x2f, 0xe6, 0xad, 0x3d, 0xd6, 0x61, 0x7c, + 0x2b, 0x5b, 0xf5, 0x4d, 0x58, 0xc7, 0xd1, 0xae, 0x70, 0x7e, 0xf2, 0x06, + 0x79, 0x84, 0x3a, 0xcf, 0x1f, 0xe7, 0xd3, 0xc3, 0x6f, 0x73, 0x3c, 0xf9, + 0xbf, 0x1a, 0x8b, 0xe0, 0xcb, 0xaa, 0xdf, 0xe7, 0xcb, 0x1d, 0xef, 0x55, + 0xdb, 0x04, 0xca, 0x5d, 0x75, 0x7d, 0xd2, 0x96, 0xc8, 0xf4, 0x0a, 0x5d, + 0xd2, 0xfd, 0xdc, 0xff, 0xf3, 0xcc, 0xed, 0x42, 0xde, 0x56, 0xa3, 0xcd, + 0x09, 0xa5, 0x4d, 0x06, 0xb4, 0x89, 0x28, 0x6d, 0x18, 0xef, 0x3d, 0xe5, + 0xf1, 0x5b, 0x0b, 0xce, 0x8b, 0xb9, 0x5a, 0xe8, 0xba, 0x7d, 0xd4, 0xf9, + 0xcf, 0x76, 0x68, 0x7d, 0xd0, 0xa1, 0xee, 0x5b, 0x0b, 0x7d, 0xc6, 0xf6, + 0x56, 0xf5, 0x47, 0x4c, 0xbc, 0x15, 0xd7, 0x3c, 0x68, 0x10, 0xfa, 0x79, + 0x6e, 0x0a, 0xbe, 0x1a, 0x71, 0x6f, 0x35, 0xb4, 0xfa, 0x8e, 0x77, 0x5e, + 0xf3, 0x4a, 0x1b, 0xca, 0x00, 0xf5, 0xe6, 0x3a, 0xcc, 0xb7, 0x27, 0xda, + 0x07, 0xfe, 0xfa, 0x19, 0xfa, 0x37, 0x6b, 0x3c, 0x11, 0x84, 0xcc, 0xdf, + 0x9c, 0x6a, 0xf7, 0x62, 0x38, 0x07, 0x6d, 0xc4, 0xad, 0x53, 0x11, 0xc6, + 0x14, 0x68, 0xf7, 0x48, 0xc3, 0x34, 0xe2, 0x57, 0xe8, 0xf1, 0x25, 0xb5, + 0x47, 0x7d, 0xb8, 0x7f, 0x07, 0x71, 0x7e, 0xb8, 0x3e, 0x8a, 0xe7, 0x7a, + 0x0d, 0x16, 0x21, 0xba, 0x45, 0xcf, 0x74, 0x6e, 0x2a, 0x11, 0x3b, 0x2c, + 0x5e, 0xdf, 0xb8, 0xab, 0xfa, 0x60, 0x65, 0x5f, 0x0f, 0xca, 0x9e, 0x8a, + 0xbd, 0x60, 0x1c, 0x0d, 0x1f, 0x7e, 0xc6, 0xd8, 0x83, 0x7c, 0xb1, 0x4f, + 0xf1, 0x51, 0xc1, 0xa1, 0x45, 0x9c, 0x25, 0x7d, 0xd2, 0x65, 0xf8, 0xe1, + 0x2e, 0xce, 0x90, 0x7e, 0x77, 0xf9, 0xe4, 0xa4, 0x9b, 0x62, 0x7d, 0x0c, + 0xfa, 0xe0, 0xa4, 0x8c, 0x20, 0x2e, 0x18, 0x09, 0xb6, 0x32, 0xaf, 0x0c, + 0xdf, 0x30, 0xe7, 0xe5, 0x1e, 0xfb, 0x98, 0x33, 0x95, 0x73, 0x0b, 0xdc, + 0x3b, 0x65, 0xdb, 0xc4, 0xde, 0x73, 0x53, 0xdc, 0xaf, 0xc9, 0x43, 0xb0, + 0x6d, 0x4d, 0xbb, 0xf8, 0xe5, 0x59, 0x0c, 0xe0, 0x77, 0x10, 0xf2, 0xc0, + 0xb1, 0xf8, 0x5d, 0x58, 0x96, 0x77, 0x2f, 0xf8, 0xb6, 0x3d, 0x20, 0x6f, + 0x3b, 0xe5, 0x93, 0xa7, 0xdc, 0xf5, 0x3c, 0x03, 0x37, 0xc7, 0x9a, 0xb5, + 0xe3, 0xb8, 0x79, 0x29, 0x97, 0x97, 0xdc, 0xa5, 0xf5, 0x96, 0xd2, 0x92, + 0xf2, 0xbf, 0x8c, 0x33, 0xbc, 0x7e, 0xaf, 0x25, 0x86, 0x7e, 0xa4, 0xcd, + 0x67, 0x6b, 0x7f, 0xd5, 0xb6, 0xc0, 0xd7, 0x7f, 0xe4, 0x47, 0xf2, 0xe5, + 0xb2, 0xec, 0x52, 0xfd, 0xbf, 0xda, 0x73, 0xd5, 0xba, 0xdf, 0xf7, 0x6f, + 0xa9, 0xdf, 0xb5, 0xfe, 0xa3, 0xf1, 0xc1, 0x96, 0xe9, 0x7a, 0x9d, 0xf0, + 0x98, 0x57, 0x57, 0x58, 0x8d, 0xf7, 0x0e, 0x78, 0x7a, 0x21, 0xa5, 0xbe, + 0x73, 0xca, 0xa6, 0x7e, 0xe0, 0x7e, 0x9a, 0xe5, 0xe0, 0xec, 0x6d, 0xd0, + 0xc4, 0xd7, 0xc1, 0x8c, 0xfb, 0x7c, 0xdd, 0xd1, 0xea, 0xf9, 0xc2, 0x96, + 0x74, 0x9f, 0xa3, 0xef, 0xe4, 0x40, 0x8f, 0xb6, 0x49, 0x66, 0x3c, 0x28, + 0xc9, 0x73, 0x1b, 0x62, 0xc6, 0xd7, 0x25, 0xff, 0x41, 0xde, 0xb4, 0x4f, + 0x7d, 0x51, 0xf4, 0xdf, 0x29, 0x5c, 0xdb, 0xf0, 0x33, 0xe4, 0x79, 0x9f, + 0x7f, 0xcf, 0xae, 0xe3, 0xd1, 0x9d, 0x1e, 0x8f, 0xf2, 0xbe, 0x65, 0xea, + 0x1f, 0x18, 0xdb, 0x7d, 0x8e, 0x7b, 0x34, 0xcf, 0x75, 0x9f, 0x33, 0xf1, + 0x7a, 0xed, 0x73, 0x7d, 0x95, 0xe7, 0x70, 0xbf, 0x47, 0xb1, 0x61, 0x98, + 0x7b, 0xd7, 0x20, 0x7c, 0xba, 0x3e, 0xda, 0x1c, 0xda, 0xef, 0xcd, 0xee, + 0x2e, 0x21, 0xbf, 0x27, 0x3c, 0x9e, 0xa3, 0xbe, 0x89, 0x78, 0xfa, 0x66, + 0xc5, 0xbe, 0x8c, 0x18, 0xfc, 0x09, 0x73, 0x22, 0x55, 0xf6, 0xe5, 0x71, + 0xf3, 0x6e, 0x35, 0xf6, 0xe5, 0x4e, 0x6f, 0x1e, 0xff, 0x9e, 0xaf, 0x57, + 0xfc, 0xb6, 0xaf, 0x57, 0xea, 0x7d, 0x5a, 0x9f, 0xf6, 0xb5, 0xb8, 0xaf, + 0xea, 0x98, 0x2f, 0xbf, 0x6a, 0xde, 0x25, 0x8b, 0x98, 0x8d, 0x3e, 0x65, + 0x22, 0x67, 0x30, 0xd3, 0xd6, 0x59, 0x8b, 0xb8, 0x0f, 0xe7, 0xc7, 0x92, + 0x8e, 0xdc, 0xd6, 0xd8, 0xfa, 0xf4, 0xec, 0x98, 0xe6, 0x79, 0xe6, 0x5c, + 0x4f, 0xef, 0x44, 0x77, 0x43, 0xae, 0x5e, 0x89, 0xac, 0x60, 0x8a, 0x66, + 0x4e, 0xa4, 0x61, 0x87, 0x52, 0x5a, 0x2f, 0xfb, 0x2e, 0xf6, 0x3b, 0xa8, + 0x78, 0xae, 0x35, 0xce, 0x73, 0xf2, 0x90, 0x5d, 0xd6, 0xda, 0x4d, 0xd3, + 0x50, 0xf1, 0x44, 0xd3, 0x8b, 0x3e, 0xdf, 0x93, 0x9f, 0x66, 0x4e, 0x1c, + 0x9c, 0x29, 0x0f, 0x87, 0xb6, 0xf7, 0xda, 0x79, 0x21, 0x66, 0x7f, 0x58, + 0x8e, 0x28, 0x76, 0xf8, 0x15, 0xdc, 0xdf, 0xc7, 0xf8, 0x32, 0x11, 0x52, + 0x4c, 0x70, 0x22, 0x36, 0x01, 0x59, 0xcc, 0xba, 0xc4, 0xf8, 0xaf, 0x55, + 0xac, 0xff, 0x9c, 0xd0, 0xcf, 0x22, 0xa6, 0xe0, 0x59, 0x39, 0xec, 0x6e, + 0x76, 0x97, 0xc4, 0xf8, 0xbf, 0x59, 0xad, 0x09, 0x35, 0xca, 0x84, 0x1b, + 0x6a, 0x4a, 0x97, 0x8c, 0x0c, 0x8c, 0x06, 0x53, 0x6b, 0x26, 0x9d, 0x68, + 0xd3, 0xae, 0x12, 0x64, 0xbc, 0x04, 0xfd, 0x5f, 0x8a, 0x05, 0x46, 0x14, + 0x9b, 0xf6, 0x65, 0x49, 0xb7, 0xd3, 0xcf, 0xa7, 0x3e, 0xf9, 0x8a, 0xdc, + 0xb4, 0xb7, 0xca, 0xcd, 0x1e, 0xe2, 0x31, 0xfb, 0xd1, 0xa6, 0x2e, 0x19, + 0x44, 0x5f, 0x12, 0x7d, 0x4d, 0xca, 0x8f, 0x1a, 0x9f, 0x41, 0x67, 0xdd, + 0xb4, 0xa9, 0xab, 0xee, 0xe2, 0x2f, 0xde, 0xf5, 0x6f, 0xa0, 0x09, 0xb1, + 0x1d, 0xdb, 0xd0, 0xa6, 0x8e, 0xb3, 0xeb, 0xfa, 0x3b, 0xd1, 0xbe, 0x17, + 0x73, 0x34, 0xe8, 0xfb, 0x59, 0xce, 0x76, 0x53, 0xe7, 0xac, 0x19, 0xb3, + 0xae, 0xae, 0xfd, 0xfb, 0x36, 0x83, 0x4f, 0xf8, 0x94, 0xf4, 0xce, 0xa5, + 0xe4, 0xe1, 0x8e, 0xda, 0xf6, 0xbf, 0xea, 0xda, 0xad, 0xb2, 0xa6, 0x8d, + 0x64, 0x38, 0xd6, 0x5e, 0xdb, 0xef, 0xf3, 0x93, 0xdf, 0xee, 0xc0, 0xfb, + 0x42, 0x66, 0xac, 0xa4, 0xc6, 0x52, 0x37, 0xa3, 0x5c, 0xeb, 0xc3, 0xba, + 0x67, 0x78, 0xcd, 0x67, 0xf8, 0x2c, 0xf3, 0x7a, 0xb7, 0xd9, 0x8f, 0x67, + 0x98, 0x13, 0x60, 0x5e, 0x83, 0x3c, 0xbb, 0x5a, 0x9c, 0xc5, 0x31, 0x9f, + 0xcd, 0x37, 0x64, 0x2a, 0xbc, 0xe7, 0xeb, 0x95, 0x58, 0x05, 0xab, 0xb6, + 0xab, 0xe0, 0xe7, 0x84, 0x49, 0x3b, 0xad, 0x49, 0xc5, 0x6e, 0x80, 0xce, + 0x87, 0x40, 0xe7, 0x07, 0x83, 0x8c, 0x0b, 0x9b, 0x3d, 0x5a, 0x3b, 0x32, + 0x52, 0xfa, 0x0d, 0x64, 0x9c, 0x3c, 0x0a, 0x9f, 0xa2, 0x64, 0x79, 0xf8, + 0x8c, 0x01, 0xd8, 0x34, 0x57, 0x82, 0x9a, 0x77, 0x40, 0x7c, 0x3f, 0x7f, + 0x5d, 0x46, 0xa6, 0x98, 0x13, 0x20, 0x3f, 0x33, 0xae, 0x4f, 0xe1, 0xde, + 0x2d, 0x8c, 0x75, 0x21, 0xc3, 0x63, 0xe0, 0xd7, 0x90, 0x38, 0xd3, 0xdb, + 0x24, 0x37, 0x3e, 0xa6, 0x3e, 0x40, 0x37, 0x6c, 0xd4, 0x29, 0x77, 0x54, + 0x26, 0xaf, 0x6c, 0x82, 0xac, 0x32, 0xee, 0xd7, 0x9c, 0x46, 0x39, 0xac, + 0xbe, 0x39, 0x7d, 0x0e, 0xe6, 0xe1, 0x4c, 0x8d, 0xd9, 0xc8, 0xed, 0xa1, + 0x98, 0xb4, 0x8e, 0xca, 0xcc, 0xac, 0xad, 0x78, 0x97, 0x94, 0xdc, 0x2e, + 0x93, 0x76, 0xd9, 0x7d, 0x71, 0xe8, 0x2a, 0xfa, 0xf2, 0x3f, 0x88, 0x98, + 0xb3, 0xdc, 0xbd, 0x81, 0x31, 0x71, 0x72, 0xba, 0x7a, 0x0e, 0xc5, 0xc8, + 0xe0, 0xde, 0x2f, 0xdb, 0x8c, 0xcc, 0x30, 0x3e, 0xfe, 0xa0, 0x9c, 0x8a, + 0x72, 0x4d, 0x8e, 0x65, 0xed, 0x96, 0x3c, 0xc2, 0xbd, 0xfd, 0xc7, 0xe3, + 0xe5, 0x97, 0x31, 0x5f, 0x5c, 0xba, 0x5f, 0x1d, 0xd3, 0xb8, 0xfe, 0x54, + 0x4d, 0x0c, 0x6b, 0xf2, 0x05, 0x26, 0x8e, 0xbd, 0x2e, 0x13, 0x8b, 0xa4, + 0x0f, 0x6d, 0x7c, 0x40, 0x7e, 0xe1, 0xf4, 0xda, 0x4f, 0x68, 0xad, 0x31, + 0x91, 0x62, 0x7d, 0xa6, 0xd9, 0x49, 0xda, 0xf3, 0x12, 0x1a, 0xfc, 0x1a, + 0xae, 0x19, 0xd7, 0xe6, 0xdd, 0x5e, 0xf7, 0x09, 0xf1, 0x71, 0x20, 0x9b, + 0x53, 0x8d, 0x81, 0x4f, 0xca, 0xd7, 0xf7, 0x71, 0x8c, 0xc1, 0x81, 0x48, + 0x80, 0xb4, 0x7a, 0xef, 0x2e, 0xe2, 0x67, 0x6a, 0xf3, 0x7f, 0x0f, 0x1c, + 0xdb, 0x3b, 0x90, 0x38, 0xc3, 0x18, 0x36, 0xec, 0x3c, 0xba, 0xc1, 0xbc, + 0x6b, 0x2e, 0xb7, 0x4e, 0xb4, 0x7e, 0x76, 0xfc, 0x1f, 0x0e, 0xf1, 0x10, + 0x89, 0x58, 0xa3, 0xc5, 0x3c, 0x38, 0x75, 0x1c, 0x6b, 0x2a, 0xcc, 0xb9, + 0x11, 0xcb, 0xdf, 0x24, 0x97, 0xfb, 0x2c, 0x79, 0x20, 0x94, 0x8a, 0x5b, + 0xb2, 0x25, 0x7e, 0x4e, 0xb0, 0x26, 0xeb, 0x2b, 0x8b, 0x89, 0x1c, 0xc7, + 0x87, 0xa6, 0x39, 0x5f, 0x5c, 0xe3, 0x95, 0xe4, 0x96, 0x72, 0xf9, 0x29, + 0x57, 0x02, 0xc9, 0x7b, 0x3e, 0x2c, 0xb3, 0x16, 0x6e, 0xbd, 0xfa, 0x79, + 0x38, 0x05, 0xea, 0x0a, 0x7b, 0xc2, 0x60, 0x0e, 0x27, 0x8f, 0x77, 0x2f, + 0xb2, 0xfd, 0xe4, 0x43, 0xa6, 0x7d, 0x06, 0xed, 0x06, 0x0f, 0xeb, 0x34, + 0x75, 0xbc, 0xbb, 0x78, 0x6c, 0x83, 0x89, 0xbf, 0x97, 0x15, 0xff, 0xf5, + 0x56, 0x4d, 0x4c, 0x93, 0x0a, 0x8c, 0x17, 0xc6, 0x02, 0x63, 0x05, 0xab, + 0xaf, 0x09, 0xb4, 0x5a, 0x70, 0x99, 0xab, 0xf1, 0x73, 0x56, 0xcc, 0xf7, + 0x8b, 0x3c, 0xa9, 0x18, 0x29, 0xd6, 0x14, 0x2d, 0xf5, 0x85, 0x0e, 0x2d, + 0x30, 0xc7, 0x1f, 0x51, 0x7d, 0x70, 0x78, 0xb1, 0x55, 0xf2, 0xf6, 0x7a, + 0xc9, 0xab, 0x8c, 0x47, 0x55, 0x07, 0x58, 0xce, 0x3d, 0xe8, 0xe3, 0xbe, + 0x1f, 0x57, 0x5c, 0xc4, 0xeb, 0x85, 0x4e, 0xb4, 0x99, 0x6b, 0xde, 0x51, + 0xd7, 0x5f, 0x5d, 0x97, 0x4d, 0xd8, 0x96, 0x55, 0x5f, 0x93, 0x65, 0x5f, + 0x7d, 0x2d, 0xf6, 0xb4, 0x5c, 0x27, 0xdf, 0x94, 0xfc, 0x9c, 0xbb, 0xeb, + 0xe5, 0xdc, 0x1f, 0xc3, 0x9c, 0x9c, 0x5b, 0x32, 0xa1, 0xa1, 0xa6, 0xbe, + 0x53, 0x53, 0xc1, 0x5b, 0x2b, 0xf9, 0x53, 0xb4, 0x17, 0x2b, 0xb5, 0x72, + 0xdc, 0x7b, 0x06, 0xbe, 0x48, 0x1e, 0x7e, 0x45, 0xce, 0xfb, 0xfe, 0x80, + 0xf7, 0x2b, 0xcf, 0x7f, 0xc1, 0x9e, 0x9a, 0xb5, 0xce, 0x6e, 0xd5, 0xd4, + 0xd9, 0xbf, 0x8d, 0x67, 0x59, 0x63, 0xcf, 0x95, 0x1b, 0xc0, 0xbb, 0x0d, + 0xc4, 0x89, 0x54, 0xc6, 0x53, 0xc7, 0xab, 0x2e, 0xd7, 0xb9, 0x76, 0x79, + 0x73, 0x05, 0xa1, 0xe7, 0x0f, 0x4e, 0xf9, 0x63, 0x4e, 0x4a, 0x63, 0x7f, + 0x22, 0x16, 0xb4, 0x38, 0xc6, 0xe8, 0xfb, 0xb4, 0x7b, 0x12, 0x7a, 0x9c, + 0x3a, 0x9f, 0xef, 0xed, 0xc0, 0xd7, 0xa3, 0x2e, 0xa0, 0x3e, 0x57, 0x1b, + 0x10, 0xcf, 0x43, 0xd7, 0x8f, 0x94, 0x34, 0x97, 0x1f, 0xfb, 0x6a, 0x30, + 0x31, 0x93, 0x55, 0xdd, 0x00, 0x7f, 0xaf, 0xf4, 0x26, 0xf3, 0x41, 0x67, + 0x24, 0x50, 0x5d, 0xa7, 0x61, 0x6c, 0xc6, 0x9a, 0x46, 0x0b, 0x74, 0x83, + 0xc8, 0x55, 0xf0, 0xc6, 0x6b, 0x0b, 0xe4, 0xd7, 0x60, 0xbb, 0x89, 0xaf, + 0x96, 0x76, 0x58, 0xd2, 0xae, 0xb5, 0xcf, 0xbc, 0x13, 0xa1, 0x7f, 0x32, + 0x9c, 0xec, 0x87, 0x9f, 0xad, 0xd8, 0x03, 0xe6, 0x2b, 0x0f, 0x22, 0x1e, + 0xab, 0xce, 0xb1, 0x40, 0xbe, 0xc6, 0xd9, 0x9f, 0x85, 0x5f, 0xb9, 0x52, + 0xf7, 0xc8, 0x17, 0x27, 0x35, 0xb7, 0x39, 0xb7, 0xd0, 0xa2, 0x3a, 0x76, + 0xae, 0x38, 0x86, 0x73, 0x91, 0xad, 0xd6, 0x50, 0xde, 0xeb, 0x0f, 0x4b, + 0xb1, 0xc8, 0xb6, 0x74, 0x35, 0xe8, 0xb9, 0xfb, 0xb5, 0x1d, 0x5b, 0xe6, + 0xe1, 0x2b, 0x16, 0x17, 0x1d, 0xfc, 0xf7, 0xe0, 0xbf, 0x0f, 0xff, 0xbb, + 0x25, 0x3d, 0x4d, 0xff, 0x95, 0xb5, 0x9c, 0x96, 0xba, 0xf5, 0xe9, 0x23, + 0x75, 0x29, 0x0e, 0x2c, 0xef, 0xc5, 0x39, 0xf9, 0x62, 0xbd, 0x9c, 0x30, + 0x4f, 0xea, 0xeb, 0x08, 0xe6, 0x4b, 0xfd, 0x5a, 0x5f, 0x75, 0x0d, 0xcb, + 0xf2, 0xea, 0x5e, 0xe4, 0xe9, 0x66, 0x39, 0x5c, 0xf4, 0x6b, 0x57, 0x31, + 0x39, 0x52, 0xa9, 0x5d, 0x49, 0x26, 0x38, 0xf4, 0xc9, 0x23, 0xd9, 0x29, + 0xc5, 0x13, 0x58, 0xd6, 0xd0, 0xf5, 0x47, 0x26, 0x16, 0xdf, 0x7e, 0x64, + 0x05, 0x13, 0x8e, 0x7b, 0x8b, 0xab, 0x61, 0x86, 0x88, 0xa5, 0xe3, 0xb7, + 0x72, 0xea, 0xbb, 0x61, 0xdf, 0x7e, 0xcc, 0x43, 0x9c, 0x1d, 0xf4, 0x4c, + 0xf3, 0x0a, 0x76, 0xd7, 0xc4, 0xa3, 0xc4, 0x91, 0xf2, 0xb9, 0x6a, 0xec, + 0x47, 0x08, 0xe7, 0x2f, 0x01, 0xcb, 0xc9, 0x61, 0x1f, 0x3f, 0xed, 0x34, + 0x7e, 0x20, 0x71, 0xa6, 0x89, 0x2a, 0xec, 0x91, 0x8f, 0x35, 0x7d, 0x09, + 0x73, 0x65, 0xe4, 0x77, 0xa5, 0x47, 0xe5, 0x57, 0xa5, 0x31, 0xc8, 0xf7, + 0x04, 0xe6, 0x3c, 0x20, 0x6f, 0x96, 0xf6, 0xc9, 0xb5, 0xd2, 0xb8, 0xbc, + 0x51, 0xda, 0x8d, 0x98, 0x6a, 0x94, 0x58, 0x4f, 0x0f, 0x2b, 0x3d, 0x2c, + 0x07, 0xcf, 0x2b, 0x06, 0xf0, 0x16, 0xfd, 0x9e, 0xe3, 0xea, 0x67, 0x13, + 0x5f, 0x9f, 0xf8, 0x35, 0xe3, 0x79, 0x62, 0x33, 0x8b, 0x25, 0x1f, 0xc3, + 0x71, 0xb4, 0x0b, 0x6b, 0xdb, 0xfc, 0x36, 0x65, 0xe4, 0x7c, 0x24, 0x30, + 0x7a, 0x3e, 0x14, 0x78, 0x50, 0xbf, 0x73, 0x61, 0xbd, 0xb3, 0x2c, 0x93, + 0xae, 0x43, 0xde, 0x1c, 0x1c, 0x81, 0x2c, 0x8c, 0x42, 0xd5, 0x3f, 0xe4, + 0xac, 0x17, 0x90, 0x34, 0xf5, 0x11, 0xfc, 0xcc, 0xe4, 0x8b, 0xae, 0x64, + 0x0b, 0xf3, 0x01, 0x83, 0x47, 0xb3, 0xd1, 0xee, 0x43, 0xfb, 0xe7, 0x5e, + 0x7b, 0xa7, 0x64, 0x67, 0x25, 0xf5, 0xbe, 0xfa, 0xc3, 0x2f, 0x7b, 0x7d, + 0x83, 0xe8, 0x03, 0x67, 0x5e, 0x64, 0xdf, 0x45, 0xaf, 0x8f, 0x67, 0xc2, + 0x5a, 0x7d, 0x5c, 0xf9, 0x2a, 0x6b, 0x8f, 0x8b, 0x7e, 0xd7, 0xa0, 0xb5, + 0xf8, 0x0f, 0x3a, 0x8d, 0x6e, 0x23, 0x26, 0xf0, 0x9f, 0x9d, 0x8c, 0xc1, + 0x8a, 0x90, 0xaf, 0xbb, 0xa0, 0x13, 0xff, 0xba, 0x75, 0xa5, 0x6d, 0x0d, + 0x7d, 0x5c, 0x85, 0xd1, 0xfe, 0x58, 0xba, 0x17, 0xff, 0xed, 0xe1, 0x79, + 0x9f, 0xc0, 0xbb, 0xe1, 0xac, 0x0a, 0xc4, 0x8d, 0xc7, 0x21, 0xdb, 0x2d, + 0xb2, 0xfe, 0x2c, 0xe9, 0xd5, 0x0b, 0x5d, 0x9d, 0x82, 0xdc, 0xba, 0xb2, + 0x50, 0x0a, 0x05, 0x46, 0x0a, 0x29, 0x31, 0x78, 0x6a, 0x4b, 0x32, 0xd1, + 0x94, 0x9c, 0x1e, 0x48, 0xf4, 0x30, 0x0f, 0x99, 0xed, 0x77, 0xe5, 0x52, + 0x89, 0xf6, 0x38, 0x27, 0x97, 0x07, 0x12, 0x6e, 0x51, 0x88, 0x8b, 0x71, + 0xe5, 0x32, 0x64, 0xf3, 0x9d, 0xf3, 0xbb, 0xe5, 0x48, 0x41, 0xfd, 0xe0, + 0xde, 0xb0, 0xbc, 0x20, 0x97, 0x06, 0x5e, 0xb8, 0x75, 0xc9, 0x3d, 0x84, + 0x33, 0x25, 0x1f, 0x1e, 0xee, 0x32, 0xfb, 0x56, 0x1c, 0x92, 0x30, 0x1f, + 0xa2, 0x35, 0x35, 0xa7, 0x51, 0xd2, 0xfb, 0x23, 0x5e, 0x5c, 0x0e, 0x9f, + 0x3b, 0x30, 0x60, 0xea, 0x29, 0x01, 0x7f, 0x9f, 0x61, 0xf8, 0x31, 0x7c, + 0xce, 0xa7, 0x8d, 0x3f, 0x4f, 0x67, 0x20, 0x3d, 0xdb, 0x2a, 0xa1, 0x8b, + 0xf7, 0x81, 0xae, 0x21, 0x39, 0xd4, 0x5f, 0x2e, 0x7f, 0xd3, 0x0d, 0xc5, + 0x27, 0x10, 0xa3, 0x60, 0xff, 0xb2, 0xee, 0xc5, 0x36, 0xd0, 0xa4, 0x49, + 0xa2, 0x2f, 0xfa, 0xeb, 0x35, 0x7a, 0x58, 0x86, 0x8b, 0xeb, 0x8c, 0x2d, + 0xf3, 0xb1, 0x0d, 0xfe, 0x7c, 0x06, 0x53, 0xd6, 0x6d, 0xf5, 0x07, 0xbc, + 0xef, 0x24, 0xbc, 0xf6, 0x3d, 0x81, 0x07, 0x42, 0xed, 0x12, 0x72, 0x9e, + 0xdf, 0x48, 0x6c, 0xe4, 0x52, 0xc1, 0xef, 0x87, 0x9f, 0x18, 0xf2, 0xfd, + 0x61, 0xd9, 0xbe, 0x72, 0xd6, 0xb2, 0xbd, 0x7b, 0xf1, 0x5b, 0xde, 0x9c, + 0x29, 0x6f, 0x2c, 0x62, 0x8e, 0xd8, 0x5a, 0xb5, 0x4f, 0x66, 0xec, 0xa7, + 0xf2, 0x74, 0x7f, 0xe2, 0x15, 0xc5, 0xc9, 0x56, 0x9e, 0xe1, 0x7d, 0xc4, + 0x90, 0x25, 0x7d, 0x26, 0xb6, 0x07, 0xf4, 0xcd, 0xc4, 0xee, 0xb6, 0xe7, + 0xad, 0x60, 0xc0, 0xf8, 0x23, 0x0d, 0xf2, 0xbd, 0x28, 0xec, 0x36, 0xbf, + 0x61, 0x61, 0xfe, 0xcb, 0xbd, 0xed, 0xf9, 0x29, 0xec, 0x4b, 0x9c, 0x49, + 0x5a, 0x13, 0xd8, 0x1f, 0xcf, 0x80, 0x18, 0x50, 0x0b, 0x74, 0xea, 0xc4, + 0xfb, 0x21, 0x7e, 0xea, 0xf7, 0xdf, 0x7f, 0x1d, 0x74, 0x18, 0xf7, 0x6f, + 0x70, 0x61, 0x62, 0x31, 0x17, 0x32, 0xec, 0x61, 0x60, 0xab, 0xe5, 0xd6, + 0xc7, 0xc6, 0xfa, 0x78, 0x3a, 0x62, 0x94, 0x62, 0xf0, 0x03, 0x29, 0x13, + 0xe4, 0xcd, 0x0e, 0xf4, 0xaf, 0xf9, 0x24, 0xa5, 0xaf, 0xee, 0xf7, 0x7d, + 0x58, 0xc1, 0x76, 0x4f, 0x14, 0xf6, 0x19, 0x6c, 0x9e, 0xb5, 0x2c, 0xa9, + 0xae, 0xa4, 0x3d, 0x89, 0xfd, 0xa6, 0x43, 0x89, 0x62, 0x4e, 0x62, 0x32, + 0x0f, 0x7d, 0xf1, 0x1a, 0x64, 0xff, 0x5a, 0x29, 0x1e, 0x48, 0x63, 0x4f, + 0x87, 0x0b, 0x43, 0x32, 0x31, 0xab, 0xdf, 0x7e, 0x41, 0xef, 0x0f, 0xc9, + 0x5c, 0x21, 0xd1, 0x33, 0x0f, 0xfe, 0x9b, 0x2f, 0x10, 0x5f, 0xd4, 0x1b, + 0x1f, 0xc5, 0x8c, 0x4b, 0x85, 0xcd, 0xb0, 0x0f, 0x92, 0xba, 0x04, 0xff, + 0xe7, 0x52, 0xa9, 0x07, 0x7c, 0x86, 0xfb, 0x25, 0x07, 0xbf, 0xd0, 0x99, + 0xa5, 0x01, 0xc8, 0x39, 0xf7, 0x62, 0xcb, 0xc2, 0x56, 0x9c, 0x1d, 0x71, + 0x44, 0x8a, 0x1f, 0xff, 0x2f, 0xce, 0xd7, 0x7f, 0xef, 0x1d, 0x6a, 0xa7, + 0xe7, 0x75, 0x5f, 0xb0, 0xcb, 0x88, 0x01, 0xb2, 0xfd, 0xc6, 0x6e, 0xa7, + 0x23, 0x6d, 0x92, 0xbe, 0x9b, 0x76, 0xbc, 0x5d, 0x63, 0x44, 0xe5, 0xc5, + 0x08, 0xef, 0xbf, 0xb3, 0xd1, 0xd0, 0x2f, 0x5c, 0xd7, 0xbe, 0x8e, 0xdf, + 0x56, 0xe9, 0x70, 0xf8, 0x6b, 0xe3, 0xf7, 0xed, 0x8d, 0xac, 0xef, 0x76, + 0x38, 0x49, 0xac, 0xf5, 0x5b, 0x2f, 0x5f, 0x80, 0xeb, 0x79, 0x3e, 0xb3, + 0xc1, 0x5b, 0x97, 0xf3, 0xb6, 0x62, 0x9e, 0x16, 0x6f, 0xad, 0x56, 0xcd, + 0x4f, 0x9a, 0xb5, 0x10, 0xe3, 0x16, 0xfe, 0xb2, 0x51, 0xbf, 0x35, 0x86, + 0xbd, 0xa8, 0x6d, 0xff, 0x79, 0x23, 0x71, 0x73, 0x1d, 0x4e, 0xab, 0x62, + 0x3c, 0x6f, 0xb6, 0xb7, 0xe3, 0x9a, 0x6b, 0x72, 0x8c, 0xc9, 0x87, 0xcf, + 0x95, 0x38, 0x3f, 0xdb, 0x29, 0x39, 0xa1, 0xf9, 0x0c, 0x83, 0xe5, 0x9b, + 0x2b, 0xdc, 0x2f, 0x13, 0xe7, 0x15, 0x5f, 0x37, 0x93, 0xb7, 0xf8, 0xdd, + 0x0b, 0xbf, 0x97, 0xa3, 0x2f, 0x31, 0x26, 0x07, 0x71, 0x7e, 0x97, 0xe1, + 0x53, 0x2d, 0x99, 0xef, 0x62, 0xf1, 0x77, 0x00, 0xe7, 0x12, 0x82, 0x8c, + 0x51, 0x46, 0x29, 0x53, 0x38, 0xbf, 0x71, 0x5b, 0xde, 0x1d, 0xa0, 0x3c, + 0x0f, 0xc8, 0x95, 0x8a, 0x3c, 0xe7, 0x20, 0xcf, 0x94, 0xe5, 0x1c, 0x64, + 0xda, 0xf0, 0xf5, 0x7e, 0x7e, 0x67, 0x1d, 0x83, 0xbd, 0x52, 0x1f, 0xe2, + 0x25, 0xf0, 0xb5, 0xed, 0x7d, 0x2b, 0x15, 0xd0, 0x1c, 0x4e, 0x76, 0xb6, + 0xc1, 0xfb, 0x0e, 0x00, 0xd7, 0x57, 0x9e, 0x93, 0xf4, 0x6c, 0x33, 0xbf, + 0xe7, 0xea, 0xe2, 0x99, 0x65, 0xaf, 0xf0, 0xdf, 0xe7, 0x45, 0xe2, 0x4d, + 0xe9, 0xcf, 0xf2, 0x9a, 0x71, 0xde, 0x26, 0x8c, 0x19, 0x04, 0x9d, 0x9b, + 0x31, 0x3f, 0xf7, 0xb8, 0xda, 0x38, 0xde, 0x0f, 0x55, 0xe1, 0x53, 0x7d, + 0x7a, 0xaf, 0xd5, 0x35, 0xb3, 0xfd, 0xcd, 0xde, 0xfb, 0xf1, 0x1c, 0x94, + 0xef, 0xc1, 0xb7, 0xf4, 0x89, 0xc9, 0x2f, 0x29, 0x3d, 0x87, 0xb9, 0x02, + 0xf9, 0x37, 0xa4, 0x39, 0x8c, 0x2c, 0x6c, 0xcb, 0x5e, 0x1d, 0x1f, 0x5b, + 0x91, 0xef, 0xae, 0x80, 0xc6, 0xdd, 0xd9, 0xc2, 0x1a, 0xe9, 0x56, 0x1d, + 0xd4, 0xe5, 0xf1, 0x36, 0xec, 0x85, 0x62, 0xb9, 0x0f, 0xc8, 0xf1, 0xd2, + 0x20, 0xe8, 0x10, 0x93, 0xa7, 0xe0, 0x37, 0x3f, 0x53, 0xba, 0x43, 0x96, + 0x23, 0xd8, 0x57, 0x45, 0xc6, 0x86, 0xe5, 0xfb, 0xf3, 0x09, 0xef, 0x3a, + 0xe1, 0x2e, 0x5b, 0x3b, 0xb0, 0x07, 0xca, 0x13, 0xe5, 0x8a, 0xe3, 0x82, + 0x88, 0x45, 0x38, 0xef, 0xd3, 0x46, 0xb7, 0x61, 0xde, 0x62, 0x84, 0xf2, + 0xcb, 0xbd, 0x85, 0x3c, 0x99, 0x65, 0x5c, 0xc5, 0x77, 0x36, 0x36, 0x29, + 0x53, 0x73, 0x16, 0x09, 0xc5, 0x81, 0xae, 0x9c, 0x81, 0x3f, 0x8f, 0x2f, + 0x97, 0xfe, 0x77, 0x14, 0xd4, 0xa3, 0xb0, 0x95, 0x05, 0xd8, 0xca, 0x02, + 0x6c, 0x24, 0x64, 0xe1, 0x5a, 0x01, 0x36, 0xb2, 0x00, 0x1b, 0x09, 0x7d, + 0xf6, 0x3a, 0x62, 0xbb, 0xd7, 0xc0, 0x43, 0xc6, 0xd7, 0x3e, 0x4a, 0x5f, + 0x1b, 0x7f, 0xff, 0x03, 0x4c, 0x03, 0x3a, 0xe1, 0xd4, 0x71, 0x00, 0x00, + 0x00 }; static const u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; static const u32 bnx2_RXP_b06FwRodata[(0x24/4) + 1] = { - 0x08004580, 0x08004580, 0x080044f8, 0x08004530, 0x08004564, 0x08004588, - 0x08004588, 0x08004588, 0x08004468, 0x00000000 }; + 0x08004590, 0x08004590, 0x08004508, 0x08004540, 0x08004574, 0x08004598, + 0x08004598, 0x08004598, 0x08004478, 0x00000000 }; static struct fw_info bnx2_rxp_fw_06 = { - /* Firmware version: 4.0.5 */ + /* Firmware version: 4.1.1 */ .ver_major = 0x4, - .ver_minor = 0x0, - .ver_fix = 0x5, + .ver_minor = 0x1, + .ver_fix = 0x1, .start_addr = 0x080031d0, .text_addr = 0x08000000, - .text_len = 0x71c0, + .text_len = 0x71d0, .text_index = 0x0, .gz_text = bnx2_RXP_b06FwText, .gz_text_len = sizeof(bnx2_RXP_b06FwText), @@ -2931,22 +2932,22 @@ static struct fw_info bnx2_rxp_fw_06 = { .data_index = 0x0, .data = bnx2_RXP_b06FwData, - .sbss_addr = 0x08007200, + .sbss_addr = 0x08007220, .sbss_len = 0x58, .sbss_index = 0x0, - .bss_addr = 0x08007258, + .bss_addr = 0x08007278, .bss_len = 0x44c, .bss_index = 0x0, - .rodata_addr = 0x080071c0, + .rodata_addr = 0x080071d0, .rodata_len = 0x24, .rodata_index = 0x0, .rodata = bnx2_RXP_b06FwRodata, }; static u8 bnx2_rv2p_proc1[] = { - /* Date: 12/07/2007 14:57 */ + /* Date: 12/07/2007 15:02 */ 0xd5, 0x56, 0x41, 0x6b, 0x13, 0x51, 0x10, 0x9e, 0xdd, 0x6c, 0xbb, 0xdb, 0x64, 0xb3, 0x59, 0xaa, 0xd6, 0x50, 0x53, 0x93, 0x06, 0x2f, 0xad, 0x29, 0x6d, 0xaa, 0x82, 0x42, 0xa1, 0x92, 0x4b, 0xc1, 0xf6, 0x20, 0xf5, 0x22, @@ -3032,7 +3033,7 @@ static u8 bnx2_rv2p_proc1[] = { 0xa7, 0xd8, 0x0d, 0x00, 0x00, 0x00 }; static u8 bnx2_rv2p_proc2[] = { - /* Date: 12/07/2007 14:57 */ + /* Date: 12/07/2007 15:02 */ 0xed, 0x59, 0x5d, 0x6c, 0x54, 0xc7, 0x15, 0x9e, 0xbd, 0xbb, 0x7b, 0xf7, 0x7a, 0x7d, 0xf7, 0xae, 0x71, 0xa8, 0xff, 0xf9, 0xb3, 0x09, 0xd8, 0xa9, 0x21, 0xce, 0x9a, 0x98, 0x02, 0x55, 0x63, 0x39, 0x95, 0x81, 0xa6, 0x55, diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h index 13b222e..e6ffa27 100644 --- a/drivers/net/bnx2_fw2.h +++ b/drivers/net/bnx2_fw2.h @@ -3173,250 +3173,250 @@ static struct fw_info bnx2_rxp_fw_09 = { }; static u8 bnx2_xi_rv2p_proc1[] = { - /* Date: 12/07/2007 16:21 */ - 0xc5, 0x56, 0xcd, 0x6b, 0x13, 0x51, 0x10, 0x9f, 0xdd, 0xa4, 0xd9, 0x34, - 0xd9, 0x64, 0x97, 0xaa, 0x25, 0xb4, 0x91, 0xa6, 0x55, 0x0f, 0x69, 0x23, - 0xb6, 0xea, 0xc1, 0x43, 0xc1, 0xda, 0x8b, 0xa0, 0x9e, 0x7a, 0x10, 0xf1, - 0xdb, 0x20, 0x05, 0xf1, 0x8f, 0x70, 0x51, 0xab, 0x20, 0x78, 0x28, 0x6a, - 0xb0, 0x0a, 0xea, 0x49, 0x45, 0x3c, 0x34, 0x07, 0x41, 0x50, 0x14, 0x14, - 0x3c, 0xe9, 0x4d, 0xf0, 0xe3, 0x50, 0x15, 0x3f, 0x0e, 0x7a, 0x13, 0x8f, - 0xda, 0xf8, 0xde, 0xcc, 0xef, 0xd9, 0xdd, 0x4d, 0xd3, 0x14, 0x0f, 0xba, - 0xd0, 0xfc, 0xfa, 0xde, 0x9b, 0x37, 0x6f, 0xe6, 0x37, 0xf3, 0x66, 0x9e, - 0x4f, 0x44, 0x36, 0x05, 0xf5, 0x3e, 0x85, 0x94, 0xb5, 0x12, 0x69, 0x05, - 0x16, 0xd1, 0x5d, 0x97, 0x31, 0xd8, 0x40, 0xf2, 0x0d, 0x09, 0x04, 0x43, - 0xbe, 0xfa, 0xfd, 0x4e, 0x5b, 0x4b, 0x1a, 0x13, 0xb4, 0xb5, 0x5f, 0xe3, - 0x36, 0x7a, 0x5c, 0x2a, 0x28, 0xfc, 0xd5, 0xa0, 0x40, 0x8f, 0xd7, 0xcc, - 0xde, 0xaf, 0x67, 0x59, 0xef, 0x3b, 0xec, 0x7f, 0x9d, 0x10, 0xdc, 0x52, - 0x49, 0x8b, 0x1e, 0x20, 0xad, 0xf7, 0x19, 0x5e, 0x4e, 0xeb, 0x71, 0xd1, - 0x0a, 0xd6, 0xe3, 0x7c, 0x5b, 0xe6, 0xe7, 0xa6, 0x3d, 0x3d, 0x4f, 0xef, - 0xc7, 0xf5, 0xd8, 0xcb, 0x9c, 0xae, 0xa7, 0x59, 0xaf, 0xac, 0x77, 0x65, - 0x4e, 0xf3, 0x3e, 0xd7, 0x12, 0x7d, 0xea, 0x8f, 0xf7, 0x6f, 0x56, 0x7a, - 0x60, 0x37, 0x89, 0x9e, 0x43, 0x25, 0x3d, 0x3f, 0x06, 0xb9, 0x51, 0xc8, - 0x15, 0x9b, 0xe4, 0xe6, 0xa6, 0x35, 0x3a, 0x54, 0xad, 0x68, 0x7f, 0xfa, - 0x95, 0xa1, 0xae, 0xf0, 0xd3, 0x27, 0xfe, 0x4e, 0xc2, 0xec, 0x77, 0x83, - 0xfa, 0x1f, 0x65, 0xdb, 0xa0, 0x96, 0x9b, 0x53, 0x7e, 0x1b, 0x7f, 0x8d, - 0xbc, 0xc8, 0x39, 0xac, 0xe7, 0xad, 0x5a, 0x37, 0x7e, 0x85, 0xfd, 0xc9, - 0x86, 0xfc, 0x89, 0xf9, 0xd9, 0xe4, 0x57, 0x98, 0xa7, 0xf4, 0x22, 0x76, - 0xeb, 0x73, 0x94, 0x0d, 0x7c, 0x4e, 0x0a, 0xfc, 0xa6, 0x62, 0xfb, 0x52, - 0x2d, 0xf6, 0x7d, 0x6a, 0x2c, 0xf8, 0x69, 0xd6, 0xf5, 0xfc, 0xd3, 0x85, - 0xf9, 0x72, 0x74, 0x5d, 0xfc, 0xef, 0x80, 0xff, 0x8f, 0xe0, 0xdf, 0x0e, - 0x5a, 0x6b, 0x17, 0x78, 0x3d, 0xc9, 0xfb, 0x7b, 0x95, 0x3d, 0x1a, 0x57, - 0x03, 0xfb, 0x81, 0x07, 0x81, 0x07, 0x80, 0xab, 0x80, 0x2b, 0x81, 0x2b, - 0x80, 0x5d, 0xc0, 0xcb, 0x40, 0x1f, 0xe8, 0x01, 0xf3, 0xc0, 0x8b, 0x40, - 0x17, 0x98, 0x05, 0xd6, 0x80, 0x57, 0x81, 0x69, 0xe0, 0x31, 0xe0, 0x23, - 0xe0, 0x13, 0xe0, 0x37, 0xe0, 0x39, 0xa3, 0xcf, 0xc2, 0xb9, 0x40, 0x42, - 0x3e, 0x58, 0x31, 0x9e, 0xae, 0x21, 0xef, 0x35, 0xcf, 0x58, 0x2f, 0x1b, - 0x39, 0xc4, 0x97, 0x79, 0x9a, 0x81, 0x5c, 0xd7, 0xec, 0x8d, 0xd8, 0xfd, - 0x28, 0xb5, 0xbd, 0x17, 0xf1, 0xb8, 0x79, 0xec, 0xcf, 0xe1, 0xed, 0x1e, - 0x9f, 0x93, 0x4f, 0xc9, 0xbc, 0x31, 0x6b, 0x8f, 0x27, 0x78, 0x34, 0x23, - 0xf8, 0x39, 0xd3, 0xa9, 0x7e, 0x1b, 0x8d, 0xc9, 0xac, 0x8c, 0x8f, 0xe4, - 0x0c, 0xcf, 0x46, 0x8f, 0xb1, 0xa7, 0x9d, 0x1d, 0xad, 0xce, 0x33, 0x76, - 0xb5, 0x3b, 0x57, 0xb0, 0x6a, 0x47, 0xfd, 0xbf, 0x32, 0x2c, 0x98, 0x1c, - 0x61, 0xa8, 0xb8, 0xa9, 0xa4, 0xc6, 0xcd, 0xee, 0x33, 0x73, 0x8e, 0x46, - 0xb7, 0x50, 0xe3, 0xfb, 0x92, 0xa4, 0x5a, 0x4a, 0xeb, 0xfd, 0xd9, 0x38, - 0x2f, 0x72, 0x3d, 0x47, 0x5e, 0x30, 0x16, 0xae, 0x3c, 0x17, 0xf9, 0x57, - 0x25, 0x97, 0x71, 0xf7, 0x10, 0xc5, 0x3e, 0xb3, 0x2e, 0xf7, 0x31, 0x60, - 0xbb, 0x7f, 0x58, 0x41, 0xdd, 0x9c, 0x83, 0x7d, 0xc7, 0x4d, 0x1c, 0x7d, - 0xb6, 0x73, 0x80, 0x64, 0x3c, 0x51, 0x96, 0xf5, 0x89, 0x32, 0xee, 0xf3, - 0x40, 0x34, 0x1f, 0xe4, 0x5e, 0x24, 0x10, 0xef, 0x7d, 0xb8, 0x17, 0xf1, - 0x7b, 0x9c, 0x9e, 0xbd, 0x31, 0x1d, 0xce, 0x97, 0x02, 0x55, 0x47, 0x60, - 0x4f, 0x53, 0x9c, 0x4d, 0x3d, 0x36, 0xf9, 0xce, 0xd3, 0xb3, 0x41, 0x22, - 0xc2, 0xdf, 0x18, 0x55, 0xc2, 0x71, 0xb2, 0x16, 0xc9, 0x97, 0x76, 0xe7, - 0x44, 0xf4, 0xe5, 0x55, 0x04, 0xa8, 0x39, 0x8f, 0x1d, 0xf8, 0x35, 0x86, - 0x3c, 0xee, 0x6d, 0xca, 0x63, 0x53, 0xe7, 0x25, 0x9f, 0x5b, 0xd5, 0xaf, - 0xbf, 0xaf, 0xcf, 0x22, 0x17, 0x84, 0xf2, 0xd3, 0xd4, 0x43, 0xf0, 0xe4, - 0xb0, 0x5c, 0x71, 0xee, 0x9e, 0xc4, 0x4d, 0xea, 0xb8, 0x4a, 0xc6, 0x20, - 0x6a, 0xa7, 0x63, 0xfc, 0xeb, 0x0b, 0xd7, 0xc1, 0x75, 0x2d, 0xe2, 0x15, - 0xae, 0xbb, 0x71, 0x5e, 0xa2, 0x79, 0x2f, 0xf1, 0xcf, 0x80, 0xa7, 0xde, - 0x36, 0x75, 0xa1, 0x13, 0x72, 0xdd, 0x4b, 0xc8, 0x89, 0xde, 0xf1, 0x72, - 0xb8, 0x8e, 0xf8, 0x0d, 0xd4, 0xc1, 0x3f, 0x71, 0x78, 0xd8, 0x22, 0x0e, - 0xa3, 0xff, 0x37, 0x0e, 0xe8, 0xa7, 0xed, 0xe2, 0x40, 0xb1, 0x38, 0xfc, - 0x98, 0x5f, 0x5e, 0x1c, 0x08, 0x3c, 0x51, 0x8b, 0x38, 0xa4, 0xc0, 0xd7, - 0xd7, 0xf9, 0xa5, 0xe3, 0x90, 0x85, 0xdc, 0xe7, 0x90, 0x1c, 0xdb, 0x3d, - 0x2a, 0xf7, 0xd4, 0xa9, 0x7e, 0x89, 0xf1, 0x3b, 0x52, 0xd1, 0xf5, 0xe7, - 0x04, 0xd5, 0xe1, 0xff, 0x9b, 0x08, 0x0f, 0x39, 0x65, 0x9f, 0xbc, 0x23, - 0x6e, 0xd7, 0x0d, 0x5f, 0xb2, 0x5c, 0xaa, 0x08, 0xde, 0x62, 0x79, 0x3f, - 0xc4, 0x5b, 0x94, 0x5f, 0xe1, 0xcd, 0xa7, 0x9b, 0x7f, 0xea, 0x92, 0xc7, - 0xfa, 0x86, 0x51, 0xd7, 0x0f, 0xa3, 0xbe, 0x7e, 0xc8, 0x48, 0xfd, 0xae, - 0xee, 0xe4, 0x3a, 0x4b, 0xdd, 0xa8, 0xb3, 0xd5, 0x9c, 0x8c, 0x7b, 0x72, - 0xf2, 0x6e, 0x19, 0x76, 0x5c, 0x96, 0xeb, 0xc9, 0x09, 0x76, 0x67, 0xf5, - 0xbe, 0x02, 0x7d, 0xdc, 0xc5, 0xe2, 0x95, 0x19, 0x57, 0xea, 0xed, 0xcc, - 0x73, 0xd4, 0x7f, 0xcf, 0xf0, 0x04, 0x7f, 0x37, 0xe9, 0xf9, 0x6e, 0x55, - 0xef, 0xc2, 0xfc, 0x2a, 0x99, 0x41, 0xb1, 0xef, 0x3a, 0xac, 0x2f, 0x99, - 0x7d, 0x7d, 0x9a, 0xcf, 0x07, 0xf3, 0xa6, 0xbf, 0x0c, 0x6c, 0xd7, 0xf6, - 0x78, 0x94, 0x77, 0x24, 0x9e, 0x82, 0x4a, 0xce, 0x76, 0xf4, 0xb6, 0xe2, - 0x94, 0x2d, 0xe3, 0xa9, 0x93, 0xac, 0x66, 0xd7, 0x94, 0x99, 0x1f, 0xe7, - 0x44, 0x9e, 0xb8, 0xf3, 0x94, 0xe7, 0xf3, 0xf5, 0x84, 0xcc, 0x3b, 0x3b, - 0x0d, 0x1f, 0x1e, 0xfb, 0x57, 0x13, 0x3e, 0xf6, 0x5f, 0x12, 0xdc, 0xab, - 0x9e, 0x22, 0xfa, 0xcb, 0xd4, 0x5c, 0xe9, 0x3f, 0x33, 0x6e, 0x9a, 0x91, - 0x98, 0x0f, 0x7b, 0xa3, 0xf4, 0x91, 0x0e, 0xd4, 0xff, 0xce, 0x50, 0x9c, - 0xe2, 0x7d, 0x79, 0xb9, 0xf1, 0x0a, 0xf7, 0x0b, 0xd3, 0x47, 0xe2, 0x7d, - 0x21, 0x87, 0x3c, 0xbb, 0xdc, 0x26, 0x1f, 0x4d, 0x9d, 0xbd, 0x80, 0x7b, - 0xb0, 0x58, 0x3f, 0xd6, 0x98, 0x6f, 0xf1, 0x8e, 0x28, 0x22, 0xff, 0x4c, - 0xdf, 0x5c, 0xec, 0xbd, 0x20, 0xf2, 0xcb, 0x7b, 0x27, 0xf8, 0x2d, 0xde, - 0x09, 0xff, 0xec, 0x3d, 0x50, 0x58, 0x88, 0xa3, 0xc9, 0xd3, 0x70, 0x1c, - 0xc3, 0xf9, 0x1a, 0xef, 0xd7, 0x4b, 0xf5, 0xe9, 0x3c, 0x78, 0x9e, 0x04, - 0xcf, 0x49, 0xea, 0x48, 0x30, 0x31, 0x6e, 0xf2, 0x14, 0xeb, 0xb5, 0xa7, - 0x6c, 0x16, 0x77, 0x3b, 0xce, 0x58, 0x1a, 0xf3, 0xee, 0x19, 0x91, 0x4b, - 0xca, 0x7c, 0xc1, 0xe0, 0xd9, 0x53, 0xf2, 0x3e, 0xb4, 0xe9, 0x37, 0xf9, - 0x0f, 0x65, 0x7b, 0x50, 0x0d, 0x00, 0x00, 0x00 }; + /* Date: 01/14/2008 15:44 */ + 0xc5, 0x56, 0xcd, 0x6b, 0x13, 0x51, 0x10, 0x9f, 0xdd, 0x7c, 0x6c, 0x9a, + 0x6c, 0xb2, 0xa1, 0x6a, 0x09, 0x35, 0xd2, 0x58, 0x7a, 0x30, 0x6d, 0xc4, + 0x56, 0x3d, 0x78, 0x28, 0x54, 0x7a, 0x11, 0xac, 0xa7, 0x1e, 0x44, 0xc4, + 0xcf, 0x20, 0x05, 0xf5, 0x8f, 0x70, 0x51, 0xab, 0x20, 0x78, 0x28, 0x68, + 0xb4, 0x7e, 0xa0, 0x27, 0x15, 0xf1, 0x90, 0x1c, 0x04, 0x05, 0x45, 0x50, + 0xf0, 0xa4, 0x37, 0x41, 0xbd, 0x54, 0xc5, 0x0f, 0xf0, 0xe2, 0x45, 0x8f, + 0xda, 0xf8, 0xde, 0xcc, 0xef, 0xd9, 0xdd, 0x4d, 0xd2, 0x14, 0x0f, 0x1a, + 0x68, 0x7f, 0xec, 0xdb, 0xdf, 0x9b, 0x37, 0xf3, 0x9b, 0x79, 0x33, 0x9b, + 0x27, 0x22, 0x9b, 0xfc, 0xc6, 0x80, 0x42, 0x72, 0xad, 0x58, 0x4a, 0x81, + 0x45, 0x74, 0xcf, 0x65, 0xf4, 0x37, 0x91, 0xfc, 0x46, 0x04, 0xfc, 0x91, + 0xbc, 0xfa, 0xff, 0x9d, 0x26, 0x4a, 0x1a, 0x63, 0x34, 0xb1, 0x5e, 0xe3, + 0x24, 0x3d, 0x29, 0x15, 0x14, 0xfe, 0x6a, 0x92, 0xaf, 0x9f, 0x87, 0xea, + 0x0f, 0x1a, 0x19, 0xb6, 0xfb, 0x0e, 0xfb, 0xdf, 0xc4, 0x04, 0xb7, 0x55, + 0x52, 0x62, 0x07, 0x48, 0x1b, 0xf3, 0x0c, 0xaf, 0xe6, 0xf4, 0x73, 0xd1, + 0xf2, 0x37, 0xe2, 0x7c, 0x5b, 0xd6, 0x17, 0xe6, 0x3c, 0xbd, 0x4e, 0xef, + 0x27, 0xf5, 0xb3, 0x97, 0x3e, 0xdd, 0x48, 0xb1, 0x5d, 0x79, 0xdf, 0x9b, + 0x3e, 0xcd, 0xfb, 0x5c, 0x4b, 0xec, 0xa9, 0x3f, 0xde, 0xbf, 0x55, 0xd9, + 0x81, 0xdf, 0x24, 0x76, 0x0e, 0x96, 0xf4, 0xfa, 0x76, 0xf0, 0xc6, 0xc1, + 0x2b, 0xb6, 0xf0, 0x16, 0xe6, 0x34, 0x3a, 0x54, 0xad, 0xe8, 0x78, 0x06, + 0x49, 0xe2, 0x49, 0xd0, 0x4c, 0xca, 0x15, 0x9d, 0x06, 0x84, 0xfd, 0x6e, + 0x58, 0xef, 0x57, 0xbe, 0x0d, 0x6b, 0xde, 0x82, 0x8a, 0xdb, 0xc4, 0x1b, + 0xe6, 0x39, 0x15, 0x63, 0x57, 0xf3, 0xde, 0x2a, 0x9e, 0x89, 0x2f, 0x18, + 0x57, 0x26, 0x10, 0x57, 0x24, 0xde, 0x96, 0xf8, 0x82, 0x7a, 0xa5, 0xda, + 0xf8, 0xaf, 0xcf, 0x51, 0xbe, 0xf0, 0x39, 0x49, 0xe8, 0x9c, 0x8c, 0xec, + 0x4b, 0x76, 0x88, 0xfb, 0x93, 0x35, 0xb3, 0x21, 0xec, 0x3f, 0x91, 0xb6, + 0xf7, 0x54, 0xf9, 0x8d, 0xf5, 0x72, 0x3b, 0x1d, 0x12, 0xd0, 0xe1, 0x31, + 0xe2, 0x9b, 0xa2, 0x21, 0xbb, 0xc0, 0xef, 0xe3, 0xbc, 0x7f, 0xad, 0xf2, + 0x47, 0xe3, 0x3a, 0xe0, 0x7a, 0xe0, 0x01, 0xe0, 0x7e, 0xe0, 0x1a, 0xe0, + 0x6a, 0xe0, 0x2a, 0x60, 0x2f, 0xf0, 0x32, 0x30, 0x0f, 0xf4, 0x80, 0x39, + 0xe0, 0x05, 0xa0, 0x0b, 0xcc, 0x00, 0x6b, 0xc0, 0xab, 0xc0, 0x14, 0xf0, + 0x28, 0xf0, 0x21, 0xf0, 0x31, 0xf0, 0x0b, 0xf0, 0x1c, 0xd0, 0xb1, 0x60, + 0x0f, 0xa8, 0x7e, 0x3e, 0xee, 0x47, 0x48, 0xa7, 0xeb, 0xa8, 0x7f, 0xad, + 0x33, 0xde, 0x97, 0x0d, 0x0f, 0xf9, 0x65, 0x9d, 0x2e, 0x83, 0xd7, 0x5b, + 0xbf, 0x19, 0xb9, 0x27, 0xa5, 0xae, 0xf7, 0x23, 0x9a, 0x37, 0x8f, 0xe3, + 0x39, 0xb4, 0xc3, 0xe3, 0x73, 0x72, 0x49, 0x59, 0x37, 0x6e, 0xed, 0xf1, + 0x04, 0x8f, 0xa4, 0x05, 0x3f, 0xa7, 0x7b, 0xd4, 0xff, 0x66, 0x73, 0x26, + 0x23, 0xcf, 0x87, 0xb3, 0x46, 0x67, 0x63, 0xc7, 0xf8, 0xd3, 0xcd, 0x8f, + 0x4e, 0xe7, 0x19, 0xbf, 0xba, 0x9d, 0x2b, 0x58, 0xb5, 0xc3, 0xf1, 0x5f, + 0x19, 0x15, 0x8c, 0x8f, 0x31, 0x54, 0xdc, 0x64, 0x5c, 0xe3, 0x56, 0xf7, + 0xb9, 0x39, 0x47, 0xa3, 0x5b, 0xa8, 0xf1, 0x7d, 0x89, 0x53, 0x2d, 0xa9, + 0xed, 0xfe, 0x6c, 0x9e, 0x17, 0x5e, 0xff, 0xe1, 0x97, 0x8c, 0x85, 0x2b, + 0x2f, 0x84, 0xff, 0xba, 0xe4, 0x32, 0xee, 0x1e, 0xa1, 0xc8, 0xcf, 0xbc, + 0x97, 0xfb, 0xe8, 0xb3, 0xdf, 0x3f, 0x2c, 0xbf, 0x61, 0xce, 0xc1, 0xbe, + 0xe3, 0x26, 0x8f, 0x79, 0xf6, 0x73, 0x90, 0xe4, 0x79, 0xba, 0x2c, 0xef, + 0xa7, 0xcb, 0xb8, 0xcf, 0x83, 0xe1, 0x7a, 0x90, 0x7b, 0x11, 0x43, 0xbe, + 0xf7, 0xe2, 0x5e, 0x44, 0xef, 0x71, 0xaa, 0x7e, 0x73, 0x2e, 0x58, 0x2f, + 0x05, 0xaa, 0x8e, 0xc1, 0x9f, 0x96, 0x3c, 0x9b, 0xbe, 0x6c, 0xea, 0x9d, + 0x97, 0xeb, 0x7e, 0x2c, 0xa4, 0xdf, 0x76, 0xaa, 0x04, 0xf3, 0x64, 0xb5, + 0xa9, 0x97, 0x6e, 0xe7, 0x84, 0xec, 0xe5, 0x54, 0x06, 0xa8, 0xb5, 0x8e, + 0x1d, 0xc4, 0x35, 0x81, 0x3a, 0x5e, 0xdb, 0x52, 0xc7, 0xa6, 0xdf, 0x4b, + 0x3d, 0x77, 0xea, 0x5f, 0x7f, 0xdf, 0xa7, 0x85, 0xe7, 0x07, 0xea, 0xd3, + 0xf4, 0x43, 0xe8, 0xe4, 0x30, 0xaf, 0xb8, 0x70, 0x5f, 0xf2, 0x26, 0xfd, + 0x5c, 0x15, 0xa3, 0x1f, 0xf6, 0xd3, 0x31, 0xf1, 0x0d, 0x04, 0xfb, 0xe7, + 0x50, 0x87, 0x7c, 0x05, 0xfb, 0x6e, 0x54, 0x97, 0x70, 0xdd, 0x4b, 0xfe, + 0xd3, 0xd0, 0xa9, 0xbf, 0x4b, 0x5f, 0xe8, 0x01, 0x6f, 0xcd, 0x32, 0x3c, + 0xb1, 0x3b, 0x59, 0x0e, 0xf6, 0x11, 0xaf, 0x89, 0xfe, 0x87, 0x7d, 0x7d, + 0xf5, 0x47, 0x1d, 0xf2, 0x30, 0xfe, 0x7f, 0xf3, 0x80, 0xf9, 0x52, 0xb4, + 0x24, 0x0f, 0x09, 0x5a, 0x99, 0xbe, 0x84, 0xf8, 0xa9, 0x83, 0xbe, 0x49, + 0xe8, 0xf0, 0x6d, 0x71, 0x79, 0x7d, 0x33, 0xe0, 0x7d, 0x0d, 0xf0, 0xb8, + 0x2e, 0xc6, 0xe5, 0xfe, 0x39, 0xd5, 0x2f, 0x11, 0xdd, 0xc6, 0x2a, 0xba, + 0xaf, 0x9c, 0xa0, 0x06, 0xe2, 0x7a, 0x1b, 0x8a, 0x2f, 0xab, 0xfc, 0x93, + 0xef, 0x84, 0x3b, 0x0d, 0xa3, 0x83, 0xbc, 0x2e, 0x55, 0x04, 0x6f, 0x33, + 0x3f, 0x1f, 0xd0, 0x23, 0xac, 0x9b, 0xe8, 0x91, 0xa7, 0x5b, 0x7f, 0xfa, + 0x8d, 0xc7, 0xf6, 0x46, 0xd1, 0xaf, 0x0f, 0xa1, 0x6f, 0x7e, 0x48, 0x4b, + 0x5f, 0xae, 0x4e, 0x71, 0xff, 0xa4, 0x3e, 0xf4, 0xcf, 0x6a, 0x56, 0x9e, + 0xfb, 0xb3, 0xf2, 0x1d, 0x36, 0xea, 0xb8, 0xcc, 0xeb, 0xcf, 0x0a, 0xf6, + 0x65, 0xf4, 0xbe, 0x02, 0x7d, 0xdc, 0xc5, 0xf4, 0xca, 0xbc, 0x2b, 0x7d, + 0x74, 0xfe, 0x05, 0xfa, 0xba, 0x67, 0x74, 0x42, 0xbc, 0x5b, 0xf4, 0x7a, + 0x1f, 0x7f, 0xf2, 0x2c, 0xe9, 0xab, 0x38, 0xc3, 0xe2, 0xdf, 0x0d, 0x78, + 0x5f, 0x32, 0xfb, 0x06, 0xb4, 0x9e, 0x4f, 0x16, 0xcd, 0xdc, 0x18, 0xdc, + 0xa1, 0xfd, 0xf1, 0x28, 0xe7, 0x48, 0x3e, 0x05, 0x15, 0xcf, 0x76, 0xf4, + 0xb6, 0xe2, 0xac, 0x2d, 0xcf, 0xb3, 0x27, 0xd9, 0xcc, 0xae, 0x59, 0xb3, + 0x3e, 0xc9, 0x05, 0x3a, 0x7d, 0xf7, 0x19, 0xaf, 0xe7, 0x1a, 0x31, 0x59, + 0x77, 0xa6, 0x8c, 0x1e, 0x1e, 0xc7, 0x57, 0x13, 0x3d, 0xf6, 0x5d, 0x14, + 0xdc, 0x4b, 0x3b, 0x19, 0xd3, 0x35, 0x57, 0xe6, 0xca, 0xbc, 0x9b, 0x62, + 0x24, 0xd6, 0xc3, 0xde, 0x2c, 0xf3, 0x21, 0x81, 0xbe, 0xde, 0x13, 0xc8, + 0x53, 0x74, 0xde, 0xae, 0x34, 0x5f, 0xc1, 0x39, 0x60, 0xe6, 0x43, 0xb4, + 0xdf, 0x67, 0x51, 0x67, 0xd7, 0xba, 0xd4, 0xa3, 0xe9, 0x9f, 0x97, 0x16, + 0xe5, 0x1e, 0xb4, 0x9b, 0xb3, 0x1a, 0x73, 0x1d, 0xbe, 0x0f, 0x8a, 0xa8, + 0x3f, 0x33, 0x0f, 0xdb, 0x7d, 0x07, 0x08, 0x7f, 0x65, 0xf3, 0x3f, 0xdf, + 0x61, 0xfe, 0xff, 0xb3, 0x39, 0x5f, 0x58, 0xca, 0xa3, 0xa9, 0xd3, 0x60, + 0x1e, 0x83, 0xf5, 0x1a, 0x9d, 0xc3, 0xcb, 0xcd, 0xdf, 0x1c, 0x74, 0x3e, + 0x06, 0x9d, 0xe3, 0x94, 0x88, 0xb1, 0x30, 0x6e, 0xfc, 0x14, 0xdb, 0xb5, + 0x67, 0x6d, 0xa6, 0xbb, 0x89, 0x33, 0x96, 0xc6, 0x9c, 0x7b, 0x46, 0x78, + 0x71, 0x59, 0x2f, 0x18, 0x3c, 0x7b, 0x4a, 0xbe, 0xfb, 0x6c, 0xfa, 0x0d, + 0x6d, 0x29, 0x98, 0xe1, 0x30, 0x0d, 0x00, 0x00, 0x00 }; static u8 bnx2_xi_rv2p_proc2[] = { - /* Date: 12/07/2007 16:21 */ - 0xad, 0x58, 0x5d, 0x6c, 0xd3, 0x55, 0x14, 0xbf, 0xfd, 0x58, 0xdb, 0xb5, + /* Date: 01/14/2008 15:44 */ + 0xad, 0x58, 0x5d, 0x6c, 0xd3, 0x55, 0x14, 0xbf, 0xfd, 0x58, 0xdb, 0x75, 0xff, 0xb6, 0x63, 0x9b, 0xdd, 0xa7, 0x6e, 0x6e, 0x61, 0x6c, 0xd8, 0xcd, 0xd1, 0x8d, 0x4f, 0x4d, 0x5c, 0x86, 0x19, 0x20, 0x26, 0x8c, 0x61, 0xd4, - 0x37, 0xd8, 0x90, 0xb2, 0xb1, 0x8d, 0x2c, 0x8c, 0xf0, 0xc0, 0x8b, 0x0d, + 0x37, 0xd8, 0x90, 0xb2, 0xb2, 0x8d, 0x2c, 0x8c, 0xf0, 0xc0, 0x8b, 0x0d, 0xd3, 0xf1, 0xd2, 0x07, 0x47, 0xb2, 0x0d, 0x8d, 0xc1, 0x45, 0x7d, 0x40, - 0x9f, 0xec, 0x83, 0x32, 0x30, 0xc6, 0xc4, 0xe8, 0x42, 0xf0, 0x01, 0x48, + 0x9f, 0xec, 0x83, 0x52, 0x30, 0xc6, 0xc4, 0xe8, 0x42, 0xf0, 0x01, 0x48, 0x30, 0xc6, 0x68, 0x48, 0x08, 0xea, 0x32, 0x10, 0x75, 0x0c, 0xfb, 0x64, - 0x98, 0xf7, 0x9e, 0xdf, 0xb9, 0xff, 0xfe, 0xff, 0x6d, 0x27, 0x18, 0xec, + 0x98, 0xf7, 0x9e, 0xdf, 0xb9, 0xff, 0xfe, 0xff, 0x5d, 0x27, 0x18, 0xec, 0x43, 0x4f, 0xef, 0xbd, 0xe7, 0x9e, 0x7b, 0x3e, 0x7e, 0xe7, 0x9c, 0x7b, - 0x5b, 0x24, 0x84, 0x70, 0x8a, 0x44, 0xaa, 0x46, 0x52, 0x11, 0x70, 0xb8, - 0x04, 0x3e, 0x6b, 0x8b, 0x88, 0x5c, 0x4b, 0xf9, 0xe4, 0x77, 0x81, 0x78, - 0xc9, 0x59, 0x4e, 0x63, 0xb7, 0x50, 0x34, 0x2c, 0x44, 0xc2, 0x4a, 0x4b, - 0x98, 0x5e, 0x65, 0xfa, 0x3b, 0xd3, 0xc7, 0x1d, 0xa0, 0x57, 0x78, 0xbc, - 0x85, 0xc7, 0xd7, 0x78, 0xfc, 0x23, 0xd3, 0x8d, 0x3c, 0xbf, 0x99, 0x69, - 0x92, 0xe9, 0x76, 0x5e, 0x9f, 0x65, 0x2a, 0x3f, 0x09, 0x43, 0x7e, 0xc9, - 0xe5, 0x26, 0xad, 0xa7, 0x81, 0xe9, 0x26, 0xe8, 0xbb, 0xa7, 0x56, 0xf1, - 0x2d, 0x2c, 0x67, 0xf8, 0x30, 0x7f, 0x7d, 0x02, 0xb4, 0x06, 0xbb, 0x3e, - 0x4e, 0x3c, 0xad, 0xf7, 0x83, 0xf4, 0x06, 0x41, 0xfb, 0xd8, 0xfe, 0x8e, - 0x28, 0x91, 0xe4, 0x7e, 0x27, 0xc6, 0x5d, 0x0d, 0xca, 0x0f, 0xc5, 0xc2, - 0xed, 0x54, 0x72, 0x5a, 0x7c, 0x9e, 0xf3, 0x98, 0x7f, 0x35, 0x0c, 0xfa, - 0x9a, 0x1f, 0xf4, 0x17, 0x7f, 0xa1, 0xfc, 0x5e, 0x5e, 0x8e, 0x07, 0x58, - 0xbe, 0xc1, 0x6a, 0x07, 0xb0, 0x7f, 0xce, 0x80, 0x1e, 0x2f, 0xd7, 0x42, + 0x5b, 0x2c, 0x84, 0x70, 0x8a, 0x44, 0xaa, 0x56, 0x52, 0x61, 0x38, 0x5c, + 0x02, 0x9f, 0xb5, 0xc5, 0x44, 0xae, 0xa5, 0x7c, 0xf2, 0xbb, 0x40, 0xbc, + 0xe4, 0xac, 0xa0, 0xb1, 0x5b, 0x28, 0x1a, 0x12, 0x22, 0x61, 0xa5, 0xa5, + 0x4c, 0xaf, 0x32, 0xfd, 0x9d, 0xe9, 0xe3, 0x0e, 0xd0, 0x2b, 0x3c, 0xde, + 0xc2, 0xe3, 0x6b, 0x3c, 0xfe, 0x91, 0xe9, 0x46, 0x9e, 0xdf, 0xcc, 0x34, + 0xc9, 0x74, 0x3b, 0xaf, 0xa7, 0x99, 0xca, 0x4f, 0xc2, 0x90, 0x5f, 0x72, + 0xb9, 0x59, 0xeb, 0x69, 0x60, 0xba, 0x19, 0xfa, 0xee, 0xa9, 0x53, 0x7c, + 0xf3, 0x4b, 0x59, 0x3e, 0xcc, 0x5f, 0x9f, 0x00, 0xad, 0xc5, 0xae, 0x8f, + 0x13, 0x4f, 0xeb, 0xfd, 0x20, 0x7d, 0x01, 0xd0, 0x7e, 0xb6, 0xbf, 0x33, + 0x42, 0x24, 0xb9, 0xdf, 0x89, 0x71, 0x77, 0xa3, 0xf2, 0x43, 0x89, 0x70, + 0x3b, 0x95, 0x9c, 0x56, 0x9f, 0xe7, 0x3c, 0xe6, 0x5f, 0x0d, 0x81, 0xbe, + 0xe6, 0x07, 0xfd, 0xc5, 0x5f, 0x28, 0xbf, 0x97, 0x96, 0x62, 0x45, 0x2c, + 0xdf, 0x60, 0xb5, 0x8b, 0xb0, 0x7f, 0xd6, 0x80, 0x1e, 0x2f, 0xd7, 0x41, 0xbf, 0xef, 0x9f, 0x52, 0xf3, 0x2e, 0x91, 0x60, 0x39, 0x42, 0x68, 0x3d, - 0x79, 0x7d, 0x10, 0xfb, 0x56, 0xad, 0xc1, 0xea, 0x5b, 0x71, 0x8c, 0xab, - 0x3e, 0x28, 0xa2, 0xb8, 0x9c, 0x4e, 0x69, 0xfe, 0x7c, 0x72, 0xdd, 0x52, - 0x2e, 0xe4, 0x8b, 0x3a, 0x1f, 0x29, 0x93, 0x88, 0x82, 0x8a, 0xe6, 0xec, - 0x73, 0x20, 0x7f, 0x6a, 0xb5, 0x9a, 0x77, 0x8a, 0x1e, 0x97, 0x9a, 0xf7, - 0x88, 0x9e, 0x01, 0xed, 0x5f, 0xac, 0xc7, 0x3d, 0x44, 0xca, 0x7b, 0xc7, - 0x95, 0x9d, 0x61, 0xb1, 0xcf, 0x19, 0x26, 0x7e, 0xf8, 0xc5, 0xe5, 0x33, - 0x3e, 0x03, 0xff, 0x97, 0x35, 0x06, 0xd9, 0x12, 0x6f, 0xc3, 0xbe, 0xd2, - 0x18, 0xe8, 0x64, 0xac, 0x40, 0x91, 0x68, 0x7c, 0x94, 0x86, 0x2d, 0x37, - 0xd7, 0xf9, 0x88, 0x2f, 0xd1, 0xac, 0xe3, 0xa7, 0xe3, 0xa5, 0xe2, 0xf8, - 0x89, 0x8c, 0x23, 0xbb, 0xa5, 0x1e, 0x7e, 0xfd, 0x75, 0xb5, 0xe2, 0x97, - 0xce, 0xad, 0xc3, 0x39, 0x19, 0xfd, 0xac, 0xf1, 0xff, 0xe8, 0x3f, 0xc4, - 0x5f, 0xc9, 0xeb, 0x60, 0xbf, 0xd4, 0x4a, 0xbf, 0x28, 0x5a, 0xed, 0x48, - 0x34, 0xdb, 0xe3, 0x71, 0x7d, 0x22, 0x4c, 0xbf, 0x6f, 0x75, 0x16, 0x91, - 0x5f, 0x77, 0x61, 0xfe, 0x54, 0xd7, 0x39, 0xc4, 0x63, 0x07, 0xd9, 0x2f, - 0xfc, 0x6f, 0x7c, 0x8a, 0x5d, 0xbd, 0x41, 0x35, 0x7e, 0xa5, 0x3d, 0x7e, - 0x01, 0xeb, 0x05, 0x63, 0xf0, 0xeb, 0x2e, 0x96, 0xba, 0xc3, 0xe5, 0x50, - 0x24, 0xe9, 0x19, 0xa3, 0xa1, 0x31, 0x47, 0xeb, 0x86, 0x38, 0x99, 0xc2, - 0xfa, 0xe1, 0x80, 0x1a, 0xef, 0x8a, 0x2e, 0x60, 0x1c, 0x1d, 0x18, 0xe7, - 0x8d, 0x4e, 0xf8, 0xe1, 0x96, 0x13, 0xf2, 0x18, 0x5e, 0x7e, 0x37, 0xc5, - 0xc1, 0x21, 0x8c, 0x2e, 0xd0, 0x37, 0x69, 0xfd, 0x6f, 0x47, 0x92, 0xec, - 0xee, 0x0a, 0xb9, 0xcf, 0x81, 0x91, 0x71, 0x6d, 0xe2, 0x56, 0xe3, 0xfe, - 0x61, 0xf1, 0x3b, 0x6e, 0x68, 0xbc, 0xb2, 0xff, 0xd9, 0xbf, 0xef, 0x89, - 0x6c, 0x9c, 0x82, 0x76, 0x35, 0x80, 0x7a, 0xea, 0xb3, 0xf1, 0xaa, 0xf1, - 0x69, 0xf7, 0x33, 0xc7, 0xc7, 0x82, 0x17, 0x22, 0x12, 0x27, 0x36, 0xdc, - 0x30, 0x4e, 0x2b, 0xa4, 0xbf, 0x74, 0xfc, 0x95, 0x20, 0xaf, 0x18, 0x64, - 0x79, 0x03, 0x6c, 0xd7, 0x10, 0xdb, 0x75, 0xc7, 0xaf, 0xfd, 0xaa, 0xed, - 0x01, 0x3d, 0x69, 0xb3, 0xc7, 0x21, 0xf1, 0x64, 0xc7, 0x21, 0xeb, 0x93, - 0xfc, 0xa6, 0x0e, 0x3f, 0xaa, 0xea, 0x41, 0x4d, 0x3b, 0x1b, 0x14, 0x9f, - 0x27, 0x36, 0x9d, 0xb2, 0xe3, 0x50, 0xe7, 0xe3, 0x9e, 0x5a, 0x2d, 0x5f, - 0xe1, 0x32, 0x2d, 0x71, 0x89, 0xb8, 0x9d, 0x4e, 0x59, 0xf3, 0xb3, 0x32, - 0x4f, 0x7e, 0xda, 0xf3, 0x42, 0xfb, 0xe5, 0x70, 0x90, 0x0a, 0x54, 0xfb, - 0xe5, 0x79, 0xfb, 0x79, 0xc0, 0xb7, 0xd7, 0xc4, 0x4f, 0xe9, 0x06, 0xf6, - 0x1f, 0xd3, 0xc8, 0x46, 0x25, 0xaf, 0x9b, 0xe5, 0xb7, 0xb2, 0x7c, 0xc3, - 0x92, 0x77, 0x4a, 0xbf, 0x4e, 0x33, 0xdf, 0x74, 0xdc, 0x32, 0x79, 0xa7, - 0xfd, 0x47, 0xe7, 0x47, 0x2f, 0xcf, 0xab, 0xfd, 0x55, 0x0f, 0xc8, 0xc3, - 0x4d, 0xa6, 0xbc, 0xef, 0xcc, 0x7c, 0x53, 0xeb, 0x01, 0xf1, 0x1c, 0x0f, - 0xed, 0xf5, 0xe4, 0x4f, 0x59, 0x4f, 0xc8, 0x0e, 0x9f, 0x71, 0x8e, 0xeb, - 0xc7, 0xa8, 0x3a, 0xa7, 0x9c, 0xf5, 0x2e, 0x67, 0xbd, 0x65, 0xbf, 0x6a, - 0xe6, 0x3a, 0xb3, 0xd7, 0x5a, 0x2f, 0xd6, 0x5a, 0xf2, 0x5e, 0x8d, 0x1b, - 0x97, 0x73, 0xfb, 0x85, 0xcd, 0x9f, 0x09, 0x41, 0xfe, 0xf7, 0x72, 0x7c, + 0x79, 0x7d, 0x10, 0xfb, 0x56, 0xad, 0xc1, 0xea, 0x5b, 0x31, 0x8c, 0xab, + 0x3f, 0x28, 0xa6, 0xb8, 0x9c, 0x4e, 0x69, 0xfe, 0x7c, 0x72, 0xdd, 0x52, + 0x2e, 0xe4, 0x8b, 0x7a, 0x1f, 0x29, 0x93, 0x88, 0x80, 0x8a, 0x96, 0xdc, + 0x73, 0x20, 0x7f, 0x6a, 0xb5, 0x9a, 0x77, 0x8a, 0x5e, 0x97, 0x9a, 0xf7, + 0x88, 0xde, 0xb8, 0xf6, 0x2f, 0xd6, 0x63, 0x1e, 0x22, 0x15, 0x7d, 0xe3, + 0xca, 0xce, 0x90, 0xd8, 0xe7, 0x0c, 0x11, 0x3f, 0xfc, 0xe2, 0xf2, 0x19, + 0x9f, 0x81, 0xff, 0xcb, 0x5a, 0x83, 0x6c, 0x89, 0xb5, 0x63, 0x5f, 0x59, + 0x14, 0x74, 0x32, 0x5a, 0xa0, 0x48, 0x24, 0x36, 0x4a, 0xc3, 0xd6, 0x9b, + 0xeb, 0x7c, 0xc4, 0x97, 0x68, 0xd1, 0xf1, 0xd3, 0xf1, 0x52, 0x71, 0xfc, + 0x44, 0xc6, 0x91, 0xdd, 0xd2, 0x00, 0xbf, 0xfe, 0xba, 0x5a, 0xf1, 0x4b, + 0xe7, 0xd6, 0xe3, 0x9c, 0xac, 0x7e, 0xd6, 0xf8, 0x7f, 0xf4, 0x1f, 0xe2, + 0xaf, 0xe4, 0x75, 0xb2, 0x5f, 0xea, 0xa4, 0x5f, 0x14, 0xad, 0x71, 0x24, + 0x5a, 0xec, 0xf1, 0xb8, 0x3e, 0x11, 0xa2, 0xdf, 0xb7, 0xba, 0x8a, 0xc9, + 0xaf, 0xbb, 0x30, 0x7f, 0xaa, 0xfb, 0x1c, 0xe2, 0xb1, 0x83, 0xec, 0x17, + 0xfe, 0x37, 0x3e, 0xc5, 0xae, 0xbe, 0x80, 0x1a, 0xbf, 0xd2, 0x11, 0xbb, + 0x80, 0xf5, 0x82, 0x31, 0xf8, 0x75, 0x17, 0x4b, 0xdd, 0xe1, 0x72, 0x28, + 0x92, 0xf4, 0x8c, 0xd1, 0xd0, 0x98, 0xa5, 0x75, 0x43, 0x9c, 0x4c, 0x61, + 0xfd, 0x70, 0x91, 0x1a, 0xef, 0x8a, 0xcc, 0x63, 0x1c, 0x89, 0x8f, 0xf3, + 0x46, 0x27, 0xfc, 0x70, 0xcb, 0x09, 0x79, 0x0c, 0x2f, 0xbf, 0x9b, 0xe2, + 0xe0, 0x10, 0x46, 0x37, 0xe8, 0x9b, 0xb4, 0xfe, 0xb7, 0x23, 0x49, 0x76, + 0x77, 0x07, 0xdd, 0xe7, 0xc0, 0xc8, 0xb8, 0x36, 0x71, 0xab, 0x71, 0xff, + 0xb0, 0xf8, 0x1d, 0x37, 0x34, 0x5e, 0xd9, 0xff, 0xec, 0xdf, 0xf7, 0x44, + 0x2e, 0x4e, 0x41, 0xbb, 0x1b, 0x41, 0x3d, 0x0d, 0xb9, 0x78, 0xd5, 0xf8, + 0xb4, 0xfb, 0x99, 0xe3, 0x63, 0xc1, 0x0b, 0x11, 0x89, 0x13, 0x1b, 0x6e, + 0x18, 0xa7, 0x95, 0xd2, 0x5f, 0x3a, 0xfe, 0x4a, 0x90, 0x57, 0x0c, 0xb2, + 0xbc, 0x38, 0xdb, 0x35, 0xc4, 0x76, 0xdd, 0xf1, 0x6b, 0xbf, 0x6a, 0x7b, + 0x40, 0x4f, 0xda, 0xec, 0x71, 0x48, 0x3c, 0xd9, 0x71, 0xc8, 0xfa, 0x24, + 0xbf, 0xa9, 0xc7, 0x8f, 0xea, 0x06, 0x50, 0xd3, 0xce, 0x46, 0xc5, 0xe7, + 0x89, 0x4e, 0xa7, 0xec, 0x38, 0xd4, 0xf9, 0xb8, 0xa7, 0x4e, 0xcb, 0x57, + 0xb8, 0xcc, 0x48, 0x5c, 0x22, 0x6e, 0xa7, 0x53, 0xd6, 0xfc, 0xac, 0xca, + 0x93, 0x9f, 0xf6, 0xbc, 0xd0, 0x7e, 0x39, 0x1c, 0xa0, 0x02, 0xd5, 0x71, + 0x79, 0xce, 0x7e, 0x1e, 0xf0, 0xed, 0x35, 0xf1, 0x53, 0xb6, 0x81, 0xfd, + 0xc7, 0x34, 0xbc, 0x51, 0xc9, 0xeb, 0x61, 0xf9, 0x6d, 0x2c, 0xdf, 0xb0, + 0xe4, 0x9d, 0xd2, 0xaf, 0xcb, 0xcc, 0x37, 0x1d, 0xb7, 0x6c, 0xde, 0x69, + 0xff, 0xd1, 0xf9, 0x91, 0xcb, 0x73, 0x6a, 0x7f, 0xf5, 0x03, 0xf2, 0x70, + 0x93, 0x29, 0xef, 0x3b, 0x33, 0xdf, 0xd4, 0x7a, 0x91, 0x78, 0x8e, 0x87, + 0xf6, 0x7a, 0xf2, 0xa7, 0xac, 0x27, 0x64, 0x87, 0xcf, 0x38, 0xc7, 0xf5, + 0x63, 0x54, 0x9d, 0x53, 0xc1, 0x7a, 0x57, 0xb0, 0xde, 0xb2, 0x5f, 0xb5, + 0x70, 0x9d, 0xd9, 0x6b, 0xad, 0x17, 0x6b, 0x2d, 0x79, 0xaf, 0xc6, 0x4d, + 0x4b, 0xcb, 0xfb, 0x85, 0xcd, 0x9f, 0x09, 0x41, 0xfe, 0xf7, 0x72, 0x7c, 0x3c, 0x79, 0xfa, 0x8b, 0xe6, 0x07, 0xbe, 0xb6, 0x11, 0xbf, 0xcf, 0xc4, - 0xbf, 0xdd, 0xde, 0xca, 0x3c, 0x75, 0x27, 0xdb, 0x7e, 0xf8, 0xb3, 0xd7, - 0x19, 0x24, 0xbe, 0x1b, 0x23, 0x6a, 0xdf, 0x49, 0x87, 0xf6, 0x53, 0x07, - 0xea, 0x90, 0x03, 0xf6, 0x56, 0xb3, 0xbd, 0x72, 0xb9, 0x99, 0xf0, 0xef, + 0xbf, 0xdd, 0xde, 0xaa, 0x3c, 0x75, 0x27, 0xd7, 0x7e, 0xf8, 0xb3, 0xcf, + 0x19, 0x20, 0xbe, 0x1b, 0x23, 0x6a, 0xdf, 0x49, 0x87, 0xf6, 0x53, 0x27, + 0xea, 0x90, 0x03, 0xf6, 0xd6, 0xb0, 0xbd, 0x72, 0xb9, 0x85, 0xf0, 0xef, 0xbb, 0x31, 0x62, 0xb5, 0xd7, 0xf8, 0x97, 0xf3, 0xec, 0xb8, 0x19, 0xe1, - 0x3e, 0xd6, 0x87, 0xbc, 0xf0, 0xed, 0xff, 0x5c, 0xeb, 0xc3, 0xe7, 0x86, - 0xf5, 0xf9, 0x4a, 0x5e, 0x95, 0x98, 0x1f, 0x55, 0xfb, 0x1f, 0x13, 0x0c, - 0x33, 0x31, 0xdc, 0x88, 0xfa, 0x77, 0xe7, 0x00, 0xf4, 0x1f, 0x6e, 0xd0, + 0x3e, 0xd6, 0x8f, 0xbc, 0xf0, 0xed, 0xff, 0x5c, 0xeb, 0xc3, 0xe7, 0x86, + 0xf4, 0xf9, 0x4a, 0x5e, 0xb5, 0x98, 0x1b, 0x55, 0xfb, 0x1f, 0x13, 0x0c, + 0x33, 0x31, 0xdc, 0x84, 0xfa, 0x77, 0xe7, 0x00, 0xf4, 0x1f, 0x6e, 0xd4, 0x7d, 0x1c, 0x38, 0x16, 0x5c, 0xff, 0xbf, 0x9e, 0xc8, 0xe7, 0x97, 0x41, - 0x07, 0xf8, 0x4a, 0xd9, 0xae, 0x22, 0xb6, 0x2b, 0x2a, 0xb2, 0xeb, 0xec, - 0x5e, 0xca, 0x97, 0x0e, 0xe6, 0x7b, 0x56, 0xd7, 0xe3, 0x1c, 0x3e, 0xd8, - 0x5f, 0xc0, 0xe7, 0xe7, 0xf3, 0x57, 0x3e, 0xb9, 0xb3, 0x8c, 0xa3, 0x7e, - 0xe6, 0x73, 0xe7, 0xa9, 0xf3, 0x18, 0xa5, 0xd7, 0x50, 0x9d, 0x3f, 0x73, - 0x7c, 0x56, 0xf1, 0x05, 0x4d, 0x9c, 0xdb, 0xed, 0xfa, 0xe9, 0xfe, 0xa3, - 0xfb, 0x5f, 0xf1, 0x45, 0xc4, 0xc1, 0xd0, 0x4a, 0x7e, 0x76, 0xab, 0xe9, - 0x99, 0xc5, 0x59, 0x1d, 0x27, 0x83, 0xec, 0x9c, 0x1f, 0x55, 0xe7, 0x7f, - 0x98, 0xe5, 0x7f, 0xa7, 0xc5, 0xff, 0xe0, 0x7f, 0x22, 0xfa, 0xa8, 0x7e, - 0xcf, 0xd7, 0x97, 0xbf, 0xb8, 0x9f, 0x9b, 0x27, 0x6a, 0xfe, 0xc2, 0x43, - 0xfb, 0x63, 0x77, 0x9b, 0xd5, 0xfe, 0x7a, 0x31, 0x97, 0x42, 0x7e, 0x75, - 0x33, 0x0e, 0xf7, 0x71, 0xbd, 0xbe, 0xe1, 0x57, 0x13, 0x3e, 0xd1, 0xb7, - 0x93, 0xfc, 0x21, 0x22, 0x01, 0xf8, 0xa7, 0xef, 0x45, 0xed, 0x4f, 0xcc, - 0x57, 0x52, 0xbf, 0x75, 0x89, 0x6e, 0xaf, 0x41, 0xfc, 0x95, 0x41, 0xd0, - 0x08, 0xd7, 0xf9, 0x39, 0xb3, 0x8f, 0x81, 0x9e, 0xf6, 0xe8, 0xba, 0x8c, - 0x7e, 0xfe, 0x95, 0x47, 0x31, 0xc8, 0x20, 0x35, 0xa1, 0x3e, 0x77, 0x36, - 0x18, 0xb4, 0xde, 0xd3, 0x04, 0x3c, 0x89, 0x3a, 0xdd, 0xe7, 0xf0, 0xe1, - 0x3e, 0x50, 0x99, 0xe9, 0x77, 0xd6, 0x7e, 0x58, 0x68, 0xe9, 0x07, 0xfa, + 0x07, 0xf8, 0xca, 0xd8, 0xae, 0x62, 0xb6, 0x2b, 0x22, 0x72, 0xeb, 0xec, + 0x5e, 0xca, 0x97, 0x4e, 0xe6, 0x7b, 0x56, 0xd7, 0xe3, 0x65, 0x7c, 0xb0, + 0xbf, 0x80, 0xcf, 0xcf, 0xe7, 0xaf, 0x7c, 0x72, 0xd3, 0x8c, 0xa3, 0x01, + 0xe6, 0x73, 0xe7, 0xa9, 0xf3, 0x18, 0x65, 0xd6, 0x50, 0x9d, 0x3f, 0x73, + 0x3c, 0xad, 0xf8, 0x02, 0x26, 0xce, 0xed, 0x76, 0xfd, 0x74, 0xff, 0xd1, + 0xfd, 0xaf, 0xf8, 0xc2, 0xe2, 0x60, 0x70, 0x25, 0x3f, 0xbb, 0xd5, 0xf4, + 0xcc, 0x42, 0x5a, 0xc7, 0xc9, 0x20, 0x3b, 0xe7, 0x46, 0xd5, 0xf9, 0x1f, + 0xe6, 0xf8, 0xdf, 0x69, 0xf1, 0x3f, 0xf8, 0x9f, 0x88, 0x3c, 0xaa, 0xdf, + 0xf3, 0xf5, 0xe5, 0x2f, 0xee, 0x2f, 0xcf, 0x13, 0x35, 0x7f, 0xe1, 0xa1, + 0xfd, 0xb1, 0xbb, 0xdd, 0x6a, 0x7f, 0x83, 0x98, 0x4d, 0x21, 0xbf, 0x7a, + 0x18, 0x87, 0xfb, 0xb8, 0x5e, 0xdf, 0xf0, 0xab, 0x09, 0x9f, 0xe8, 0xdf, + 0x49, 0xfe, 0x10, 0xe1, 0x22, 0xf8, 0xa7, 0xff, 0x45, 0xed, 0x4f, 0xcc, + 0x57, 0x51, 0xbf, 0x75, 0x89, 0x1e, 0xaf, 0x41, 0xfc, 0x55, 0x01, 0xd0, + 0x30, 0xd7, 0xf9, 0x59, 0xb3, 0x8f, 0x81, 0x9e, 0xf6, 0xe8, 0xba, 0x8c, + 0x7e, 0xfe, 0x95, 0x47, 0x31, 0xc8, 0x20, 0x35, 0xa3, 0x3e, 0x77, 0x35, + 0x1a, 0xb4, 0xde, 0xdb, 0x0c, 0x3c, 0x89, 0x7a, 0xdd, 0xe7, 0xf0, 0xe1, + 0x3e, 0x50, 0x95, 0xed, 0x77, 0xd6, 0x7e, 0x58, 0x68, 0xe9, 0x07, 0xfa, 0x3c, 0xed, 0x47, 0x2d, 0x97, 0x86, 0xb2, 0xaf, 0x58, 0xfb, 0xa1, 0xee, - 0x13, 0x4b, 0xdc, 0x27, 0x4a, 0xc4, 0xc5, 0x14, 0xec, 0x9a, 0x4b, 0x65, - 0xe3, 0x4f, 0x9f, 0xa7, 0xe5, 0x41, 0x6f, 0x6d, 0x47, 0x46, 0x3e, 0xce, - 0x3f, 0xc0, 0x7a, 0xfe, 0x4c, 0xf7, 0xd8, 0x08, 0xdb, 0xa3, 0xe4, 0x62, - 0x7e, 0x3b, 0xf7, 0xe7, 0x84, 0x39, 0xb6, 0xf7, 0xd5, 0x6e, 0xd2, 0xab, - 0x98, 0xf1, 0x16, 0xb1, 0xe4, 0x03, 0xf8, 0x4b, 0x5b, 0x41, 0x27, 0x5b, - 0x75, 0x1c, 0x74, 0xbc, 0x74, 0x7c, 0x10, 0xc7, 0xc8, 0x3a, 0x62, 0x6b, - 0xef, 0x5b, 0x47, 0x7d, 0xa4, 0xb5, 0x6f, 0x51, 0xe3, 0x0f, 0xfb, 0x77, - 0x47, 0x15, 0xff, 0xeb, 0xe2, 0x2a, 0xe1, 0x50, 0x88, 0x1f, 0x98, 0x66, - 0xfa, 0x15, 0x07, 0xc0, 0xcc, 0x57, 0x8e, 0x5f, 0x01, 0x4f, 0xb7, 0xe9, - 0x7a, 0xae, 0xe3, 0x65, 0xcd, 0xd7, 0x78, 0x0e, 0x6e, 0x33, 0x75, 0x59, - 0xdb, 0xa9, 0xf8, 0xa3, 0x8c, 0x47, 0x9f, 0xe8, 0xdc, 0x86, 0x7b, 0x6e, - 0xc8, 0x8b, 0xba, 0x1f, 0xf2, 0x5a, 0xe3, 0x25, 0x71, 0x51, 0xe8, 0x55, - 0xc3, 0xea, 0xe2, 0x42, 0xb2, 0xe7, 0xd4, 0xa5, 0x6f, 0x69, 0xf9, 0xfd, - 0xe9, 0x00, 0xe6, 0xcb, 0x76, 0x86, 0xc9, 0x1f, 0x53, 0xc0, 0xf3, 0xbb, - 0x93, 0xa0, 0xef, 0x88, 0x17, 0xb0, 0xbf, 0xf8, 0x04, 0xdd, 0x03, 0x7d, - 0x65, 0x8c, 0xcf, 0x72, 0xd4, 0x89, 0xe4, 0x34, 0xdd, 0x4b, 0x96, 0x97, - 0x45, 0x50, 0x51, 0x8f, 0xd9, 0x6f, 0x80, 0x4f, 0xb7, 0x25, 0xce, 0x0f, - 0xc2, 0x2b, 0xdd, 0x2b, 0x25, 0x1e, 0xb1, 0x9d, 0x71, 0xeb, 0xcb, 0xc6, - 0xad, 0xf6, 0x47, 0xb9, 0x33, 0x2f, 0x4e, 0x37, 0xd8, 0x71, 0xea, 0x61, - 0x9c, 0xde, 0x33, 0xfb, 0x7b, 0xae, 0x5c, 0xf4, 0xf9, 0x8b, 0xff, 0x1b, - 0x6e, 0x41, 0xb7, 0xd7, 0xab, 0xf3, 0xcb, 0x72, 0xea, 0x71, 0x8d, 0x2d, - 0xce, 0x4d, 0xf7, 0xb5, 0x5e, 0x27, 0x3c, 0xd6, 0xf5, 0x66, 0xb3, 0x9f, - 0x1d, 0xe1, 0x77, 0x5e, 0xda, 0xa0, 0x1f, 0xb1, 0x3b, 0x49, 0x1a, 0x1a, - 0x15, 0x67, 0x15, 0x5f, 0x63, 0xec, 0x08, 0xd7, 0xdb, 0x4b, 0x2e, 0xd4, - 0x9b, 0xfe, 0x03, 0x18, 0x5f, 0xe6, 0xfa, 0x71, 0x77, 0x0d, 0xd5, 0xe5, - 0xd8, 0x91, 0xf3, 0x5a, 0x1e, 0xc9, 0x31, 0xd2, 0x5c, 0xd7, 0x9f, 0x77, - 0x71, 0xbd, 0x25, 0xbf, 0xb9, 0x63, 0x7f, 0xd0, 0x7d, 0xc6, 0x2d, 0x3a, - 0x9f, 0x54, 0xb4, 0x42, 0xd6, 0x6f, 0x3e, 0xff, 0x19, 0xd0, 0x1e, 0x2f, - 0xa8, 0x68, 0xb2, 0xc7, 0x43, 0x98, 0x76, 0x61, 0xe4, 0xa9, 0x63, 0x39, - 0xbd, 0x18, 0x7b, 0xf9, 0x5e, 0x36, 0xcd, 0x7e, 0x0a, 0x91, 0x3f, 0x8a, - 0xa4, 0x9d, 0x8a, 0x86, 0x63, 0xa3, 0xb3, 0xd0, 0x7f, 0x68, 0x2b, 0xec, - 0x5b, 0x62, 0xbb, 0x99, 0x86, 0xde, 0x1e, 0x23, 0xfc, 0x85, 0xc6, 0xf1, - 0x0e, 0x09, 0x79, 0xc6, 0x60, 0xc7, 0x50, 0x1a, 0xe3, 0xa5, 0xcd, 0xa0, - 0x7f, 0x6d, 0xc1, 0xbe, 0xa3, 0xc7, 0xd9, 0x1f, 0x5b, 0xf3, 0xef, 0xeb, - 0xbf, 0x07, 0xbe, 0xe1, 0x46, 0x75, 0xfe, 0xe0, 0x0c, 0xbf, 0x5f, 0xc4, - 0x80, 0x4b, 0x8d, 0x07, 0x8c, 0x34, 0x8f, 0x0f, 0x71, 0x7d, 0xbf, 0xcd, - 0xef, 0x8d, 0xa1, 0xac, 0xf7, 0xc6, 0x02, 0xee, 0x99, 0x33, 0xe9, 0x24, - 0x70, 0x91, 0x28, 0xcc, 0x7e, 0xaf, 0xaa, 0x71, 0x75, 0xac, 0x8c, 0xe3, - 0x54, 0xba, 0x1e, 0x74, 0x72, 0x3d, 0xde, 0x09, 0x43, 0xc7, 0xd8, 0x2f, - 0xed, 0x14, 0xa7, 0x96, 0xc5, 0xd9, 0x95, 0xde, 0xc9, 0xe0, 0x9b, 0xe2, - 0x73, 0x23, 0xdc, 0x4f, 0x22, 0xc8, 0x3f, 0x51, 0x9e, 0xe4, 0x77, 0xcb, - 0x04, 0xee, 0x9d, 0x53, 0x06, 0x68, 0x24, 0xa8, 0xf5, 0x45, 0x3e, 0x26, - 0x52, 0xc8, 0x3b, 0xac, 0x3b, 0x2c, 0xeb, 0x7c, 0x1f, 0xc9, 0x79, 0xe7, - 0x28, 0xba, 0xe4, 0x28, 0x71, 0x68, 0x3b, 0xb1, 0xda, 0x17, 0x54, 0xf8, - 0xbd, 0x69, 0xe6, 0xd5, 0x02, 0xf9, 0xad, 0x6a, 0x26, 0x4d, 0xfa, 0x57, - 0x8a, 0x12, 0xea, 0xc3, 0x15, 0xa1, 0x45, 0xf8, 0x31, 0x36, 0xcd, 0xfe, - 0x1f, 0xd9, 0x04, 0x7a, 0x8c, 0xf1, 0xa7, 0x71, 0x75, 0x65, 0xa3, 0x41, - 0xfb, 0xe6, 0x47, 0x71, 0x8e, 0xbe, 0x47, 0x64, 0xbf, 0xc7, 0x35, 0x1e, - 0x2b, 0xda, 0x50, 0x48, 0xfb, 0x8f, 0xaa, 0x73, 0x82, 0x12, 0x47, 0x4a, - 0x7f, 0xe9, 0x13, 0xce, 0x47, 0x3b, 0x4e, 0x15, 0x8e, 0x75, 0x7e, 0x58, - 0xf1, 0x9d, 0x9d, 0xef, 0x19, 0xbc, 0x86, 0xe8, 0x5e, 0x2e, 0x8b, 0x5c, - 0x82, 0xdf, 0x4d, 0x7c, 0x3f, 0x58, 0x29, 0x7e, 0x6f, 0x23, 0x7e, 0x31, - 0xd6, 0xdb, 0x18, 0x18, 0x43, 0x5f, 0x1c, 0x67, 0x1c, 0x2d, 0x34, 0xf2, - 0xfd, 0x87, 0xf5, 0xfb, 0x8d, 0xdf, 0x67, 0xc0, 0x9b, 0xd7, 0x88, 0xcf, - 0x32, 0xbe, 0x18, 0xf7, 0x87, 0xd8, 0xee, 0xdb, 0xb0, 0xdb, 0xd0, 0x76, - 0x0f, 0x98, 0x76, 0xeb, 0xfb, 0x95, 0x55, 0x4e, 0xb1, 0xc4, 0xad, 0xa2, - 0xab, 0x8c, 0x2b, 0x54, 0xcf, 0x0a, 0xd8, 0x4e, 0xc9, 0xd7, 0xa6, 0xec, - 0x09, 0xb1, 0x3d, 0x41, 0x71, 0xb0, 0xc5, 0xba, 0x2f, 0xc0, 0xfb, 0xfc, - 0x72, 0x1f, 0xe6, 0x51, 0x17, 0x8c, 0x15, 0xfc, 0xa9, 0xfc, 0xa6, 0xe5, - 0x66, 0xe7, 0xbd, 0xd5, 0x7f, 0x74, 0x23, 0xa5, 0x0f, 0xea, 0x9b, 0x8c, - 0x53, 0x33, 0xfe, 0x3f, 0xd0, 0xf5, 0xed, 0x2e, 0xdd, 0x5f, 0xfd, 0x67, - 0x86, 0x51, 0x9f, 0xce, 0x0c, 0x9f, 0xe5, 0x77, 0x07, 0xfb, 0xa5, 0x9b, - 0xfe, 0xb7, 0x90, 0xb1, 0xab, 0xb3, 0xd7, 0x37, 0xbb, 0x1e, 0x55, 0x16, - 0x3d, 0xf4, 0xb9, 0xff, 0x00, 0x0e, 0x4b, 0x7c, 0x26, 0x30, 0x14, 0x00, + 0x13, 0x8b, 0xdc, 0x27, 0x4a, 0xc5, 0xc5, 0x14, 0xec, 0x9a, 0x4d, 0xe5, + 0xe2, 0x4f, 0x9f, 0xa7, 0xe5, 0x41, 0x6f, 0x6d, 0x47, 0x56, 0x3e, 0xce, + 0x3f, 0xc0, 0x7a, 0xfe, 0x4c, 0xf7, 0xd8, 0x30, 0xdb, 0xa3, 0xe4, 0x62, + 0x7e, 0x3b, 0xf7, 0xe7, 0x84, 0x39, 0xb6, 0xf7, 0xd5, 0x1e, 0xd2, 0xab, + 0x84, 0xf1, 0x16, 0xb6, 0xe4, 0x03, 0xf8, 0xcb, 0xda, 0x40, 0x27, 0xdb, + 0x74, 0x1c, 0x74, 0xbc, 0x74, 0x7c, 0x10, 0xc7, 0xf0, 0x3a, 0x62, 0xeb, + 0xe8, 0x5f, 0x47, 0x7d, 0xa4, 0xad, 0x7f, 0x41, 0xe3, 0x0f, 0xfb, 0x77, + 0x47, 0x14, 0xff, 0xeb, 0xe2, 0x2a, 0xe1, 0x50, 0x88, 0x1f, 0x98, 0x66, + 0xfb, 0x15, 0x07, 0xc0, 0xcc, 0x57, 0x8e, 0x5f, 0x01, 0x4f, 0xb7, 0xeb, + 0x7a, 0xae, 0xe3, 0x65, 0xcd, 0xd7, 0xd8, 0x32, 0xdc, 0x66, 0xeb, 0xb2, + 0xb6, 0x53, 0xf1, 0x47, 0x18, 0x8f, 0x3e, 0xd1, 0xb5, 0x0d, 0xf7, 0xdc, + 0xa0, 0x17, 0x75, 0x3f, 0xe8, 0xb5, 0xc6, 0x4b, 0xe2, 0xa2, 0xd0, 0xab, + 0x86, 0x35, 0x25, 0x85, 0x64, 0xcf, 0xa9, 0x4b, 0xdf, 0xd2, 0xf2, 0xfb, + 0xd3, 0x45, 0x98, 0x2f, 0xdf, 0x19, 0x22, 0x7f, 0x4c, 0x01, 0xcf, 0xef, + 0x4e, 0x82, 0xbe, 0x23, 0x5e, 0xc0, 0xfe, 0x92, 0x13, 0x74, 0x0f, 0xf4, + 0x95, 0x33, 0x3e, 0x2b, 0x50, 0x27, 0x92, 0xd3, 0x74, 0x2f, 0x59, 0x5a, + 0x12, 0x01, 0x45, 0x3d, 0x66, 0xbf, 0x01, 0x3e, 0xdd, 0x96, 0x38, 0x3f, + 0x08, 0xaf, 0x74, 0xaf, 0x94, 0x78, 0xc4, 0x76, 0xc6, 0xad, 0x2f, 0x17, + 0xb7, 0xda, 0x1f, 0x15, 0xce, 0xbc, 0x38, 0xdd, 0x60, 0xc7, 0xa9, 0x87, + 0x71, 0x7a, 0xcf, 0xec, 0xef, 0xcb, 0xe5, 0xa2, 0xcf, 0x5f, 0xfc, 0xdf, + 0x70, 0x0b, 0xba, 0xbd, 0x41, 0x9d, 0x5f, 0xbe, 0xac, 0x1e, 0xd7, 0xda, + 0xe2, 0xdc, 0x7c, 0x5f, 0xeb, 0x75, 0xc2, 0x63, 0x5d, 0x6f, 0x31, 0xfb, + 0xd9, 0x11, 0x7e, 0xe7, 0x65, 0x0c, 0xfa, 0x11, 0xbd, 0x93, 0xa4, 0xa1, + 0x51, 0x79, 0x56, 0xf1, 0x35, 0x45, 0x8f, 0x70, 0xbd, 0xbd, 0xe4, 0x42, + 0xbd, 0x19, 0x38, 0x80, 0xf1, 0x65, 0xae, 0x1f, 0x77, 0xd7, 0x50, 0x5d, + 0x8e, 0x1e, 0x39, 0xaf, 0xe5, 0x91, 0x1c, 0x23, 0xc3, 0x75, 0xfd, 0x79, + 0x17, 0xd7, 0x5b, 0xf2, 0x9b, 0x3b, 0xfa, 0x07, 0xdd, 0x67, 0xdc, 0xa2, + 0xeb, 0x49, 0x45, 0x2b, 0x65, 0xfd, 0xe6, 0xf3, 0x9f, 0x01, 0xed, 0xf5, + 0x82, 0x8a, 0x66, 0x7b, 0x3c, 0x84, 0x69, 0x17, 0x46, 0x9e, 0x7a, 0x96, + 0xd3, 0x87, 0xb1, 0x97, 0xef, 0x65, 0xd3, 0xec, 0xa7, 0x20, 0xf9, 0xa3, + 0x58, 0xda, 0xa9, 0x68, 0x28, 0x3a, 0x9a, 0x86, 0xfe, 0x43, 0x5b, 0x61, + 0xdf, 0x22, 0xdb, 0xcd, 0x34, 0xf8, 0xf6, 0x18, 0xe1, 0x2f, 0x38, 0x8e, + 0x77, 0x48, 0xd0, 0x33, 0x06, 0x3b, 0x86, 0x32, 0x18, 0x2f, 0x6e, 0x06, + 0xfd, 0x6b, 0x0b, 0xf6, 0x1d, 0x3d, 0xce, 0xfe, 0xd8, 0x9a, 0x7f, 0xdf, + 0xc0, 0x3d, 0xf0, 0x0d, 0x37, 0xa9, 0xf3, 0x07, 0x67, 0xf8, 0xfd, 0x22, + 0xe2, 0x2e, 0x35, 0x8e, 0x1b, 0x19, 0x1e, 0x1f, 0xe2, 0xfa, 0x7e, 0x9b, + 0xdf, 0x1b, 0x43, 0x39, 0xef, 0x8d, 0x79, 0xdc, 0x33, 0x67, 0x32, 0x49, + 0xe0, 0x22, 0x51, 0x98, 0xfb, 0x5e, 0x55, 0xe3, 0x9a, 0x68, 0x39, 0xc7, + 0xa9, 0x6c, 0x3d, 0xe8, 0xe4, 0x7a, 0xbc, 0x13, 0x86, 0x8e, 0xb1, 0x5f, + 0x3a, 0x28, 0x4e, 0xad, 0x0b, 0xe9, 0x95, 0xde, 0xc9, 0xe0, 0x9b, 0xe2, + 0x73, 0xc3, 0xdc, 0x4f, 0xc2, 0xc8, 0x3f, 0x51, 0x91, 0xe4, 0x77, 0xcb, + 0x04, 0xee, 0x9d, 0x53, 0x06, 0x68, 0x38, 0xa0, 0xf5, 0x45, 0x3e, 0x26, + 0x52, 0xc8, 0x3b, 0xac, 0x3b, 0x2c, 0xeb, 0x7c, 0x1f, 0x59, 0xf6, 0xce, + 0x51, 0x74, 0xd1, 0x51, 0xea, 0xd0, 0x76, 0x62, 0xb5, 0x3f, 0xa0, 0xf0, + 0x7b, 0xd3, 0xcc, 0xab, 0x79, 0xf2, 0x5b, 0xf5, 0x4c, 0x86, 0xf4, 0xaf, + 0x12, 0xa5, 0xd4, 0x87, 0x2b, 0x83, 0x0b, 0xf0, 0x63, 0x74, 0x9a, 0xfd, + 0x3f, 0xb2, 0x09, 0xf4, 0x18, 0xe3, 0x4f, 0xe3, 0xea, 0xca, 0x46, 0x83, + 0xf6, 0xcd, 0x8d, 0xe2, 0x1c, 0x7d, 0x8f, 0xc8, 0x7d, 0x8f, 0x6b, 0x3c, + 0x56, 0xb6, 0xa3, 0x90, 0x0e, 0x1c, 0x55, 0xe7, 0x04, 0x24, 0x8e, 0x94, + 0xfe, 0xd2, 0x27, 0x9c, 0x8f, 0x76, 0x9c, 0x2a, 0x1c, 0xeb, 0xfc, 0xb0, + 0xe2, 0x3b, 0x37, 0xdf, 0xb3, 0x78, 0x0d, 0xd2, 0xbd, 0x5c, 0x16, 0xb9, + 0x04, 0xbf, 0x9b, 0xf8, 0x7e, 0xb0, 0x52, 0xfc, 0xde, 0x46, 0xfc, 0xa2, + 0xac, 0xb7, 0x11, 0x1f, 0x43, 0x5f, 0x1c, 0x67, 0x1c, 0xcd, 0x37, 0xf1, + 0xfd, 0x87, 0xf5, 0xfb, 0x8d, 0xdf, 0x67, 0xc0, 0x9b, 0xd7, 0x88, 0xa5, + 0x19, 0x5f, 0x8c, 0xfb, 0x43, 0x6c, 0xf7, 0x6d, 0xd8, 0x6d, 0x68, 0xbb, + 0xe3, 0xa6, 0xdd, 0xfa, 0x7e, 0x65, 0x95, 0x53, 0x22, 0x71, 0xab, 0xe8, + 0x2a, 0xe3, 0x0a, 0xd5, 0xb3, 0x02, 0xb6, 0x53, 0xf2, 0xb5, 0x2b, 0x7b, + 0x82, 0x6c, 0x4f, 0x40, 0x1c, 0x6c, 0xb5, 0xee, 0x2b, 0xe2, 0x7d, 0x7e, + 0xb9, 0x0f, 0xf3, 0xa8, 0x0b, 0xc6, 0x0a, 0xfe, 0x54, 0x7e, 0xd3, 0x72, + 0x73, 0xf3, 0xde, 0xea, 0x3f, 0xba, 0x91, 0xd2, 0x07, 0xf5, 0x4d, 0xc6, + 0xa9, 0x05, 0xff, 0x1f, 0xe8, 0xfa, 0x76, 0x97, 0xee, 0xaf, 0xfe, 0x33, + 0xc3, 0xa8, 0x4f, 0x67, 0x86, 0xcf, 0xf2, 0xbb, 0x83, 0xfd, 0xd2, 0x43, + 0xff, 0x5b, 0xc8, 0xd8, 0xd5, 0xdb, 0xeb, 0x9b, 0x5d, 0x8f, 0x6a, 0x8b, + 0x1e, 0xfa, 0xdc, 0x7f, 0x00, 0x5a, 0x33, 0xe6, 0xc0, 0x30, 0x14, 0x00, 0x00, 0x00 }; static u8 bnx2_TPAT_b09FwText[] = { diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 6ef6b8b..f651a81 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -508,7 +508,7 @@ static int __init macvlan_init_module(void) goto err1; return 0; err1: - macvlan_handle_frame_hook = macvlan_handle_frame; + macvlan_handle_frame_hook = NULL; unregister_netdevice_notifier(&macvlan_notifier_block); return err; } diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 569028b..6f245cf 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -33,8 +33,7 @@ #include <linux/mii.h> #include <linux/usb.h> #include <linux/crc32.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> #define DRIVER_VERSION "14-Jun-2006" static const char driver_name [] = "asix"; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index a42acc3..a934428 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -31,8 +31,7 @@ #include <linux/mii.h> #include <linux/usb.h> #include <linux/usb/cdc.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> #if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) @@ -228,15 +227,16 @@ next_desc: buf += buf [0]; } - /* Microsoft ActiveSync based RNDIS devices lack the CDC descriptors, - * so we'll hard-wire the interfaces and not check for descriptors. + /* Microsoft ActiveSync based and some regular RNDIS devices lack the + * CDC descriptors, so we'll hard-wire the interfaces and not check + * for descriptors. */ - if (is_activesync(&intf->cur_altsetting->desc) && !info->u) { + if (rndis && !info->u) { info->control = usb_ifnum_to_if(dev->udev, 0); info->data = usb_ifnum_to_if(dev->udev, 1); if (!info->control || !info->data) { dev_dbg(&intf->dev, - "activesync: master #0/%p slave #1/%p\n", + "rndis: master #0/%p slave #1/%p\n", info->control, info->data); goto bad_desc; @@ -316,7 +316,6 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); - /*------------------------------------------------------------------------- * * Communications Device Class, Ethernet Control model diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c index 943988e..0ec7936 100644 --- a/drivers/net/usb/cdc_subset.c +++ b/drivers/net/usb/cdc_subset.c @@ -26,8 +26,7 @@ #include <linux/workqueue.h> #include <linux/mii.h> #include <linux/usb.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> /* diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 633a511..4b131a6 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -20,8 +20,7 @@ #include <linux/mii.h> #include <linux/usb.h> #include <linux/crc32.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> /* datasheet: http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c index 031cf5c..f7ccfad 100644 --- a/drivers/net/usb/gl620a.c +++ b/drivers/net/usb/gl620a.c @@ -29,8 +29,7 @@ #include <linux/workqueue.h> #include <linux/mii.h> #include <linux/usb.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> /* diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 5ea7411e..c3d119f 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -31,8 +31,7 @@ #include <linux/module.h> #include <linux/netdevice.h> #include <linux/usb.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> /* requests */ #define MCS7830_RD_BMREQ (USB_DIR_IN | USB_TYPE_VENDOR | \ diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 19bf8da..034e8a7 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -28,11 +28,10 @@ #include <linux/workqueue.h> #include <linux/mii.h> #include <linux/usb.h> +#include <linux/usb/usbnet.h> #include <asm/unaligned.h> -#include "usbnet.h" - /* * Netchip 1080 driver ... http://www.netchip.com diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 4530093..08555f8 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -28,8 +28,7 @@ #include <linux/workqueue.h> #include <linux/mii.h> #include <linux/usb.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> /* diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 1ebe325..a613247 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -29,8 +29,8 @@ #include <linux/mii.h> #include <linux/usb.h> #include <linux/usb/cdc.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> +#include <linux/usb/rndis_host.h> /* @@ -56,217 +56,17 @@ */ /* - * CONTROL uses CDC "encapsulated commands" with funky notifications. - * - control-out: SEND_ENCAPSULATED - * - interrupt-in: RESPONSE_AVAILABLE - * - control-in: GET_ENCAPSULATED - * - * We'll try to ignore the RESPONSE_AVAILABLE notifications. - * - * REVISIT some RNDIS implementations seem to have curious issues still - * to be resolved. - */ -struct rndis_msg_hdr { - __le32 msg_type; /* RNDIS_MSG_* */ - __le32 msg_len; - // followed by data that varies between messages - __le32 request_id; - __le32 status; - // ... and more -} __attribute__ ((packed)); - -/* MS-Windows uses this strange size, but RNDIS spec says 1024 minimum */ -#define CONTROL_BUFFER_SIZE 1025 - -/* RNDIS defines an (absurdly huge) 10 second control timeout, - * but ActiveSync seems to use a more usual 5 second timeout - * (which matches the USB 2.0 spec). - */ -#define RNDIS_CONTROL_TIMEOUT_MS (5 * 1000) - - -#define ccpu2 __constant_cpu_to_le32 - -#define RNDIS_MSG_COMPLETION ccpu2(0x80000000) - -/* codes for "msg_type" field of rndis messages; - * only the data channel uses packet messages (maybe batched); - * everything else goes on the control channel. - */ -#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */ -#define RNDIS_MSG_INIT ccpu2(0x00000002) -#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_HALT ccpu2(0x00000003) -#define RNDIS_MSG_QUERY ccpu2(0x00000004) -#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_SET ccpu2(0x00000005) -#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_RESET ccpu2(0x00000006) -#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_INDICATE ccpu2(0x00000007) -#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008) -#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION) - -/* codes for "status" field of completion messages */ -#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000) -#define RNDIS_STATUS_FAILURE ccpu2(0xc0000001) -#define RNDIS_STATUS_INVALID_DATA ccpu2(0xc0010015) -#define RNDIS_STATUS_NOT_SUPPORTED ccpu2(0xc00000bb) -#define RNDIS_STATUS_MEDIA_CONNECT ccpu2(0x4001000b) -#define RNDIS_STATUS_MEDIA_DISCONNECT ccpu2(0x4001000c) - - -struct rndis_data_hdr { - __le32 msg_type; /* RNDIS_MSG_PACKET */ - __le32 msg_len; // rndis_data_hdr + data_len + pad - __le32 data_offset; // 36 -- right after header - __le32 data_len; // ... real packet size - - __le32 oob_data_offset; // zero - __le32 oob_data_len; // zero - __le32 num_oob; // zero - __le32 packet_data_offset; // zero - - __le32 packet_data_len; // zero - __le32 vc_handle; // zero - __le32 reserved; // zero -} __attribute__ ((packed)); - -struct rndis_init { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_INIT */ - __le32 msg_len; // 24 - __le32 request_id; - __le32 major_version; // of rndis (1.0) - __le32 minor_version; - __le32 max_transfer_size; -} __attribute__ ((packed)); - -struct rndis_init_c { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_INIT_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; - __le32 major_version; // of rndis (1.0) - __le32 minor_version; - __le32 device_flags; - __le32 medium; // zero == 802.3 - __le32 max_packets_per_message; - __le32 max_transfer_size; - __le32 packet_alignment; // max 7; (1<<n) bytes - __le32 af_list_offset; // zero - __le32 af_list_size; // zero -} __attribute__ ((packed)); - -struct rndis_halt { /* OUT (no reply) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_HALT */ - __le32 msg_len; - __le32 request_id; -} __attribute__ ((packed)); - -struct rndis_query { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_QUERY */ - __le32 msg_len; - __le32 request_id; - __le32 oid; - __le32 len; - __le32 offset; -/*?*/ __le32 handle; // zero -} __attribute__ ((packed)); - -struct rndis_query_c { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_QUERY_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; - __le32 len; - __le32 offset; -} __attribute__ ((packed)); - -struct rndis_set { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_SET */ - __le32 msg_len; - __le32 request_id; - __le32 oid; - __le32 len; - __le32 offset; -/*?*/ __le32 handle; // zero -} __attribute__ ((packed)); - -struct rndis_set_c { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_SET_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; -} __attribute__ ((packed)); - -struct rndis_reset { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_RESET */ - __le32 msg_len; - __le32 reserved; -} __attribute__ ((packed)); - -struct rndis_reset_c { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_RESET_C */ - __le32 msg_len; - __le32 status; - __le32 addressing_lost; -} __attribute__ ((packed)); - -struct rndis_indicate { /* IN (unrequested) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_INDICATE */ - __le32 msg_len; - __le32 status; - __le32 length; - __le32 offset; -/**/ __le32 diag_status; - __le32 error_offset; -/**/ __le32 message; -} __attribute__ ((packed)); - -struct rndis_keepalive { /* OUT (optionally IN) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_KEEPALIVE */ - __le32 msg_len; - __le32 request_id; -} __attribute__ ((packed)); - -struct rndis_keepalive_c { /* IN (optionally OUT) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_KEEPALIVE_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; -} __attribute__ ((packed)); - -/* NOTE: about 30 OIDs are "mandatory" for peripherals to support ... and - * there are gobs more that may optionally be supported. We'll avoid as much - * of that mess as possible. - */ -#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101) -#define OID_GEN_MAXIMUM_FRAME_SIZE ccpu2(0x00010106) -#define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e) - -/* * RNDIS notifications from device: command completion; "reverse" * keepalives; etc */ -static void rndis_status(struct usbnet *dev, struct urb *urb) +void rndis_status(struct usbnet *dev, struct urb *urb) { devdbg(dev, "rndis status urb, len %d stat %d", urb->actual_length, urb->status); // FIXME for keepalives, respond immediately (asynchronously) // if not an RNDIS status, do like cdc_status(dev,urb) does } +EXPORT_SYMBOL_GPL(rndis_status); /* * RPC done RNDIS-style. Caller guarantees: @@ -278,7 +78,7 @@ static void rndis_status(struct usbnet *dev, struct urb *urb) * Call context is likely probe(), before interface name is known, * which is why we won't try to use it in the diagnostics. */ -static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) +int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) { struct cdc_state *info = (void *) &dev->data; int master_ifnum; @@ -347,10 +147,26 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) request_id, xid); /* then likely retry */ } else switch (buf->msg_type) { - case RNDIS_MSG_INDICATE: { /* fault */ - // struct rndis_indicate *msg = (void *)buf; - dev_info(&info->control->dev, - "rndis fault indication\n"); + case RNDIS_MSG_INDICATE: { /* fault/event */ + struct rndis_indicate *msg = (void *)buf; + int state = 0; + + switch (msg->status) { + case RNDIS_STATUS_MEDIA_CONNECT: + state = 1; + case RNDIS_STATUS_MEDIA_DISCONNECT: + dev_info(&info->control->dev, + "rndis media %sconnect\n", + !state?"dis":""); + if (dev->driver_info->link_change) + dev->driver_info->link_change( + dev, state); + break; + default: + dev_info(&info->control->dev, + "rndis indication: 0x%08x\n", + le32_to_cpu(msg->status)); + } } break; case RNDIS_MSG_KEEPALIVE: { /* ping */ @@ -387,6 +203,7 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) dev_dbg(&info->control->dev, "rndis response timeout\n"); return -ETIMEDOUT; } +EXPORT_SYMBOL_GPL(rndis_command); /* * rndis_query: @@ -453,7 +270,8 @@ response_error: return -EDOM; } -static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) +int +generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) { int retval; struct net_device *net = dev->net; @@ -467,8 +285,9 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) struct rndis_query_c *get_c; struct rndis_set *set; struct rndis_set_c *set_c; + struct rndis_halt *halt; } u; - u32 tmp; + u32 tmp, *phym; int reply_len; unsigned char *bp; @@ -517,7 +336,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) "dev can't take %u byte packets (max %u)\n", dev->hard_mtu, tmp); retval = -EINVAL; - goto fail_and_release; + goto halt_fail_and_release; } dev->hard_mtu = tmp; net->mtu = dev->hard_mtu - net->hard_header_len; @@ -533,13 +352,43 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) dev->hard_mtu, tmp, dev->rx_urb_size, 1 << le32_to_cpu(u.init_c->packet_alignment)); + /* module has some device initialization code needs to be done right + * after RNDIS_INIT */ + if (dev->driver_info->early_init && + dev->driver_info->early_init(dev) != 0) + goto halt_fail_and_release; + + /* Check physical medium */ + reply_len = sizeof *phym; + retval = rndis_query(dev, intf, u.buf, OID_GEN_PHYSICAL_MEDIUM, + 0, (void **) &phym, &reply_len); + if (retval != 0) + /* OID is optional so don't fail here. */ + *phym = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED; + if ((flags & FLAG_RNDIS_PHYM_WIRELESS) && + *phym != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) { + if (netif_msg_probe(dev)) + dev_dbg(&intf->dev, "driver requires wireless " + "physical medium, but device is not.\n"); + retval = -ENODEV; + goto halt_fail_and_release; + } + if ((flags & FLAG_RNDIS_PHYM_NOT_WIRELESS) && + *phym == RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) { + if (netif_msg_probe(dev)) + dev_dbg(&intf->dev, "driver requires non-wireless " + "physical medium, but device is wireless.\n"); + retval = -ENODEV; + goto halt_fail_and_release; + } + /* Get designated host ethernet address */ reply_len = ETH_ALEN; retval = rndis_query(dev, intf, u.buf, OID_802_3_PERMANENT_ADDRESS, 48, (void **) &bp, &reply_len); if (unlikely(retval< 0)) { dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval); - goto fail_and_release; + goto halt_fail_and_release; } memcpy(net->dev_addr, bp, ETH_ALEN); @@ -550,12 +399,12 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) u.set->oid = OID_GEN_CURRENT_PACKET_FILTER; u.set->len = ccpu2(4); u.set->offset = ccpu2((sizeof *u.set) - 8); - *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER); + *(__le32 *)(u.buf + sizeof *u.set) = RNDIS_DEFAULT_FILTER; retval = rndis_command(dev, u.header); if (unlikely(retval < 0)) { dev_err(&intf->dev, "rndis set packet filter, %d\n", retval); - goto fail_and_release; + goto halt_fail_and_release; } retval = 0; @@ -563,6 +412,11 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) kfree(u.buf); return retval; +halt_fail_and_release: + memset(u.halt, 0, sizeof *u.halt); + u.halt->msg_type = RNDIS_MSG_HALT; + u.halt->msg_len = ccpu2(sizeof *u.halt); + (void) rndis_command(dev, (void *)u.halt); fail_and_release: usb_set_intfdata(info->data, NULL); usb_driver_release_interface(driver_of(intf), info->data); @@ -571,13 +425,19 @@ fail: kfree(u.buf); return retval; } +EXPORT_SYMBOL_GPL(generic_rndis_bind); + +static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) +{ + return generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_NOT_WIRELESS); +} -static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) +void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) { struct rndis_halt *halt; /* try to clear any rndis state/activity (no i/o from stack!) */ - halt = kzalloc(sizeof *halt, GFP_KERNEL); + halt = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL); if (halt) { halt->msg_type = RNDIS_MSG_HALT; halt->msg_len = ccpu2(sizeof *halt); @@ -585,13 +445,14 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) kfree(halt); } - return usbnet_cdc_unbind(dev, intf); + usbnet_cdc_unbind(dev, intf); } +EXPORT_SYMBOL_GPL(rndis_unbind); /* * DATA -- host must not write zlps */ -static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { /* peripheral may have batched packets to us... */ while (likely(skb->len)) { @@ -633,8 +494,9 @@ static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* caller will usbnet_skb_return the remaining packet */ return 1; } +EXPORT_SYMBOL_GPL(rndis_rx_fixup); -static struct sk_buff * +struct sk_buff * rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { struct rndis_data_hdr *hdr; @@ -679,6 +541,7 @@ fill: /* FIXME make the last packet always be short ... */ return skb; } +EXPORT_SYMBOL_GPL(rndis_tx_fixup); static const struct driver_info rndis_info = { diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8ed1fc5..8463efb 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -41,8 +41,7 @@ #include <linux/workqueue.h> #include <linux/mii.h> #include <linux/usb.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> #define DRIVER_VERSION "22-Aug-2005" @@ -1204,6 +1203,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if ((dev->driver_info->flags & FLAG_ETHER) != 0 && (net->dev_addr [0] & 0x02) == 0) strcpy (net->name, "eth%d"); + /* WLAN devices should always be named "wlan%d" */ + if ((dev->driver_info->flags & FLAG_WLAN) != 0) + strcpy(net->name, "wlan%d"); /* maybe the remote can't receive an Ethernet MTU */ if (net->mtu > (dev->hard_mtu - net->hard_header_len)) diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index 9f98e8c..e24f7b3 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -29,8 +29,7 @@ #include <linux/crc32.h> #include <linux/usb.h> #include <linux/usb/cdc.h> - -#include "usbnet.h" +#include <linux/usb/usbnet.h> /* diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index f372960..714a6ca 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -545,6 +545,34 @@ config USB_ZD1201 To compile this driver as a module, choose M here: the module will be called zd1201. +config USB_NET_RNDIS_WLAN + tristate "Wireless RNDIS USB support" + depends on USB && WLAN_80211 && EXPERIMENTAL + select USB_USBNET + select USB_NET_CDCETHER + select USB_NET_RNDIS_HOST + select WIRELESS_EXT + ---help--- + This is a driver for wireless RNDIS devices. + These are USB based adapters found in devices such as: + + Buffalo WLI-U2-KG125S + U.S. Robotics USR5421 + Belkin F5D7051 + Linksys WUSB54GSv2 + Linksys WUSB54GSC + Asus WL169gE + Eminent EM4045 + BT Voyager 1055 + Linksys WUSB54GSv1 + U.S. Robotics USR5420 + BUFFALO WLI-USB-G54 + + All of these devices are based on Broadcom 4320 chip which is the + only wireless RNDIS chip known to date. + + If you choose to build a module, it'll be called rndis_wlan. + config RTL8180 tristate "Realtek 8180/8185 PCI support" depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 6af7b15..091dfe2 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -44,6 +44,8 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw/ obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o +obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o + obj-$(CONFIG_USB_ZD1201) += zd1201.o obj-$(CONFIG_LIBERTAS) += libertas/ diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 72bcf32..d6599d2 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1980,7 +1980,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) struct ath5k_buf *bf = sc->bbuf; struct ath5k_hw *ah = sc->ah; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "in beacon_send\n"); + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA || sc->opmode == IEEE80211_IF_TYPE_MNTR)) { @@ -1996,10 +1996,10 @@ ath5k_beacon_send(struct ath5k_softc *sc) */ if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) { sc->bmisscount++; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "missed %u consecutive beacons\n", sc->bmisscount); if (sc->bmisscount > 3) { /* NB: 3 is a guess */ - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "stuck beacon time (%u missed)\n", sc->bmisscount); tasklet_schedule(&sc->restq); @@ -2007,7 +2007,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) return; } if (unlikely(sc->bmisscount != 0)) { - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "resume beacon xmit after %u misses\n", sc->bmisscount); sc->bmisscount = 0; @@ -2027,7 +2027,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr); ath5k_hw_tx_start(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "TXDP[%u] = %llx (%p)\n", + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", sc->bhalq, (unsigned long long)bf->daddr, bf->desc); sc->bsent++; diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 4ba649e..bb581ef 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com> + * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com> * * This file is free software: you may copy, redistribute and/or modify it * under the terms of the GNU General Public License as published by the @@ -200,7 +200,7 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf, { struct ath5k_softc *sc = file->private_data; char buf[100]; - snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); + snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); return simple_read_from_buffer(user_buf, count, ppos, buf, 19); } @@ -209,7 +209,12 @@ static ssize_t write_file_tsf(struct file *file, size_t count, loff_t *ppos) { struct ath5k_softc *sc = file->private_data; - if (strncmp(userbuf, "reset", 5) == 0) { + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "reset", 5) == 0) { ath5k_hw_reset_tsf(sc->ah); printk(KERN_INFO "debugfs reset TSF\n"); } @@ -231,8 +236,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, { struct ath5k_softc *sc = file->private_data; struct ath5k_hw *ah = sc->ah; - char buf[1000]; - int len = 0; + char buf[500]; + unsigned int len = 0; unsigned int v; u64 tsf; @@ -277,11 +282,15 @@ static ssize_t write_file_beacon(struct file *file, { struct ath5k_softc *sc = file->private_data; struct ath5k_hw *ah = sc->ah; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; - if (strncmp(userbuf, "disable", 7) == 0) { + if (strncmp(buf, "disable", 7) == 0) { AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); printk(KERN_INFO "debugfs disable beacons\n"); - } else if (strncmp(userbuf, "enable", 6) == 0) { + } else if (strncmp(buf, "enable", 6) == 0) { AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); printk(KERN_INFO "debugfs enable beacons\n"); } @@ -314,6 +323,82 @@ static const struct file_operations fops_reset = { }; +/* debugfs: debug level */ + +static struct { + enum ath5k_debug_level level; + const char *name; + const char *desc; +} dbg_info[] = { + { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, + { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, + { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, + { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, + { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, + { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, + { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, + { ATH5K_DEBUG_LED, "led", "LED mamagement" }, + { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, + { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, + { ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" }, + { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, + { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, +}; + +static ssize_t read_file_debug(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[700]; + unsigned int len = 0; + unsigned int i; + + len += snprintf(buf+len, sizeof(buf)-len, + "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); + + for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level & dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + } + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level == dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_debug(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + unsigned int i; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { + if (strncmp(buf, dbg_info[i].name, + strlen(dbg_info[i].name)) == 0) { + sc->debug.level ^= dbg_info[i].level; /* toggle bit */ + break; + } + } + return count; +} + +static const struct file_operations fops_debug = { + .read = read_file_debug, + .write = write_file_debug, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + /* init */ void @@ -326,26 +411,24 @@ void ath5k_debug_init_device(struct ath5k_softc *sc) { sc->debug.level = ath5k_debug; + sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath5k_global_debugfs); - sc->debug.debugfs_debug = debugfs_create_u32("debug", - 0666, sc->debug.debugfs_phydir, &sc->debug.level); + ath5k_global_debugfs); + + sc->debug.debugfs_debug = debugfs_create_file("debug", 0666, + sc->debug.debugfs_phydir, sc, &fops_debug); sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, - sc->debug.debugfs_phydir, - sc, &fops_registers); + sc->debug.debugfs_phydir, sc, &fops_registers); sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, - sc->debug.debugfs_phydir, - sc, &fops_tsf); + sc->debug.debugfs_phydir, sc, &fops_tsf); sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, - sc->debug.debugfs_phydir, - sc, &fops_beacon); + sc->debug.debugfs_phydir, sc, &fops_beacon); sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, - sc->debug.debugfs_phydir, - sc, &fops_reset); + sc->debug.debugfs_phydir, sc, &fops_reset); } void @@ -415,8 +498,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) struct ath5k_buf *bf; int status; - if (likely(!(sc->debug.level & - (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL)))) + if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) return; printk(KERN_DEBUG "rx queue %x, link %p\n", @@ -426,7 +508,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) list_for_each_entry(bf, &sc->rxbuf, list) { ds = bf->desc; status = ah->ah_proc_rx_desc(ah, ds); - if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL)) + if (!status) ath5k_debug_printrxbuf(bf, status == 0); } spin_unlock_bh(&sc->rxbuflock); diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index 2b491cb..c4fd8c4 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -91,7 +91,6 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_MODE: mode init/setup * @ATH5K_DEBUG_XMIT: basic xmit operation * @ATH5K_DEBUG_BEACON: beacon handling - * @ATH5K_DEBUG_BEACON_PROC: beacon ISR proc * @ATH5K_DEBUG_CALIBRATE: periodic calibration * @ATH5K_DEBUG_TXPOWER: transmit power setting * @ATH5K_DEBUG_LED: led management @@ -99,7 +98,6 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_DUMP_TX: print transmit skb content * @ATH5K_DEBUG_DUMPMODES: dump modes * @ATH5K_DEBUG_TRACE: trace function calls - * @ATH5K_DEBUG_FATAL: fatal errors * @ATH5K_DEBUG_ANY: show at any debug level * * The debug level is used to control the amount and type of debugging output @@ -115,15 +113,13 @@ enum ath5k_debug_level { ATH5K_DEBUG_MODE = 0x00000004, ATH5K_DEBUG_XMIT = 0x00000008, ATH5K_DEBUG_BEACON = 0x00000010, - ATH5K_DEBUG_BEACON_PROC = 0x00000020, - ATH5K_DEBUG_CALIBRATE = 0x00000100, - ATH5K_DEBUG_TXPOWER = 0x00000200, - ATH5K_DEBUG_LED = 0x00000400, - ATH5K_DEBUG_DUMP_RX = 0x00001000, - ATH5K_DEBUG_DUMP_TX = 0x00002000, - ATH5K_DEBUG_DUMPMODES = 0x00004000, - ATH5K_DEBUG_TRACE = 0x00010000, - ATH5K_DEBUG_FATAL = 0x80000000, + ATH5K_DEBUG_CALIBRATE = 0x00000020, + ATH5K_DEBUG_TXPOWER = 0x00000040, + ATH5K_DEBUG_LED = 0x00000080, + ATH5K_DEBUG_DUMP_RX = 0x00000100, + ATH5K_DEBUG_DUMP_TX = 0x00000200, + ATH5K_DEBUG_DUMPMODES = 0x00000400, + ATH5K_DEBUG_TRACE = 0x00001000, ATH5K_DEBUG_ANY = 0xffffffff }; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3e73d2a..8a708b7 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1114,7 +1114,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, { const struct b43_dma_ops *ops = ring->ops; u8 *header; - int slot; + int slot, old_top_slot, old_used_slots; int err; struct b43_dmadesc_generic *desc; struct b43_dmadesc_meta *meta; @@ -1126,6 +1126,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring, #define SLOTS_PER_PACKET 2 B43_WARN_ON(skb_shinfo(skb)->nr_frags); + old_top_slot = ring->current_slot; + old_used_slots = ring->used_slots; + /* Get a slot for the header. */ slot = request_slot(ring); desc = ops->idx2desc(ring, slot, &meta_hdr); @@ -1133,13 +1136,21 @@ static int dma_tx_fragment(struct b43_dmaring *ring, header = &(ring->txhdr_cache[slot * hdrsize]); cookie = generate_cookie(ring, slot); - b43_generate_txhdr(ring->dev, header, - skb->data, skb->len, ctl, cookie); + err = b43_generate_txhdr(ring->dev, header, + skb->data, skb->len, ctl, cookie); + if (unlikely(err)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; + return err; + } meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, hdrsize, 1); - if (dma_mapping_error(meta_hdr->dmaaddr)) + if (dma_mapping_error(meta_hdr->dmaaddr)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; return -EIO; + } ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, hdrsize, 1, 0, 0); @@ -1157,6 +1168,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, if (dma_mapping_error(meta->dmaaddr)) { bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; err = -ENOMEM; goto out_unmap_hdr; } @@ -1167,6 +1180,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (dma_mapping_error(meta->dmaaddr)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; err = -EIO; goto out_free_bounce; } @@ -1252,6 +1267,13 @@ int b43_dma_tx(struct b43_wldev *dev, B43_WARN_ON(ring->stopped); err = dma_tx_fragment(ring, skb, ctl); + if (unlikely(err == -ENOKEY)) { + /* Drop this packet, as we don't have the encryption key + * anymore and must not transmit it unencrypted. */ + dev_kfree_skb_any(skb); + err = 0; + goto out_unlock; + } if (unlikely(err)) { b43err(dev->wl, "DMA tx mapping failure\n"); goto out_unlock; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 88d2c15..64c154d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3532,8 +3532,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_bluetooth_coext_enable(dev); ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ - memset(wl->bssid, 0, ETH_ALEN); - memset(wl->mac_addr, 0, ETH_ALEN); b43_upload_card_macaddress(dev); b43_security_init(dev); b43_rng_init(wl); @@ -3630,6 +3628,15 @@ static int b43_op_start(struct ieee80211_hw *hw) struct b43_wldev *dev = wl->current_dev; int did_init = 0; int err = 0; + bool do_rfkill_exit = 0; + + /* Kill all old instance specific information to make sure + * the card won't use it in the short timeframe between start + * and mac80211 reconfiguring it. */ + memset(wl->bssid, 0, ETH_ALEN); + memset(wl->mac_addr, 0, ETH_ALEN); + wl->filter_flags = 0; + wl->radiotap_enabled = 0; /* First register RFkill. * LEDs that are registered later depend on it. */ @@ -3639,8 +3646,10 @@ static int b43_op_start(struct ieee80211_hw *hw) if (b43_status(dev) < B43_STAT_INITIALIZED) { err = b43_wireless_core_init(dev); - if (err) + if (err) { + do_rfkill_exit = 1; goto out_mutex_unlock; + } did_init = 1; } @@ -3649,6 +3658,7 @@ static int b43_op_start(struct ieee80211_hw *hw) if (err) { if (did_init) b43_wireless_core_exit(dev); + do_rfkill_exit = 1; goto out_mutex_unlock; } } @@ -3656,6 +3666,9 @@ static int b43_op_start(struct ieee80211_hw *hw) out_mutex_unlock: mutex_unlock(&wl->mutex); + if (do_rfkill_exit) + b43_rfkill_exit(dev); + return err; } diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 3fc53e8..7caa26e 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -178,12 +178,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate) } /* Generate a TX data header. */ -void b43_generate_txhdr(struct b43_wldev *dev, - u8 *_txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, - u16 cookie) +int b43_generate_txhdr(struct b43_wldev *dev, + u8 *_txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const struct ieee80211_tx_control *txctl, + u16 cookie) { struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; const struct b43_phy *phy = &dev->phy; @@ -237,7 +237,15 @@ void b43_generate_txhdr(struct b43_wldev *dev, B43_WARN_ON(key_idx >= dev->max_nr_keys); key = &(dev->key[key_idx]); - B43_WARN_ON(!key->keyconf); + + if (unlikely(!key->keyconf)) { + /* This key is invalid. This might only happen + * in a short timeframe after machine resume before + * we were able to reconfigure keys. + * Drop this packet completely. Do not transmit it + * unencrypted to avoid leaking information. */ + return -ENOKEY; + } /* Hardware appends ICV. */ plcp_fragment_len += txctl->icv_len; @@ -408,6 +416,7 @@ void b43_generate_txhdr(struct b43_wldev *dev, txhdr->phy_ctl = cpu_to_le16(phy_ctl); txhdr->extra_ft = extra_ft; + return 0; } static s8 b43_rssi_postprocess(struct b43_wldev *dev, diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index ca2a2ab..4176503 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -174,11 +174,11 @@ size_t b43_txhdr_size(struct b43_wldev *dev) } -void b43_generate_txhdr(struct b43_wldev *dev, - u8 * txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, u16 cookie); +int b43_generate_txhdr(struct b43_wldev *dev, + u8 * txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const struct ieee80211_tx_control *txctl, u16 cookie); /* Transmit Status */ struct b43_txstatus { diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 93419ad..c80edd2 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -23,7 +23,7 @@ #include "phy.h" -#define B43legacy_IRQWAIT_MAX_RETRIES 100 +#define B43legacy_IRQWAIT_MAX_RETRIES 20 #define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */ @@ -40,9 +40,8 @@ #define B43legacy_MMIO_DMA4_IRQ_MASK 0x44 #define B43legacy_MMIO_DMA5_REASON 0x48 #define B43legacy_MMIO_DMA5_IRQ_MASK 0x4C -#define B43legacy_MMIO_MACCTL 0x120 -#define B43legacy_MMIO_STATUS_BITFIELD 0x120 -#define B43legacy_MMIO_STATUS2_BITFIELD 0x124 +#define B43legacy_MMIO_MACCTL 0x120 /* MAC control */ +#define B43legacy_MMIO_MACCMD 0x124 /* MAC command */ #define B43legacy_MMIO_GEN_IRQ_REASON 0x128 #define B43legacy_MMIO_GEN_IRQ_MASK 0x12C #define B43legacy_MMIO_RAM_CONTROL 0x130 @@ -177,31 +176,25 @@ #define B43legacy_RADIOCTL_ID 0x01 /* MAC Control bitfield */ +#define B43legacy_MACCTL_ENABLED 0x00000001 /* MAC Enabled */ +#define B43legacy_MACCTL_PSM_RUN 0x00000002 /* Run Microcode */ +#define B43legacy_MACCTL_PSM_JMP0 0x00000004 /* Microcode jump to 0 */ +#define B43legacy_MACCTL_SHM_ENABLED 0x00000100 /* SHM Enabled */ #define B43legacy_MACCTL_IHR_ENABLED 0x00000400 /* IHR Region Enabled */ +#define B43legacy_MACCTL_BE 0x00010000 /* Big Endian mode */ #define B43legacy_MACCTL_INFRA 0x00020000 /* Infrastructure mode */ #define B43legacy_MACCTL_AP 0x00040000 /* AccessPoint mode */ +#define B43legacy_MACCTL_RADIOLOCK 0x00080000 /* Radio lock */ #define B43legacy_MACCTL_BEACPROMISC 0x00100000 /* Beacon Promiscuous */ #define B43legacy_MACCTL_KEEP_BADPLCP 0x00200000 /* Keep bad PLCP frames */ #define B43legacy_MACCTL_KEEP_CTL 0x00400000 /* Keep control frames */ #define B43legacy_MACCTL_KEEP_BAD 0x00800000 /* Keep bad frames (FCS) */ #define B43legacy_MACCTL_PROMISC 0x01000000 /* Promiscuous mode */ +#define B43legacy_MACCTL_HWPS 0x02000000 /* Hardware Power Saving */ +#define B43legacy_MACCTL_AWAKE 0x04000000 /* Device is awake */ +#define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */ #define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */ -/* StatusBitField */ -#define B43legacy_SBF_MAC_ENABLED 0x00000001 -#define B43legacy_SBF_CORE_READY 0x00000004 -#define B43legacy_SBF_400 0x00000400 /*FIXME: fix name*/ -#define B43legacy_SBF_XFER_REG_BYTESWAP 0x00010000 -#define B43legacy_SBF_MODE_NOTADHOC 0x00020000 -#define B43legacy_SBF_MODE_AP 0x00040000 -#define B43legacy_SBF_RADIOREG_LOCK 0x00080000 -#define B43legacy_SBF_MODE_MONITOR 0x00400000 -#define B43legacy_SBF_MODE_PROMISC 0x01000000 -#define B43legacy_SBF_PS1 0x02000000 -#define B43legacy_SBF_PS2 0x04000000 -#define B43legacy_SBF_NO_SSID_BCAST 0x08000000 -#define B43legacy_SBF_TIME_UPDATE 0x10000000 - /* 802.11 core specific TM State Low flags */ #define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ #define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 4ed4243..aa20d5d 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -225,8 +225,8 @@ static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset, B43legacy_WARN_ON(offset % 4 != 0); - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - if (status & B43legacy_SBF_XFER_REG_BYTESWAP) + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + if (status & B43legacy_MACCTL_BE) val = swab32(val); b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset); @@ -434,9 +434,9 @@ static void b43legacy_time_lock(struct b43legacy_wldev *dev) { u32 status; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - status |= B43legacy_SBF_TIME_UPDATE; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + status |= B43legacy_MACCTL_TBTTHOLD; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); mmiowb(); } @@ -444,9 +444,9 @@ static void b43legacy_time_unlock(struct b43legacy_wldev *dev) { u32 status; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - status &= ~B43legacy_SBF_TIME_UPDATE; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + status &= ~B43legacy_MACCTL_TBTTHOLD; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); } static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf) @@ -647,7 +647,7 @@ void b43legacy_dummy_transmission(struct b43legacy_wldev *dev) b43legacy_ram_write(dev, i * 4, buffer[i]); /* dummy read follows */ - b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); + b43legacy_read32(dev, B43legacy_MMIO_MACCTL); b43legacy_write16(dev, 0x0568, 0x0000); b43legacy_write16(dev, 0x07C0, 0x0000); @@ -794,9 +794,9 @@ static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi) static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev) { b43legacy_jssi_write(dev, 0x7F7F7F7F); - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, b43legacy_read32(dev, - B43legacy_MMIO_STATUS2_BITFIELD) + B43legacy_MMIO_MACCMD) | (1 << 4)); B43legacy_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel); @@ -895,8 +895,8 @@ static void handle_irq_atim_end(struct b43legacy_wldev *dev) { if (!dev->reg124_set_0x4) /*FIXME rename this variable*/ return; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, - b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD) + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, + b43legacy_read32(dev, B43legacy_MMIO_MACCMD) | 0x4); } @@ -1106,9 +1106,9 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev) b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, B43legacy_CCK_RATE_11MB); - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); status |= 0x03; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, status); + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status); } static void b43legacy_refresh_templates(struct b43legacy_wldev *dev, @@ -1166,7 +1166,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) return; dev->irq_savedstate &= ~B43legacy_IRQ_BEACON; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) { /* ACK beacon IRQ. */ @@ -1182,14 +1182,14 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) b43legacy_write_beacon_template(dev, 0x68, 0x18, B43legacy_CCK_RATE_1MB); status |= 0x1; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status); } if (!(status & 0x2)) { b43legacy_write_beacon_template(dev, 0x468, 0x1A, B43legacy_CCK_RATE_1MB); status |= 0x2; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status); } } @@ -1548,9 +1548,20 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) u16 fwpatch; u16 fwdate; u16 fwtime; - u32 tmp; + u32 tmp, macctl; int err = 0; + /* Jump the microcode PSM to offset 0 */ + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN); + macctl |= B43legacy_MACCTL_PSM_JMP0; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); + /* Zero out all microcode PSM registers and shared memory. */ + for (i = 0; i < 64; i++) + b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0); + for (i = 0; i < 4096; i += 2) + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0); + /* Upload Microcode. */ data = (__be32 *) (dev->fw.ucode->data + hdr_len); len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32); @@ -1581,7 +1592,12 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_ALL); - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402); + + /* Start the microcode PSM */ + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + macctl &= ~B43legacy_MACCTL_PSM_JMP0; + macctl |= B43legacy_MACCTL_PSM_RUN; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); /* Wait for the microcode to load and respond */ i = 0; @@ -1594,9 +1610,13 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) b43legacyerr(dev->wl, "Microcode not responding\n"); b43legacy_print_fw_helptext(dev->wl); err = -ENODEV; - goto out; + goto error; + } + msleep_interruptible(50); + if (signal_pending(current)) { + err = -EINTR; + goto error; } - udelay(10); } /* dummy read follows */ b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); @@ -1617,9 +1637,8 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) " is supported. You must change your firmware" " files.\n"); b43legacy_print_fw_helptext(dev->wl); - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0); err = -EOPNOTSUPP; - goto out; + goto error; } b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u " "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, @@ -1629,7 +1648,14 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) dev->fw.rev = fwrev; dev->fw.patch = fwpatch; -out: + return 0; + +error: + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + macctl &= ~B43legacy_MACCTL_PSM_RUN; + macctl |= B43legacy_MACCTL_PSM_JMP0; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); + return err; } @@ -1736,9 +1762,9 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev) u32 mask; u32 set; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, b43legacy_read32(dev, - B43legacy_MMIO_STATUS_BITFIELD) + B43legacy_MMIO_MACCTL) & 0xFFFF3FFF); b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK, @@ -1798,14 +1824,14 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev) B43legacy_WARN_ON(dev->mac_suspended < 0); B43legacy_WARN_ON(irqs_disabled()); if (dev->mac_suspended == 0) { - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, b43legacy_read32(dev, - B43legacy_MMIO_STATUS_BITFIELD) - | B43legacy_SBF_MAC_ENABLED); + B43legacy_MMIO_MACCTL) + | B43legacy_MACCTL_ENABLED); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_MAC_SUSPENDED); /* the next two are dummy reads */ - b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); + b43legacy_read32(dev, B43legacy_MMIO_MACCTL); b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); b43legacy_power_saving_ctl_bits(dev, -1, -1); @@ -1836,10 +1862,10 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev) dev->irq_savedstate = tmp; b43legacy_power_saving_ctl_bits(dev, -1, 1); - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, b43legacy_read32(dev, - B43legacy_MMIO_STATUS_BITFIELD) - & ~B43legacy_SBF_MAC_ENABLED); + B43legacy_MMIO_MACCTL) + & ~B43legacy_MACCTL_ENABLED); b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); for (i = 40; i; i--) { tmp = b43legacy_read32(dev, @@ -2007,12 +2033,15 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) struct b43legacy_phy *phy = &dev->phy; int err; int tmp; - u32 value32; + u32 value32, macctl; u16 value16; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, - B43legacy_SBF_CORE_READY - | B43legacy_SBF_400); + /* Initialize the MAC control */ + macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED; + if (dev->phy.gmode) + macctl |= B43legacy_MACCTL_GMODE; + macctl |= B43legacy_MACCTL_INFRA; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); err = b43legacy_request_firmware(dev); if (err) @@ -2052,12 +2081,12 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) if (dev->dev->id.revision < 5) b43legacy_write32(dev, 0x010C, 0x01000000); - value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - value32 &= ~B43legacy_SBF_MODE_NOTADHOC; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); - value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - value32 |= B43legacy_SBF_MODE_NOTADHOC; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); + value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + value32 &= ~B43legacy_MACCTL_INFRA; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32); + value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + value32 |= B43legacy_MACCTL_INFRA; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32); if (b43legacy_using_pio(dev)) { b43legacy_write32(dev, 0x0210, 0x00000100); @@ -2951,12 +2980,19 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) { struct b43legacy_wl *wl = dev->wl; struct b43legacy_phy *phy = &dev->phy; + u32 macctl; B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED); if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED) return; b43legacy_set_status(dev, B43legacy_STAT_UNINIT); + /* Stop the microcode PSM. */ + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + macctl &= ~B43legacy_MACCTL_PSM_RUN; + macctl |= B43legacy_MACCTL_PSM_JMP0; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); + mutex_unlock(&wl->mutex); /* Must unlock as it would otherwise deadlock. No races here. * Cancel possibly pending workqueues. */ @@ -3221,6 +3257,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) struct b43legacy_wldev *dev = wl->current_dev; int did_init = 0; int err = 0; + bool do_rfkill_exit = 0; /* First register RFkill. * LEDs that are registered later depend on it. */ @@ -3230,8 +3267,10 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { err = b43legacy_wireless_core_init(dev); - if (err) + if (err) { + do_rfkill_exit = 1; goto out_mutex_unlock; + } did_init = 1; } @@ -3240,6 +3279,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) if (err) { if (did_init) b43legacy_wireless_core_exit(dev); + do_rfkill_exit = 1; goto out_mutex_unlock; } } @@ -3247,6 +3287,9 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) out_mutex_unlock: mutex_unlock(&wl->mutex); + if (do_rfkill_exit) + b43legacy_rfkill_exit(dev); + return err; } diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index c16febb..8e5c09b 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c @@ -140,7 +140,7 @@ void b43legacy_phy_calibrate(struct b43legacy_wldev *dev) { struct b43legacy_phy *phy = &dev->phy; - b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); /* Dummy read. */ + b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Dummy read. */ if (phy->calibrated) return; if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) { @@ -2231,16 +2231,16 @@ bit26 = 1; * or the latest PS-Poll packet sent was successful, * set bit26 */ } - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); if (bit25) - status |= B43legacy_SBF_PS1; + status |= B43legacy_MACCTL_HWPS; else - status &= ~B43legacy_SBF_PS1; + status &= ~B43legacy_MACCTL_HWPS; if (bit26) - status |= B43legacy_SBF_PS2; + status |= B43legacy_MACCTL_AWAKE; else - status &= ~B43legacy_SBF_PS2; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status &= ~B43legacy_MACCTL_AWAKE; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); if (bit26 && dev->dev->id.revision >= 5) { for (i = 0; i < 100; i++) { if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index de843ac..e4f4c5c 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -334,9 +334,9 @@ struct b43legacy_pioqueue *b43legacy_setup_pioqueue(struct b43legacy_wldev *dev, tasklet_init(&queue->txtask, tx_tasklet, (unsigned long)queue); - value = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - value &= ~B43legacy_SBF_XFER_REG_BYTESWAP; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value); + value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + value &= ~B43legacy_MACCTL_BE; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value); qsize = b43legacy_read16(dev, queue->mmio_base + B43legacy_PIO_TXQBUFSIZE); diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c index 318a270..955832e 100644 --- a/drivers/net/wireless/b43legacy/radio.c +++ b/drivers/net/wireless/b43legacy/radio.c @@ -91,10 +91,10 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev) { u32 status; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - B43legacy_WARN_ON(status & B43legacy_SBF_RADIOREG_LOCK); - status |= B43legacy_SBF_RADIOREG_LOCK; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK); + status |= B43legacy_MACCTL_RADIOLOCK; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); mmiowb(); udelay(10); } @@ -104,10 +104,10 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev) u32 status; b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */ - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - B43legacy_WARN_ON(!(status & B43legacy_SBF_RADIOREG_LOCK)); - status &= ~B43legacy_SBF_RADIOREG_LOCK; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK)); + status &= ~B43legacy_MACCTL_RADIOLOCK; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); mmiowb(); } diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h index d6b9362..3694b1e 100644 --- a/drivers/net/wireless/hostap/hostap_80211.h +++ b/drivers/net/wireless/hostap/hostap_80211.h @@ -71,11 +71,6 @@ struct hostap_80211_rx_status { u16 rate; /* in 100 kbps */ }; - -void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats); - - /* prism2_rx_80211 'type' argument */ enum { PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC, diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 0759380..437a9bc 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -891,6 +891,9 @@ static struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_PROD_ID123( "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", 0xa5f472c2, 0x9c05598d, 0xc9049a39), + PCMCIA_DEVICE_PROD_ID123( + "Wireless LAN" , "11Mbps PC Card", "Version 01.02", + 0x4b8870ff, 0x70e946d1, 0x4b74baa0), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 6e01873..571815d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -373,7 +373,7 @@ struct iwl3945_eeprom { #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ #define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ -#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */ +#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 76c4ed1..4fdeb53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2369,18 +2369,4 @@ struct pci_device_id iwl3945_hw_card_ids[] = { {0} }; -/* - * Clear the OWNER_MSK, to establish driver (instead of uCode running on - * embedded controller) as EEPROM reader; each read is a series of pulses - * to/from the EEPROM chip, not a single event, so even reads could conflict - * if they weren't arbitrated by some ownership mechanism. Here, the driver - * simply claims ownership, which should be safe when this function is called - * (i.e. before loading uCode!). - */ -inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) -{ - _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); - return 0; -} - MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 20b925f..1da14f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -671,7 +671,6 @@ extern int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel); /* * Forward declare iwl-3945.c functions for iwl-base.c */ -extern int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv); extern __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv); extern int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv); extern void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv); @@ -791,7 +790,6 @@ struct iwl3945_priv { u16 active_rate_basic; u8 call_post_assoc_from_beacon; - u8 assoc_station_added; /* Rate scaling data */ s8 data_retry_limit; u8 retry_rate; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index ff71c09..ffe1e9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -465,7 +465,7 @@ struct iwl4965_eeprom { #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ #define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ -#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */ +#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 04db34b..569347f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4961,11 +4961,4 @@ int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv) return rc; } -inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv) -{ - iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); -} - - MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 78bc148..9cb82be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -750,7 +750,6 @@ struct iwl4965_priv; * Forward declare iwl-4965.c functions for iwl-base.c */ extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv); -extern void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv); extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq, diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index cd2eb18..cb009f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -246,10 +246,10 @@ static inline int iwl_check_bits(unsigned long field, unsigned long mask) static inline unsigned long elapsed_jiffies(unsigned long start, unsigned long end) { - if (end > start) + if (end >= start) return end - start; - return end + (MAX_JIFFY_OFFSET - start); + return end + (MAX_JIFFY_OFFSET - start) + 1; } static inline u8 iwl_get_dma_hi_address(dma_addr_t addr) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 748ac12..33239f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1557,6 +1557,20 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac) memcpy(mac, priv->eeprom.mac_address, 6); } +/* + * Clear the OWNER_MSK, to establish driver (instead of uCode running on + * embedded controller) as EEPROM reader; each read is a series of pulses + * to/from the EEPROM chip, not a single event, so even reads could conflict + * if they weren't arbitrated by some ownership mechanism. Here, the driver + * simply claims ownership, which should be safe when this function is called + * (i.e. before loading uCode!). + */ +static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) +{ + _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); + return 0; +} + /** * iwl3945_eeprom_init - read EEPROM contents * @@ -2792,7 +2806,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, #endif /* drop all data frame if we are not associated */ - if (!iwl3945_is_associated(priv) && !priv->assoc_id && + if ((!iwl3945_is_associated(priv) || !priv->assoc_id) && ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; @@ -4745,8 +4759,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) #ifdef CONFIG_IWL3945_DEBUG if (iwl3945_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_MAC_CLK_ACTV) - IWL_DEBUG_ISR("Microcode started or stopped.\n"); + if (inta & CSR_INT_BIT_SCD) + IWL_DEBUG_ISR("Scheduler finished to transmit " + "the frame/frames.\n"); /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) @@ -4754,7 +4769,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) } #endif /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE); + inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); /* HW RF KILL switch toggled (4965 only) */ if (inta & CSR_INT_BIT_RF_KILL) { @@ -4890,8 +4905,11 @@ static irqreturn_t iwl3945_isr(int irq, void *data) IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); + inta &= ~CSR_INT_BIT_SCD; + /* iwl3945_irq_tasklet() will service interrupts and re-enable them */ - tasklet_schedule(&priv->irq_tasklet); + if (likely(inta || inta_fh)) + tasklet_schedule(&priv->irq_tasklet); unplugged: spin_unlock(&priv->lock); @@ -5146,6 +5164,15 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) return 0; } +/* + * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map + */ +static void iwl3945_free_channel_map(struct iwl3945_priv *priv) +{ + kfree(priv->channel_info); + priv->channel_count = 0; +} + /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses * from more than one AP. */ @@ -5471,6 +5498,17 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) return 0; } +/* + * iwl3945_free_geos - undo allocations in iwl3945_init_geos + */ +static void iwl3945_free_geos(struct iwl3945_priv *priv) +{ + kfree(priv->modes); + kfree(priv->ieee_channels); + kfree(priv->ieee_rates); + clear_bit(STATUS_GEO_CONFIGURED, &priv->status); +} + /****************************************************************************** * * uCode download functions @@ -6130,15 +6168,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) /* Clear out the uCode error bit if it is set */ clear_bit(STATUS_FW_ERROR, &priv->status); - rc = iwl3945_init_channel_map(priv); - if (rc) { - IWL_ERROR("initializing regulatory failed: %d\n", rc); - return; - } - - iwl3945_init_geos(priv); - iwl3945_reset_channel_flag(priv); - if (iwl3945_is_rfkill(priv)) return; @@ -6599,7 +6628,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) * that based on the direct_mask added to each channel entry */ scan->tx_cmd.len = cpu_to_le16( iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(scan), 0)); + IWL_MAX_SCAN_SIZE - sizeof(*scan), 0)); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; @@ -7120,7 +7149,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) { int rc = 0; - if (priv->status & STATUS_EXIT_PENDING) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* The following should be done only at AP bring up */ @@ -8614,11 +8643,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); + err = iwl3945_init_channel_map(priv); + if (err) { + IWL_ERROR("initializing regulatory failed: %d\n", err); + goto out_remove_sysfs; + } + + err = iwl3945_init_geos(priv); + if (err) { + IWL_ERROR("initializing geos failed: %d\n", err); + goto out_free_channel_map; + } + iwl3945_reset_channel_flag(priv); + iwl3945_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); if (err) { IWL_ERROR("Failed to register network device (error %d)\n", err); - goto out_remove_sysfs; + goto out_free_geos; } priv->hw->conf.beacon_int = 100; @@ -8628,6 +8670,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return 0; + out_free_geos: + iwl3945_free_geos(priv); + out_free_channel_map: + iwl3945_free_channel_map(priv); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); @@ -8702,10 +8748,8 @@ static void iwl3945_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - kfree(priv->channel_info); - - kfree(priv->ieee_channels); - kfree(priv->ieee_rates); + iwl3945_free_channel_map(priv); + iwl3945_free_geos(priv); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index c86da5c..bf3a60c 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1639,6 +1639,12 @@ static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac) memcpy(mac, priv->eeprom.mac_address, 6); } +static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv) +{ + iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); +} + /** * iwl4965_eeprom_init - read EEPROM contents * @@ -2927,8 +2933,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, #endif /* drop all data frame if we are not associated */ - if (!iwl4965_is_associated(priv) && !priv->assoc_id && - ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { + if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && + (!iwl4965_is_associated(priv) || + !priv->assoc_id || + !priv->assoc_station_added)) { IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n"); goto drop_unlock; } @@ -5131,8 +5139,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) #ifdef CONFIG_IWL4965_DEBUG if (iwl4965_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_MAC_CLK_ACTV) - IWL_DEBUG_ISR("Microcode started or stopped.\n"); + if (inta & CSR_INT_BIT_SCD) + IWL_DEBUG_ISR("Scheduler finished to transmit " + "the frame/frames.\n"); /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) @@ -5140,7 +5149,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) } #endif /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE); + inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { @@ -5269,8 +5278,11 @@ static irqreturn_t iwl4965_isr(int irq, void *data) IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); + inta &= ~CSR_INT_BIT_SCD; + /* iwl4965_irq_tasklet() will service interrupts and re-enable them */ - tasklet_schedule(&priv->irq_tasklet); + if (likely(inta || inta_fh)) + tasklet_schedule(&priv->irq_tasklet); unplugged: spin_unlock(&priv->lock); @@ -5576,6 +5588,15 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) return 0; } +/* + * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map + */ +static void iwl4965_free_channel_map(struct iwl4965_priv *priv) +{ + kfree(priv->channel_info); + priv->channel_count = 0; +} + /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses * from more than one AP. */ @@ -5909,6 +5930,17 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) return 0; } +/* + * iwl4965_free_geos - undo allocations in iwl4965_init_geos + */ +static void iwl4965_free_geos(struct iwl4965_priv *priv) +{ + kfree(priv->modes); + kfree(priv->ieee_channels); + kfree(priv->ieee_rates); + clear_bit(STATUS_GEO_CONFIGURED, &priv->status); +} + /****************************************************************************** * * uCode download functions @@ -6560,15 +6592,6 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv) /* Clear out the uCode error bit if it is set */ clear_bit(STATUS_FW_ERROR, &priv->status); - rc = iwl4965_init_channel_map(priv); - if (rc) { - IWL_ERROR("initializing regulatory failed: %d\n", rc); - return; - } - - iwl4965_init_geos(priv); - iwl4965_reset_channel_flag(priv); - if (iwl4965_is_rfkill(priv)) return; @@ -7023,7 +7046,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) * that based on the direct_mask added to each channel entry */ scan->tx_cmd.len = cpu_to_le16( iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(scan), 0)); + IWL_MAX_SCAN_SIZE - sizeof(*scan), 0)); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; @@ -7448,7 +7471,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw, if (priv->vif) { IWL_DEBUG_MAC80211("leave - vif != NULL\n"); - return 0; + return -EOPNOTSUPP; } spin_lock_irqsave(&priv->lock, flags); @@ -7580,7 +7603,7 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv) { int rc = 0; - if (priv->status & STATUS_EXIT_PENDING) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* The following should be done only at AP bring up */ @@ -9198,11 +9221,24 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); + err = iwl4965_init_channel_map(priv); + if (err) { + IWL_ERROR("initializing regulatory failed: %d\n", err); + goto out_remove_sysfs; + } + + err = iwl4965_init_geos(priv); + if (err) { + IWL_ERROR("initializing geos failed: %d\n", err); + goto out_free_channel_map; + } + iwl4965_reset_channel_flag(priv); + iwl4965_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); if (err) { IWL_ERROR("Failed to register network device (error %d)\n", err); - goto out_remove_sysfs; + goto out_free_geos; } priv->hw->conf.beacon_int = 100; @@ -9212,6 +9248,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return 0; + out_free_geos: + iwl4965_free_geos(priv); + out_free_channel_map: + iwl4965_free_channel_map(priv); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); @@ -9286,10 +9326,8 @@ static void iwl4965_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - kfree(priv->channel_info); - - kfree(priv->ieee_channels); - kfree(priv->ieee_rates); + iwl4965_free_channel_map(priv); + iwl4965_free_geos(priv); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index c622e9b..87e145f 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -12,8 +12,10 @@ #include "cmd.h" -static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static int assoc_helper_essid(struct lbs_private *priv, diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 58d7ef6..5a69f2b 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -349,7 +349,7 @@ struct assoc_request { u8 channel; u8 band; u8 mode; - u8 bssid[ETH_ALEN]; + u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); /** WEP keys */ struct enc_key wep_keys[4]; diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 4b5ab9a..5a9cadb 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -249,14 +249,14 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) lbs_deb_enter(LBS_DEB_CS); int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); - if(int_cause == 0x0) { + if (int_cause == 0x0) { /* Not for us */ return IRQ_NONE; } else if (int_cause == 0xffff) { /* Read in junk, the card has probably been removed */ card->priv->surpriseremoved = 1; - + return IRQ_HANDLED; } else { if (int_cause & IF_CS_H_IC_TX_OVER) lbs_host_to_card_done(card->priv); @@ -717,8 +717,8 @@ static void if_cs_release(struct pcmcia_device *p_dev) lbs_deb_enter(LBS_DEB_CS); - pcmcia_disable_device(p_dev); free_irq(p_dev->irq.AssignedIRQ, card); + pcmcia_disable_device(p_dev); if (card->iobase) ioport_unmap(card->iobase); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c new file mode 100644 index 0000000..d3ecf89 --- /dev/null +++ b/drivers/net/wireless/rndis_wlan.c @@ -0,0 +1,2757 @@ +/* + * Driver for RNDIS based wireless USB devices. + * + * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net> + * Copyright (C) 2008 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Portions of this file are based on NDISwrapper project, + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * http://ndiswrapper.sourceforge.net/ + */ + +// #define DEBUG // error path messages, extra info +// #define VERBOSE // more; success messages + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/workqueue.h> +#include <linux/mutex.h> +#include <linux/mii.h> +#include <linux/usb.h> +#include <linux/usb/cdc.h> +#include <linux/wireless.h> +#include <linux/if_arp.h> +#include <linux/ctype.h> +#include <linux/spinlock.h> +#include <net/iw_handler.h> +#include <net/ieee80211.h> +#include <linux/usb/usbnet.h> +#include <linux/usb/rndis_host.h> + + +/* NOTE: All these are settings for Broadcom chipset */ +static char modparam_country[4] = "EU"; +module_param_string(country, modparam_country, 4, 0444); +MODULE_PARM_DESC(country, "Country code (ISO 3166-1 alpha-2), default: EU"); + +static int modparam_frameburst = 1; +module_param_named(frameburst, modparam_frameburst, int, 0444); +MODULE_PARM_DESC(frameburst, "enable frame bursting (default: on)"); + +static int modparam_afterburner = 0; +module_param_named(afterburner, modparam_afterburner, int, 0444); +MODULE_PARM_DESC(afterburner, + "enable afterburner aka '125 High Speed Mode' (default: off)"); + +static int modparam_power_save = 0; +module_param_named(power_save, modparam_power_save, int, 0444); +MODULE_PARM_DESC(power_save, + "set power save mode: 0=off, 1=on, 2=fast (default: off)"); + +static int modparam_power_output = 3; +module_param_named(power_output, modparam_power_output, int, 0444); +MODULE_PARM_DESC(power_output, + "set power output: 0=25%, 1=50%, 2=75%, 3=100% (default: 100%)"); + +static int modparam_roamtrigger = -70; +module_param_named(roamtrigger, modparam_roamtrigger, int, 0444); +MODULE_PARM_DESC(roamtrigger, + "set roaming dBm trigger: -80=optimize for distance, " + "-60=bandwidth (default: -70)"); + +static int modparam_roamdelta = 1; +module_param_named(roamdelta, modparam_roamdelta, int, 0444); +MODULE_PARM_DESC(roamdelta, + "set roaming tendency: 0=aggressive, 1=moderate, " + "2=conservative (default: moderate)"); + +static int modparam_workaround_interval = 500; +module_param_named(workaround_interval, modparam_workaround_interval, + int, 0444); +MODULE_PARM_DESC(workaround_interval, + "set stall workaround interval in msecs (default: 500)"); + + +/* various RNDIS OID defs */ +#define OID_GEN_LINK_SPEED ccpu2(0x00010107) +#define OID_GEN_RNDIS_CONFIG_PARAMETER ccpu2(0x0001021b) + +#define OID_GEN_XMIT_OK ccpu2(0x00020101) +#define OID_GEN_RCV_OK ccpu2(0x00020102) +#define OID_GEN_XMIT_ERROR ccpu2(0x00020103) +#define OID_GEN_RCV_ERROR ccpu2(0x00020104) +#define OID_GEN_RCV_NO_BUFFER ccpu2(0x00020105) + +#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101) +#define OID_802_3_CURRENT_ADDRESS ccpu2(0x01010102) +#define OID_802_3_MULTICAST_LIST ccpu2(0x01010103) +#define OID_802_3_MAXIMUM_LIST_SIZE ccpu2(0x01010104) + +#define OID_802_11_BSSID ccpu2(0x0d010101) +#define OID_802_11_SSID ccpu2(0x0d010102) +#define OID_802_11_INFRASTRUCTURE_MODE ccpu2(0x0d010108) +#define OID_802_11_ADD_WEP ccpu2(0x0d010113) +#define OID_802_11_REMOVE_WEP ccpu2(0x0d010114) +#define OID_802_11_DISASSOCIATE ccpu2(0x0d010115) +#define OID_802_11_AUTHENTICATION_MODE ccpu2(0x0d010118) +#define OID_802_11_PRIVACY_FILTER ccpu2(0x0d010119) +#define OID_802_11_BSSID_LIST_SCAN ccpu2(0x0d01011a) +#define OID_802_11_ENCRYPTION_STATUS ccpu2(0x0d01011b) +#define OID_802_11_ADD_KEY ccpu2(0x0d01011d) +#define OID_802_11_REMOVE_KEY ccpu2(0x0d01011e) +#define OID_802_11_PMKID ccpu2(0x0d010123) +#define OID_802_11_NETWORK_TYPES_SUPPORTED ccpu2(0x0d010203) +#define OID_802_11_NETWORK_TYPE_IN_USE ccpu2(0x0d010204) +#define OID_802_11_TX_POWER_LEVEL ccpu2(0x0d010205) +#define OID_802_11_RSSI ccpu2(0x0d010206) +#define OID_802_11_RSSI_TRIGGER ccpu2(0x0d010207) +#define OID_802_11_FRAGMENTATION_THRESHOLD ccpu2(0x0d010209) +#define OID_802_11_RTS_THRESHOLD ccpu2(0x0d01020a) +#define OID_802_11_SUPPORTED_RATES ccpu2(0x0d01020e) +#define OID_802_11_CONFIGURATION ccpu2(0x0d010211) +#define OID_802_11_BSSID_LIST ccpu2(0x0d010217) + + +/* Typical noise/maximum signal level values taken from ndiswrapper iw_ndis.h */ +#define WL_NOISE -96 /* typical noise level in dBm */ +#define WL_SIGMAX -32 /* typical maximum signal level in dBm */ + + +/* Assume that Broadcom 4320 (only chipset at time of writing known to be + * based on wireless rndis) has default txpower of 13dBm. + * This value is from Linksys WUSB54GSC User Guide, Appendix F: Specifications. + * 13dBm == 19.9mW + */ +#define BCM4320_DEFAULT_TXPOWER 20 + + +/* codes for "status" field of completion messages */ +#define RNDIS_STATUS_ADAPTER_NOT_READY ccpu2(0xc0010011) +#define RNDIS_STATUS_ADAPTER_NOT_OPEN ccpu2(0xc0010012) + + +/* NDIS data structures. Taken from wpa_supplicant driver_ndis.c + * slightly modified for datatype endianess, etc + */ +#define NDIS_802_11_LENGTH_SSID 32 +#define NDIS_802_11_LENGTH_RATES 8 +#define NDIS_802_11_LENGTH_RATES_EX 16 + +struct NDIS_802_11_SSID { + __le32 SsidLength; + u8 Ssid[NDIS_802_11_LENGTH_SSID]; +} __attribute__((packed)); + +enum NDIS_802_11_NETWORK_TYPE { + Ndis802_11FH, + Ndis802_11DS, + Ndis802_11OFDM5, + Ndis802_11OFDM24, + Ndis802_11NetworkTypeMax +}; + +struct NDIS_802_11_CONFIGURATION_FH { + __le32 Length; + __le32 HopPattern; + __le32 HopSet; + __le32 DwellTime; +} __attribute__((packed)); + +struct NDIS_802_11_CONFIGURATION { + __le32 Length; + __le32 BeaconPeriod; + __le32 ATIMWindow; + __le32 DSConfig; + struct NDIS_802_11_CONFIGURATION_FH FHConfig; +} __attribute__((packed)); + +enum NDIS_802_11_NETWORK_INFRASTRUCTURE { + Ndis802_11IBSS, + Ndis802_11Infrastructure, + Ndis802_11AutoUnknown, + Ndis802_11InfrastructureMax +}; + +enum NDIS_802_11_AUTHENTICATION_MODE { + Ndis802_11AuthModeOpen, + Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, + Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, + Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, + Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeMax +}; + +enum NDIS_802_11_ENCRYPTION_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent +}; + +enum NDIS_802_11_PRIVACY_FILTER { + Ndis802_11PrivFilterAcceptAll, + Ndis802_11PrivFilter8021xWEP +}; + +struct NDIS_WLAN_BSSID_EX { + __le32 Length; + u8 MacAddress[6]; + u8 Padding[2]; + struct NDIS_802_11_SSID Ssid; + __le32 Privacy; + __le32 Rssi; + enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + struct NDIS_802_11_CONFIGURATION Configuration; + enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; + __le32 IELength; + u8 IEs[0]; +} __attribute__((packed)); + +struct NDIS_802_11_BSSID_LIST_EX { + __le32 NumberOfItems; + struct NDIS_WLAN_BSSID_EX Bssid[0]; +} __attribute__((packed)); + +struct NDIS_802_11_FIXED_IEs { + u8 Timestamp[8]; + __le16 BeaconInterval; + __le16 Capabilities; +} __attribute__((packed)); + +struct NDIS_802_11_WEP { + __le32 Length; + __le32 KeyIndex; + __le32 KeyLength; + u8 KeyMaterial[32]; +} __attribute__((packed)); + +struct NDIS_802_11_KEY { + __le32 Length; + __le32 KeyIndex; + __le32 KeyLength; + u8 Bssid[6]; + u8 Padding[6]; + __le64 KeyRSC; + u8 KeyMaterial[32]; +} __attribute__((packed)); + +struct NDIS_802_11_REMOVE_KEY { + __le32 Length; + __le32 KeyIndex; + u8 Bssid[6]; +} __attribute__((packed)); + +struct RNDIS_CONFIG_PARAMETER_INFOBUFFER { + __le32 ParameterNameOffset; + __le32 ParameterNameLength; + __le32 ParameterType; + __le32 ParameterValueOffset; + __le32 ParameterValueLength; +} __attribute__((packed)); + +/* these have to match what is in wpa_supplicant */ +enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; +enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, CIPHER_WEP104 } + wpa_cipher; +enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, KEY_MGMT_802_1X_NO_WPA, + KEY_MGMT_WPA_NONE } wpa_key_mgmt; + +/* + * private data + */ +#define NET_TYPE_11FB 0 + +#define CAP_MODE_80211A 1 +#define CAP_MODE_80211B 2 +#define CAP_MODE_80211G 4 +#define CAP_MODE_MASK 7 +#define CAP_SUPPORT_TXPOWER 8 + +#define WORK_CONNECTION_EVENT (1<<0) +#define WORK_SET_MULTICAST_LIST (1<<1) + +/* RNDIS device private data */ +struct rndis_wext_private { + char name[32]; + + struct usbnet *usbdev; + + struct workqueue_struct *workqueue; + struct delayed_work stats_work; + struct work_struct work; + struct mutex command_lock; + spinlock_t stats_lock; + unsigned long work_pending; + + struct iw_statistics iwstats; + struct iw_statistics privstats; + + int nick_len; + char nick[32]; + + int caps; + int multicast_size; + + /* module parameters */ + char param_country[4]; + int param_frameburst; + int param_afterburner; + int param_power_save; + int param_power_output; + int param_roamtrigger; + int param_roamdelta; + u32 param_workaround_interval; + + /* hardware state */ + int radio_on; + int infra_mode; + struct NDIS_802_11_SSID essid; + + /* encryption stuff */ + int encr_tx_key_index; + char encr_keys[4][32]; + int encr_key_len[4]; + int wpa_version; + int wpa_keymgmt; + int wpa_authalg; + int wpa_ie_len; + u8 *wpa_ie; + int wpa_cipher_pair; + int wpa_cipher_group; +}; + + +static const int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; + +static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 }; + +static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; + +static const unsigned char zero_bssid[ETH_ALEN] = {0,}; +static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff }; + + +static struct rndis_wext_private *get_rndis_wext_priv(struct usbnet *dev) +{ + return (struct rndis_wext_private *)dev->driver_priv; +} + + +static u32 get_bcm4320_power(struct rndis_wext_private *priv) +{ + return BCM4320_DEFAULT_TXPOWER * + bcm4320_power_output[priv->param_power_output] / 100; +} + + +/* translate error code */ +static int rndis_error_status(__le32 rndis_status) +{ + int ret = -EINVAL; + switch (rndis_status) { + case RNDIS_STATUS_SUCCESS: + ret = 0; + break; + case RNDIS_STATUS_FAILURE: + case RNDIS_STATUS_INVALID_DATA: + ret = -EINVAL; + break; + case RNDIS_STATUS_NOT_SUPPORTED: + ret = -EOPNOTSUPP; + break; + case RNDIS_STATUS_ADAPTER_NOT_READY: + case RNDIS_STATUS_ADAPTER_NOT_OPEN: + ret = -EBUSY; + break; + } + return ret; +} + + +static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + union { + void *buf; + struct rndis_msg_hdr *header; + struct rndis_query *get; + struct rndis_query_c *get_c; + } u; + int ret, buflen; + + buflen = *len + sizeof(*u.get); + if (buflen < CONTROL_BUFFER_SIZE) + buflen = CONTROL_BUFFER_SIZE; + u.buf = kmalloc(buflen, GFP_KERNEL); + if (!u.buf) + return -ENOMEM; + memset(u.get, 0, sizeof *u.get); + u.get->msg_type = RNDIS_MSG_QUERY; + u.get->msg_len = ccpu2(sizeof *u.get); + u.get->oid = oid; + + mutex_lock(&priv->command_lock); + ret = rndis_command(dev, u.header); + mutex_unlock(&priv->command_lock); + + if (ret == 0) { + ret = le32_to_cpu(u.get_c->len); + *len = (*len > ret) ? ret : *len; + memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); + ret = rndis_error_status(u.get_c->status); + } + + kfree(u.buf); + return ret; +} + + +static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + union { + void *buf; + struct rndis_msg_hdr *header; + struct rndis_set *set; + struct rndis_set_c *set_c; + } u; + int ret, buflen; + + buflen = len + sizeof(*u.set); + if (buflen < CONTROL_BUFFER_SIZE) + buflen = CONTROL_BUFFER_SIZE; + u.buf = kmalloc(buflen, GFP_KERNEL); + if (!u.buf) + return -ENOMEM; + + memset(u.set, 0, sizeof *u.set); + u.set->msg_type = RNDIS_MSG_SET; + u.set->msg_len = cpu_to_le32(sizeof(*u.set) + len); + u.set->oid = oid; + u.set->len = cpu_to_le32(len); + u.set->offset = ccpu2(sizeof(*u.set) - 8); + u.set->handle = ccpu2(0); + memcpy(u.buf + sizeof(*u.set), data, len); + + mutex_lock(&priv->command_lock); + ret = rndis_command(dev, u.header); + mutex_unlock(&priv->command_lock); + + if (ret == 0) + ret = rndis_error_status(u.set_c->status); + + kfree(u.buf); + return ret; +} + + +/* + * Specs say that we can only set config parameters only soon after device + * initialization. + * value_type: 0 = u32, 2 = unicode string + */ +static int rndis_set_config_parameter(struct usbnet *dev, char *param, + int value_type, void *value) +{ + struct RNDIS_CONFIG_PARAMETER_INFOBUFFER *infobuf; + int value_len, info_len, param_len, ret, i; + __le16 *unibuf; + __le32 *dst_value; + + if (value_type == 0) + value_len = sizeof(__le32); + else if (value_type == 2) + value_len = strlen(value) * sizeof(__le16); + else + return -EINVAL; + + param_len = strlen(param) * sizeof(__le16); + info_len = sizeof(*infobuf) + param_len + value_len; + +#ifdef DEBUG + info_len += 12; +#endif + infobuf = kmalloc(info_len, GFP_KERNEL); + if (!infobuf) + return -ENOMEM; + +#ifdef DEBUG + info_len -= 12; + /* extra 12 bytes are for padding (debug output) */ + memset(infobuf, 0xCC, info_len + 12); +#endif + + if (value_type == 2) + devdbg(dev, "setting config parameter: %s, value: %s", + param, (u8 *)value); + else + devdbg(dev, "setting config parameter: %s, value: %d", + param, *(u32 *)value); + + infobuf->ParameterNameOffset = cpu_to_le32(sizeof(*infobuf)); + infobuf->ParameterNameLength = cpu_to_le32(param_len); + infobuf->ParameterType = cpu_to_le32(value_type); + infobuf->ParameterValueOffset = cpu_to_le32(sizeof(*infobuf) + + param_len); + infobuf->ParameterValueLength = cpu_to_le32(value_len); + + /* simple string to unicode string conversion */ + unibuf = (void *)infobuf + sizeof(*infobuf); + for (i = 0; i < param_len / sizeof(__le16); i++) + unibuf[i] = cpu_to_le16(param[i]); + + if (value_type == 2) { + unibuf = (void *)infobuf + sizeof(*infobuf) + param_len; + for (i = 0; i < value_len / sizeof(__le16); i++) + unibuf[i] = cpu_to_le16(((u8 *)value)[i]); + } else { + dst_value = (void *)infobuf + sizeof(*infobuf) + param_len; + *dst_value = cpu_to_le32(*(u32 *)value); + } + +#ifdef DEBUG + devdbg(dev, "info buffer (len: %d):", info_len); + for (i = 0; i < info_len; i += 12) { + u32 *tmp = (u32 *)((u8 *)infobuf + i); + devdbg(dev, "%08X:%08X:%08X", + cpu_to_be32(tmp[0]), + cpu_to_be32(tmp[1]), + cpu_to_be32(tmp[2])); + } +#endif + + ret = rndis_set_oid(dev, OID_GEN_RNDIS_CONFIG_PARAMETER, + infobuf, info_len); + if (ret != 0) + devdbg(dev, "setting rndis config paramater failed, %d.", ret); + + kfree(infobuf); + return ret; +} + +static int rndis_set_config_parameter_str(struct usbnet *dev, + char *param, char *value) +{ + return(rndis_set_config_parameter(dev, param, 2, value)); +} + +/*static int rndis_set_config_parameter_u32(struct usbnet *dev, + char *param, u32 value) +{ + return(rndis_set_config_parameter(dev, param, 0, &value)); +}*/ + + +/* + * data conversion functions + */ +static int level_to_qual(int level) +{ + int qual = 100 * (level - WL_NOISE) / (WL_SIGMAX - WL_NOISE); + return qual >= 0 ? (qual <= 100 ? qual : 100) : 0; +} + + +static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq) +{ + freq->e = 0; + freq->i = 0; + freq->flags = 0; + + /* see comment in wireless.h above the "struct iw_freq" + * definition for an explanation of this if + * NOTE: 1000000 is due to the kHz + */ + if (dsconfig > 1000000) { + freq->m = dsconfig / 10; + freq->e = 1; + } else + freq->m = dsconfig; + + /* convert from kHz to Hz */ + freq->e += 3; +} + + +static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig) +{ + if (freq->m < 1000 && freq->e == 0) { + if (freq->m >= 1 && + freq->m <= (sizeof(freq_chan) / sizeof(freq_chan[0]))) + *dsconfig = freq_chan[freq->m - 1] * 1000; + else + return -1; + } else { + int i; + *dsconfig = freq->m; + for (i = freq->e; i > 0; i--) + *dsconfig *= 10; + *dsconfig /= 1000; + } + + return 0; +} + + +/* + * common functions + */ +static int +add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index); + +static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid) +{ + int ret, len; + + len = sizeof(*ssid); + ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len); + + if (ret != 0) + ssid->SsidLength = 0; + +#ifdef DEBUG + { + unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1]; + + memcpy(tmp, ssid->Ssid, le32_to_cpu(ssid->SsidLength)); + tmp[le32_to_cpu(ssid->SsidLength)] = 0; + devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret); + } +#endif + return ret; +} + + +static int set_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + int ret; + + ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid)); + if (ret == 0) { + memcpy(&priv->essid, ssid, sizeof(priv->essid)); + priv->radio_on = 1; + devdbg(usbdev, "set_essid: radio_on = 1"); + } + + return ret; +} + + +static int get_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) +{ + int ret, len; + + len = ETH_ALEN; + ret = rndis_query_oid(usbdev, OID_802_11_BSSID, bssid, &len); + + if (ret != 0) + memset(bssid, 0, ETH_ALEN); + + return ret; +} + + +static int is_associated(struct usbnet *usbdev) +{ + u8 bssid[ETH_ALEN]; + int ret; + + ret = get_bssid(usbdev, bssid); + + return(ret == 0 && memcmp(bssid, zero_bssid, ETH_ALEN) != 0); +} + + +static int disassociate(struct usbnet *usbdev, int reset_ssid) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct NDIS_802_11_SSID ssid; + int i, ret = 0; + + if (priv->radio_on) { + ret = rndis_set_oid(usbdev, OID_802_11_DISASSOCIATE, NULL, 0); + if (ret == 0) { + priv->radio_on = 0; + devdbg(usbdev, "disassociate: radio_on = 0"); + + if (reset_ssid) + msleep(100); + } + } + + /* disassociate causes radio to be turned off; if reset_ssid + * is given, set random ssid to enable radio */ + if (reset_ssid) { + ssid.SsidLength = cpu_to_le32(sizeof(ssid.Ssid)); + get_random_bytes(&ssid.Ssid[2], sizeof(ssid.Ssid)-2); + ssid.Ssid[0] = 0x1; + ssid.Ssid[1] = 0xff; + for (i = 2; i < sizeof(ssid.Ssid); i++) + ssid.Ssid[i] = 0x1 + (ssid.Ssid[i] * 0xfe / 0xff); + ret = set_essid(usbdev, &ssid); + } + return ret; +} + + +static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + __le32 tmp; + int auth_mode, ret; + + devdbg(usbdev, "set_auth_mode: wpa_version=0x%x authalg=0x%x " + "keymgmt=0x%x", wpa_version, authalg, priv->wpa_keymgmt); + + if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) { + if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X) + auth_mode = Ndis802_11AuthModeWPA2; + else + auth_mode = Ndis802_11AuthModeWPA2PSK; + } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) { + if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X) + auth_mode = Ndis802_11AuthModeWPA; + else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK) + auth_mode = Ndis802_11AuthModeWPAPSK; + else + auth_mode = Ndis802_11AuthModeWPANone; + } else if (authalg & IW_AUTH_ALG_SHARED_KEY) { + if (authalg & IW_AUTH_ALG_OPEN_SYSTEM) + auth_mode = Ndis802_11AuthModeAutoSwitch; + else + auth_mode = Ndis802_11AuthModeShared; + } else + auth_mode = Ndis802_11AuthModeOpen; + + tmp = cpu_to_le32(auth_mode); + ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp, + sizeof(tmp)); + if (ret != 0) { + devwarn(usbdev, "setting auth mode failed (%08X)", ret); + return ret; + } + + priv->wpa_version = wpa_version; + priv->wpa_authalg = authalg; + return 0; +} + + +static int set_priv_filter(struct usbnet *usbdev) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + __le32 tmp; + + devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version); + + if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 || + priv->wpa_version & IW_AUTH_WPA_VERSION_WPA) + tmp = cpu_to_le32(Ndis802_11PrivFilter8021xWEP); + else + tmp = cpu_to_le32(Ndis802_11PrivFilterAcceptAll); + + return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp, + sizeof(tmp)); +} + + +static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + __le32 tmp; + int encr_mode, ret; + + devdbg(usbdev, "set_encr_mode: cipher_pair=0x%x cipher_group=0x%x", + pairwise, + groupwise); + + if (pairwise & IW_AUTH_CIPHER_CCMP) + encr_mode = Ndis802_11Encryption3Enabled; + else if (pairwise & IW_AUTH_CIPHER_TKIP) + encr_mode = Ndis802_11Encryption2Enabled; + else if (pairwise & + (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) + encr_mode = Ndis802_11Encryption1Enabled; + else if (groupwise & IW_AUTH_CIPHER_CCMP) + encr_mode = Ndis802_11Encryption3Enabled; + else if (groupwise & IW_AUTH_CIPHER_TKIP) + encr_mode = Ndis802_11Encryption2Enabled; + else + encr_mode = Ndis802_11EncryptionDisabled; + + tmp = cpu_to_le32(encr_mode); + ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp, + sizeof(tmp)); + if (ret != 0) { + devwarn(usbdev, "setting encr mode failed (%08X)", ret); + return ret; + } + + priv->wpa_cipher_pair = pairwise; + priv->wpa_cipher_group = groupwise; + return 0; +} + + +static int set_assoc_params(struct usbnet *usbdev) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + set_auth_mode(usbdev, priv->wpa_version, priv->wpa_authalg); + set_priv_filter(usbdev); + set_encr_mode(usbdev, priv->wpa_cipher_pair, priv->wpa_cipher_group); + + return 0; +} + + +static int set_infra_mode(struct usbnet *usbdev, int mode) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + __le32 tmp; + int ret, i; + + devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode); + + tmp = cpu_to_le32(mode); + ret = rndis_set_oid(usbdev, OID_802_11_INFRASTRUCTURE_MODE, &tmp, + sizeof(tmp)); + if (ret != 0) { + devwarn(usbdev, "setting infra mode failed (%08X)", ret); + return ret; + } + + /* NDIS drivers clear keys when infrastructure mode is + * changed. But Linux tools assume otherwise. So set the + * keys */ + if (priv->wpa_keymgmt == 0 || + priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) { + for (i = 0; i < 4; i++) { + if (priv->encr_key_len[i] > 0) + add_wep_key(usbdev, priv->encr_keys[i], + priv->encr_key_len[i], i); + } + } + + priv->infra_mode = mode; + return 0; +} + + +static void set_default_iw_params(struct usbnet *usbdev) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + priv->wpa_keymgmt = 0; + priv->wpa_version = 0; + + set_infra_mode(usbdev, Ndis802_11Infrastructure); + set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED, + IW_AUTH_ALG_OPEN_SYSTEM); + set_priv_filter(usbdev); + set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE); +} + + +static int deauthenticate(struct usbnet *usbdev) +{ + int ret; + + ret = disassociate(usbdev, 1); + set_default_iw_params(usbdev); + return ret; +} + + +/* index must be 0 - N, as per NDIS */ +static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct NDIS_802_11_WEP ndis_key; + int ret; + + if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4) + return -EINVAL; + + memset(&ndis_key, 0, sizeof(ndis_key)); + + ndis_key.Length = cpu_to_le32(sizeof(ndis_key)); + ndis_key.KeyLength = cpu_to_le32(key_len); + ndis_key.KeyIndex = cpu_to_le32(index); + memcpy(&ndis_key.KeyMaterial, key, key_len); + + if (index == priv->encr_tx_key_index) { + ndis_key.KeyIndex |= cpu_to_le32(1 << 31); + ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104, + IW_AUTH_CIPHER_NONE); + if (ret) + devwarn(usbdev, "encryption couldn't be enabled (%08X)", + ret); + } + + ret = rndis_set_oid(usbdev, OID_802_11_ADD_WEP, &ndis_key, + sizeof(ndis_key)); + if (ret != 0) { + devwarn(usbdev, "adding encryption key %d failed (%08X)", + index+1, ret); + return ret; + } + + priv->encr_key_len[index] = key_len; + memcpy(&priv->encr_keys[index], key, key_len); + + return 0; +} + + +/* remove_key is for both wep and wpa */ +static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct NDIS_802_11_REMOVE_KEY remove_key; + __le32 keyindex; + int ret; + + if (priv->encr_key_len[index] == 0) + return 0; + + priv->encr_key_len[index] = 0; + memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index])); + + if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP || + priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP || + priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP || + priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) { + remove_key.Length = cpu_to_le32(sizeof(remove_key)); + remove_key.KeyIndex = cpu_to_le32(index); + if (bssid) { + /* pairwise key */ + if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0) + remove_key.KeyIndex |= cpu_to_le32(1 << 30); + memcpy(remove_key.Bssid, bssid, + sizeof(remove_key.Bssid)); + } else + memset(remove_key.Bssid, 0xff, + sizeof(remove_key.Bssid)); + + ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key, + sizeof(remove_key)); + if (ret != 0) + return ret; + } else { + keyindex = cpu_to_le32(index); + ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_WEP, &keyindex, + sizeof(keyindex)); + if (ret != 0) { + devwarn(usbdev, + "removing encryption key %d failed (%08X)", + index, ret); + return ret; + } + } + + /* if it is transmit key, disable encryption */ + if (index == priv->encr_tx_key_index) + set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE); + + return 0; +} + + +static void set_multicast_list(struct usbnet *usbdev) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct dev_mc_list *mclist; + __le32 filter; + int ret, i, size; + char *buf; + + filter = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; + + if (usbdev->net->flags & IFF_PROMISC) { + filter |= RNDIS_PACKET_TYPE_PROMISCUOUS | + RNDIS_PACKET_TYPE_ALL_LOCAL; + } else if (usbdev->net->flags & IFF_ALLMULTI || + usbdev->net->mc_count > priv->multicast_size) { + filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; + } else if (usbdev->net->mc_count > 0) { + size = min(priv->multicast_size, usbdev->net->mc_count); + buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); + if (!buf) { + devwarn(usbdev, + "couldn't alloc %d bytes of memory", + size * ETH_ALEN); + return; + } + + mclist = usbdev->net->mc_list; + for (i = 0; i < size && mclist; mclist = mclist->next) { + if (mclist->dmi_addrlen != ETH_ALEN) + continue; + + memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); + i++; + } + + ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, buf, + i * ETH_ALEN); + if (ret == 0 && i > 0) + filter |= RNDIS_PACKET_TYPE_MULTICAST; + else + filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; + + devdbg(usbdev, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d", + i, priv->multicast_size, ret); + + kfree(buf); + } + + ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, + sizeof(filter)); + if (ret < 0) { + devwarn(usbdev, "couldn't set packet filter: %08x", + le32_to_cpu(filter)); + } + + devdbg(usbdev, "OID_GEN_CURRENT_PACKET_FILTER(%08x) -> %d", + le32_to_cpu(filter), ret); +} + + +/* + * wireless extension handlers + */ + +static int rndis_iw_commit(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + /* dummy op */ + return 0; +} + + +static int rndis_iw_get_range(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + int len, ret, i, j, num, has_80211g_rates; + u8 rates[8]; + __le32 tx_power; + + devdbg(usbdev, "SIOCGIWRANGE"); + + /* clear iw_range struct */ + memset(range, 0, sizeof(*range)); + wrqu->data.length = sizeof(*range); + + range->txpower_capa = IW_TXPOW_MWATT; + range->num_txpower = 1; + if (priv->caps & CAP_SUPPORT_TXPOWER) { + len = sizeof(tx_power); + ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, + &tx_power, &len); + if (ret == 0 && le32_to_cpu(tx_power) != 0xFF) + range->txpower[0] = le32_to_cpu(tx_power); + else + range->txpower[0] = get_bcm4320_power(priv); + } else + range->txpower[0] = get_bcm4320_power(priv); + + len = sizeof(rates); + ret = rndis_query_oid(usbdev, OID_802_11_SUPPORTED_RATES, &rates, + &len); + has_80211g_rates = 0; + if (ret == 0) { + j = 0; + for (i = 0; i < len; i++) { + if (rates[i] == 0) + break; + range->bitrate[j] = (rates[i] & 0x7f) * 500000; + /* check for non 802.11b rates */ + if (range->bitrate[j] == 6000000 || + range->bitrate[j] == 9000000 || + (range->bitrate[j] >= 12000000 && + range->bitrate[j] != 22000000)) + has_80211g_rates = 1; + j++; + } + range->num_bitrates = j; + } else + range->num_bitrates = 0; + + /* fill in 802.11g rates */ + if (has_80211g_rates) { + num = range->num_bitrates; + for (i = 0; i < sizeof(rates_80211g); i++) { + for (j = 0; j < num; j++) { + if (range->bitrate[j] == + rates_80211g[i] * 1000000) + break; + } + if (j == num) + range->bitrate[range->num_bitrates++] = + rates_80211g[i] * 1000000; + if (range->num_bitrates == IW_MAX_BITRATES) + break; + } + + /* estimated max real througput in bps */ + range->throughput = 54 * 1000 * 1000 / 2; + + /* ~35% more with afterburner */ + if (priv->param_afterburner) + range->throughput = range->throughput / 100 * 135; + } else { + /* estimated max real througput in bps */ + range->throughput = 11 * 1000 * 1000 / 2; + } + + range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0])); + + for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) && + i < IW_MAX_FREQUENCIES; i++) { + range->freq[i].i = i + 1; + range->freq[i].m = freq_chan[i] * 100000; + range->freq[i].e = 1; + } + range->num_frequency = i; + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + + range->max_qual.qual = 100; + range->max_qual.level = 154; + range->max_qual.updated = IW_QUAL_QUAL_UPDATED + | IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_INVALID; + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = WIRELESS_EXT; + + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; + return 0; +} + + +static int rndis_iw_get_name(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + strcpy(wrqu->name, priv->name); + return 0; +} + + +static int rndis_iw_set_essid(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *essid) +{ + struct NDIS_802_11_SSID ssid; + int length = wrqu->essid.length; + struct usbnet *usbdev = dev->priv; + + devdbg(usbdev, "SIOCSIWESSID: [flags:%d,len:%d] '%.32s'", + wrqu->essid.flags, wrqu->essid.length, essid); + + if (length > NDIS_802_11_LENGTH_SSID) + length = NDIS_802_11_LENGTH_SSID; + + ssid.SsidLength = cpu_to_le32(length); + if (length > 0) + memcpy(ssid.Ssid, essid, length); + else + memset(ssid.Ssid, 0, NDIS_802_11_LENGTH_SSID); + + set_assoc_params(usbdev); + + if (!wrqu->essid.flags || length == 0) + return disassociate(usbdev, 1); + else + return set_essid(usbdev, &ssid); +} + + +static int rndis_iw_get_essid(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *essid) +{ + struct NDIS_802_11_SSID ssid; + struct usbnet *usbdev = dev->priv; + int ret; + + ret = get_essid(usbdev, &ssid); + + if (ret == 0 && le32_to_cpu(ssid.SsidLength) > 0) { + wrqu->essid.flags = 1; + wrqu->essid.length = le32_to_cpu(ssid.SsidLength); + memcpy(essid, ssid.Ssid, wrqu->essid.length); + essid[wrqu->essid.length] = 0; + } else { + memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID)); + wrqu->essid.flags = 0; + wrqu->essid.length = 0; + } + devdbg(usbdev, "SIOCGIWESSID: %s", essid); + return ret; +} + + +static int rndis_iw_get_bssid(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + unsigned char bssid[ETH_ALEN]; + int ret; + DECLARE_MAC_BUF(mac); + + ret = get_bssid(usbdev, bssid); + + if (ret == 0) + devdbg(usbdev, "SIOCGIWAP: %s", print_mac(mac, bssid)); + else + devdbg(usbdev, "SIOCGIWAP: <not associated>"); + + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN); + + return ret; +} + + +static int rndis_iw_set_bssid(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + u8 *bssid = (u8 *)wrqu->ap_addr.sa_data; + DECLARE_MAC_BUF(mac); + int ret; + + devdbg(usbdev, "SIOCSIWAP: %s", print_mac(mac, bssid)); + + ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN); + + /* user apps may set ap's mac address, which is not required; + * they may fail to work if this function fails, so return + * success */ + if (ret) + devwarn(usbdev, "setting AP mac address failed (%08X)", ret); + + return 0; +} + + +static int rndis_iw_set_auth(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct iw_param *p = &wrqu->param; + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + int ret = -ENOTSUPP; + + switch (p->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + devdbg(usbdev, "SIOCSIWAUTH: WPA_VERSION, %08x", p->value); + priv->wpa_version = p->value; + ret = 0; + break; + + case IW_AUTH_CIPHER_PAIRWISE: + devdbg(usbdev, "SIOCSIWAUTH: CIPHER_PAIRWISE, %08x", p->value); + priv->wpa_cipher_pair = p->value; + ret = 0; + break; + + case IW_AUTH_CIPHER_GROUP: + devdbg(usbdev, "SIOCSIWAUTH: CIPHER_GROUP, %08x", p->value); + priv->wpa_cipher_group = p->value; + ret = 0; + break; + + case IW_AUTH_KEY_MGMT: + devdbg(usbdev, "SIOCSIWAUTH: KEY_MGMT, %08x", p->value); + priv->wpa_keymgmt = p->value; + ret = 0; + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + devdbg(usbdev, "SIOCSIWAUTH: TKIP_COUNTERMEASURES, %08x", + p->value); + ret = 0; + break; + + case IW_AUTH_DROP_UNENCRYPTED: + devdbg(usbdev, "SIOCSIWAUTH: DROP_UNENCRYPTED, %08x", p->value); + ret = 0; + break; + + case IW_AUTH_80211_AUTH_ALG: + devdbg(usbdev, "SIOCSIWAUTH: 80211_AUTH_ALG, %08x", p->value); + priv->wpa_authalg = p->value; + ret = 0; + break; + + case IW_AUTH_WPA_ENABLED: + devdbg(usbdev, "SIOCSIWAUTH: WPA_ENABLED, %08x", p->value); + if (wrqu->param.value) + deauthenticate(usbdev); + ret = 0; + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + devdbg(usbdev, "SIOCSIWAUTH: RX_UNENCRYPTED_EAPOL, %08x", + p->value); + ret = 0; + break; + + case IW_AUTH_ROAMING_CONTROL: + devdbg(usbdev, "SIOCSIWAUTH: ROAMING_CONTROL, %08x", p->value); + ret = 0; + break; + + case IW_AUTH_PRIVACY_INVOKED: + devdbg(usbdev, "SIOCSIWAUTH: invalid cmd %d", + wrqu->param.flags & IW_AUTH_INDEX); + return -EOPNOTSUPP; + + default: + devdbg(usbdev, "SIOCSIWAUTH: UNKNOWN %08x, %08x", + p->flags & IW_AUTH_INDEX, p->value); + } + return ret; +} + + +static int rndis_iw_get_auth(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct iw_param *p = &wrqu->param; + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + switch (p->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + p->value = priv->wpa_version; + break; + case IW_AUTH_CIPHER_PAIRWISE: + p->value = priv->wpa_cipher_pair; + break; + case IW_AUTH_CIPHER_GROUP: + p->value = priv->wpa_cipher_group; + break; + case IW_AUTH_KEY_MGMT: + p->value = priv->wpa_keymgmt; + break; + case IW_AUTH_80211_AUTH_ALG: + p->value = priv->wpa_authalg; + break; + default: + devdbg(usbdev, "SIOCGIWAUTH: invalid cmd %d", + wrqu->param.flags & IW_AUTH_INDEX); + return -EOPNOTSUPP; + } + return 0; +} + + +static int rndis_iw_get_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + switch (priv->infra_mode) { + case Ndis802_11IBSS: + wrqu->mode = IW_MODE_ADHOC; + break; + case Ndis802_11Infrastructure: + wrqu->mode = IW_MODE_INFRA; + break; + /*case Ndis802_11AutoUnknown:*/ + default: + wrqu->mode = IW_MODE_AUTO; + break; + } + devdbg(usbdev, "SIOCGIWMODE: %08x", wrqu->mode); + return 0; +} + + +static int rndis_iw_set_mode(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + int mode; + + devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode); + + switch (wrqu->mode) { + case IW_MODE_ADHOC: + mode = Ndis802_11IBSS; + break; + case IW_MODE_INFRA: + mode = Ndis802_11Infrastructure; + break; + /*case IW_MODE_AUTO:*/ + default: + mode = Ndis802_11AutoUnknown; + break; + } + + return set_infra_mode(usbdev, mode); +} + + +static int rndis_iw_set_encode(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + int ret, index, key_len; + u8 *key; + + index = (wrqu->encoding.flags & IW_ENCODE_INDEX); + + /* iwconfig gives index as 1 - N */ + if (index > 0) + index--; + else + index = priv->encr_tx_key_index; + + if (index < 0 || index >= 4) { + devwarn(usbdev, "encryption index out of range (%u)", index); + return -EINVAL; + } + + /* remove key if disabled */ + if (wrqu->data.flags & IW_ENCODE_DISABLED) { + if (remove_key(usbdev, index, NULL)) + return -EINVAL; + else + return 0; + } + + /* global encryption state (for all keys) */ + if (wrqu->data.flags & IW_ENCODE_OPEN) + ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED, + IW_AUTH_ALG_OPEN_SYSTEM); + else /*if (wrqu->data.flags & IW_ENCODE_RESTRICTED)*/ + ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED, + IW_AUTH_ALG_SHARED_KEY); + if (ret != 0) + return ret; + + if (wrqu->data.length > 0) { + key_len = wrqu->data.length; + key = extra; + } else { + /* must be set as tx key */ + if (priv->encr_key_len[index] == 0) + return -EINVAL; + key_len = priv->encr_key_len[index]; + key = priv->encr_keys[index]; + priv->encr_tx_key_index = index; + } + + if (add_wep_key(usbdev, key, key_len, index) != 0) + return -EINVAL; + + if (index == priv->encr_tx_key_index) + /* ndis drivers want essid to be set after setting encr */ + set_essid(usbdev, &priv->essid); + + return 0; +} + + +static int rndis_iw_set_encode_ext(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct NDIS_802_11_KEY ndis_key; + int i, keyidx, ret; + u8 *addr; + + keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; + + /* iwconfig gives index as 1 - N */ + if (keyidx) + keyidx--; + else + keyidx = priv->encr_tx_key_index; + + if (keyidx < 0 || keyidx >= 4) + return -EINVAL; + + if (ext->alg == WPA_ALG_WEP) { + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + priv->encr_tx_key_index = keyidx; + return add_wep_key(usbdev, ext->key, ext->key_len, keyidx); + } + + if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) + return remove_key(usbdev, keyidx, NULL); + + if (ext->key_len > sizeof(ndis_key.KeyMaterial)) + return -1; + + memset(&ndis_key, 0, sizeof(ndis_key)); + + ndis_key.Length = cpu_to_le32(sizeof(ndis_key) - + sizeof(ndis_key.KeyMaterial) + ext->key_len); + ndis_key.KeyLength = cpu_to_le32(ext->key_len); + ndis_key.KeyIndex = cpu_to_le32(keyidx); + + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + for (i = 0; i < 6; i++) + ndis_key.KeyRSC |= + cpu_to_le64(ext->rx_seq[i] << (i * 8)); + ndis_key.KeyIndex |= cpu_to_le32(1 << 29); + } + + addr = ext->addr.sa_data; + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* group key */ + if (priv->infra_mode == Ndis802_11IBSS) + memset(ndis_key.Bssid, 0xff, ETH_ALEN); + else + get_bssid(usbdev, ndis_key.Bssid); + } else { + /* pairwise key */ + ndis_key.KeyIndex |= cpu_to_le32(1 << 30); + memcpy(ndis_key.Bssid, addr, ETH_ALEN); + } + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + ndis_key.KeyIndex |= cpu_to_le32(1 << 31); + + if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) { + /* wpa_supplicant gives us the Michael MIC RX/TX keys in + * different order than NDIS spec, so swap the order here. */ + memcpy(ndis_key.KeyMaterial, ext->key, 16); + memcpy(ndis_key.KeyMaterial + 16, ext->key + 24, 8); + memcpy(ndis_key.KeyMaterial + 24, ext->key + 16, 8); + } else + memcpy(ndis_key.KeyMaterial, ext->key, ext->key_len); + + ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key, + le32_to_cpu(ndis_key.Length)); + devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret); + if (ret != 0) + return ret; + + priv->encr_key_len[keyidx] = ext->key_len; + memcpy(&priv->encr_keys[keyidx], ndis_key.KeyMaterial, ext->key_len); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + priv->encr_tx_key_index = keyidx; + + return 0; +} + + +static int rndis_iw_set_scan(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct iw_param *param = &wrqu->param; + struct usbnet *usbdev = dev->priv; + union iwreq_data evt; + int ret = -EINVAL; + __le32 tmp; + + devdbg(usbdev, "SIOCSIWSCAN"); + + if (param->flags == 0) { + tmp = ccpu2(1); + ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, + sizeof(tmp)); + evt.data.flags = 0; + evt.data.length = 0; + wireless_send_event(dev, SIOCGIWSCAN, &evt, NULL); + } + return ret; +} + + +static char *rndis_translate_scan(struct net_device *dev, + char *cev, char *end_buf, struct NDIS_WLAN_BSSID_EX *bssid) +{ +#ifdef DEBUG + struct usbnet *usbdev = dev->priv; +#endif + struct ieee80211_info_element *ie; + char *current_val; + int bssid_len, ie_len, i; + u32 beacon, atim; + struct iw_event iwe; + unsigned char sbuf[32]; + DECLARE_MAC_BUF(mac); + + bssid_len = le32_to_cpu(bssid->Length); + + devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->MacAddress)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, bssid->MacAddress, ETH_ALEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); + + devdbg(usbdev, "SSID(%d) %s", + le32_to_cpu(bssid->Ssid.SsidLength), + bssid->Ssid.Ssid); + iwe.cmd = SIOCGIWESSID; + iwe.u.essid.length = le32_to_cpu(bssid->Ssid.SsidLength); + iwe.u.essid.flags = 1; + cev = iwe_stream_add_point(cev, end_buf, &iwe, + bssid->Ssid.Ssid); + + devdbg(usbdev, "MODE %d", + le32_to_cpu(bssid->InfrastructureMode)); + iwe.cmd = SIOCGIWMODE; + switch (le32_to_cpu(bssid->InfrastructureMode)) { + case Ndis802_11IBSS: + iwe.u.mode = IW_MODE_ADHOC; + break; + case Ndis802_11Infrastructure: + iwe.u.mode = IW_MODE_INFRA; + break; + /*case Ndis802_11AutoUnknown:*/ + default: + iwe.u.mode = IW_MODE_AUTO; + break; + } + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); + + devdbg(usbdev, "FREQ %d kHz", + le32_to_cpu(bssid->Configuration.DSConfig)); + iwe.cmd = SIOCGIWFREQ; + dsconfig_to_freq(le32_to_cpu(bssid->Configuration.DSConfig), + &iwe.u.freq); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); + + devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->Rssi)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->Rssi)); + iwe.u.qual.level = le32_to_cpu(bssid->Rssi); + iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED + | IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_INVALID; + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); + + devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy)); + iwe.cmd = SIOCGIWENCODE; + iwe.u.data.length = 0; + if (le32_to_cpu(bssid->Privacy) == Ndis802_11PrivFilterAcceptAll) + iwe.u.data.flags = IW_ENCODE_DISABLED; + else + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + + cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); + + devdbg(usbdev, "RATES:"); + current_val = cev + IW_EV_LCP_LEN; + iwe.cmd = SIOCGIWRATE; + for (i = 0; i < sizeof(bssid->SupportedRates); i++) { + if (bssid->SupportedRates[i] & 0x7f) { + iwe.u.bitrate.value = + ((bssid->SupportedRates[i] & 0x7f) * + 500000); + devdbg(usbdev, " %d", iwe.u.bitrate.value); + current_val = iwe_stream_add_value(cev, + current_val, end_buf, &iwe, + IW_EV_PARAM_LEN); + } + } + + if ((current_val - cev) > IW_EV_LCP_LEN) + cev = current_val; + + beacon = le32_to_cpu(bssid->Configuration.BeaconPeriod); + devdbg(usbdev, "BCN_INT %d", beacon); + iwe.cmd = IWEVCUSTOM; + snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon); + iwe.u.data.length = strlen(sbuf); + cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); + + atim = le32_to_cpu(bssid->Configuration.ATIMWindow); + devdbg(usbdev, "ATIM %d", atim); + iwe.cmd = IWEVCUSTOM; + snprintf(sbuf, sizeof(sbuf), "atim=%u", atim); + iwe.u.data.length = strlen(sbuf); + cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); + + ie = (void *)(bssid->IEs + sizeof(struct NDIS_802_11_FIXED_IEs)); + ie_len = min(bssid_len - (int)sizeof(*bssid), + (int)le32_to_cpu(bssid->IELength)); + ie_len -= sizeof(struct NDIS_802_11_FIXED_IEs); + while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) { + if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 && + memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) || + ie->id == MFIE_TYPE_RSN) { + devdbg(usbdev, "IE: WPA%d", + (ie->id == MFIE_TYPE_RSN) ? 2 : 1); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN); + cev = iwe_stream_add_point(cev, end_buf, &iwe, + (u8 *)ie); + } + + ie_len -= sizeof(*ie) + ie->len; + ie = (struct ieee80211_info_element *)&ie->data[ie->len]; + } + + return cev; +} + + +static int rndis_iw_get_scan(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + void *buf = NULL; + char *cev = extra; + struct NDIS_802_11_BSSID_LIST_EX *bssid_list; + struct NDIS_WLAN_BSSID_EX *bssid; + int ret = -EINVAL, len, count, bssid_len; + + devdbg(usbdev, "SIOCGIWSCAN"); + + len = CONTROL_BUFFER_SIZE; + buf = kmalloc(len, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out; + } + + ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); + + if (ret != 0) + goto out; + + bssid_list = buf; + bssid = bssid_list->Bssid; + bssid_len = le32_to_cpu(bssid->Length); + count = le32_to_cpu(bssid_list->NumberOfItems); + devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count); + + while (count && ((void *)bssid + bssid_len) <= (buf + len)) { + cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA, + bssid); + bssid = (void *)bssid + bssid_len; + bssid_len = le32_to_cpu(bssid->Length); + count--; + } + +out: + wrqu->data.length = cev - extra; + wrqu->data.flags = 0; + kfree(buf); + return ret; +} + + +static int rndis_iw_set_genie(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + int ret = 0; + +#ifdef DEBUG + int j; + u8 *gie = extra; + for (j = 0; j < wrqu->data.length; j += 8) + devdbg(usbdev, + "SIOCSIWGENIE %04x - " + "%02x %02x %02x %02x %02x %02x %02x %02x", j, + gie[j + 0], gie[j + 1], gie[j + 2], gie[j + 3], + gie[j + 4], gie[j + 5], gie[j + 6], gie[j + 7]); +#endif + /* clear existing IEs */ + if (priv->wpa_ie_len) { + kfree(priv->wpa_ie); + priv->wpa_ie_len = 0; + } + + /* set new IEs */ + priv->wpa_ie = kmalloc(wrqu->data.length, GFP_KERNEL); + if (priv->wpa_ie) { + priv->wpa_ie_len = wrqu->data.length; + memcpy(priv->wpa_ie, extra, priv->wpa_ie_len); + } else + ret = -ENOMEM; + return ret; +} + + +static int rndis_iw_get_genie(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + devdbg(usbdev, "SIOCGIWGENIE"); + + if (priv->wpa_ie_len == 0 || priv->wpa_ie == NULL) { + wrqu->data.length = 0; + return 0; + } + + if (wrqu->data.length < priv->wpa_ie_len) + return -E2BIG; + + wrqu->data.length = priv->wpa_ie_len; + memcpy(extra, priv->wpa_ie, priv->wpa_ie_len); + + return 0; +} + + +static int rndis_iw_set_rts(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + __le32 tmp; + devdbg(usbdev, "SIOCSIWRTS"); + + tmp = cpu_to_le32(wrqu->rts.value); + return rndis_set_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp, + sizeof(tmp)); +} + + +static int rndis_iw_get_rts(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + __le32 tmp; + int len, ret; + + len = sizeof(tmp); + ret = rndis_query_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp, &len); + if (ret == 0) { + wrqu->rts.value = le32_to_cpu(tmp); + wrqu->rts.flags = 1; + wrqu->rts.disabled = 0; + } + + devdbg(usbdev, "SIOCGIWRTS: %d", wrqu->rts.value); + + return ret; +} + + +static int rndis_iw_set_frag(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + __le32 tmp; + + devdbg(usbdev, "SIOCSIWFRAG"); + + tmp = cpu_to_le32(wrqu->frag.value); + return rndis_set_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp, + sizeof(tmp)); +} + + +static int rndis_iw_get_frag(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + __le32 tmp; + int len, ret; + + len = sizeof(tmp); + ret = rndis_query_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp, + &len); + if (ret == 0) { + wrqu->frag.value = le32_to_cpu(tmp); + wrqu->frag.flags = 1; + wrqu->frag.disabled = 0; + } + devdbg(usbdev, "SIOCGIWFRAG: %d", wrqu->frag.value); + return ret; +} + + +static int rndis_iw_set_nick(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + devdbg(usbdev, "SIOCSIWNICK"); + + priv->nick_len = wrqu->data.length; + if (priv->nick_len > 32) + priv->nick_len = 32; + + memcpy(priv->nick, extra, priv->nick_len); + return 0; +} + + +static int rndis_iw_get_nick(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + wrqu->data.flags = 1; + wrqu->data.length = priv->nick_len; + memcpy(extra, priv->nick, priv->nick_len); + + devdbg(usbdev, "SIOCGIWNICK: '%s'", priv->nick); + + return 0; +} + + +static int rndis_iw_set_freq(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct NDIS_802_11_CONFIGURATION config; + unsigned int dsconfig; + int len, ret; + + /* this OID is valid only when not associated */ + if (is_associated(usbdev)) + return 0; + + dsconfig = 0; + if (freq_to_dsconfig(&wrqu->freq, &dsconfig)) + return -EINVAL; + + len = sizeof(config); + ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); + if (ret != 0) { + devdbg(usbdev, "SIOCSIWFREQ: querying configuration failed"); + return 0; + } + + config.DSConfig = cpu_to_le32(dsconfig); + + devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e); + return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config, + sizeof(config)); +} + + +static int rndis_iw_get_freq(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct NDIS_802_11_CONFIGURATION config; + int len, ret; + + len = sizeof(config); + ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); + if (ret == 0) + dsconfig_to_freq(le32_to_cpu(config.DSConfig), &wrqu->freq); + + devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m); + return ret; +} + + +static int rndis_iw_get_txpower(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + __le32 tx_power; + int ret = 0, len; + + if (priv->radio_on) { + if (priv->caps & CAP_SUPPORT_TXPOWER) { + len = sizeof(tx_power); + ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, + &tx_power, &len); + if (ret != 0) + return ret; + } else + /* fake incase not supported */ + tx_power = cpu_to_le32(get_bcm4320_power(priv)); + + wrqu->txpower.flags = IW_TXPOW_MWATT; + wrqu->txpower.value = le32_to_cpu(tx_power); + wrqu->txpower.disabled = 0; + } else { + wrqu->txpower.flags = IW_TXPOW_MWATT; + wrqu->txpower.value = 0; + wrqu->txpower.disabled = 1; + } + + devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value); + + return ret; +} + + +static int rndis_iw_set_txpower(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + __le32 tx_power = 0; + int ret = 0; + + if (!wrqu->txpower.disabled) { + if (wrqu->txpower.flags == IW_TXPOW_MWATT) + tx_power = cpu_to_le32(wrqu->txpower.value); + else { /* wrqu->txpower.flags == IW_TXPOW_DBM */ + if (wrqu->txpower.value > 20) + tx_power = cpu_to_le32(128); + else if (wrqu->txpower.value < -43) + tx_power = cpu_to_le32(127); + else { + signed char tmp; + tmp = wrqu->txpower.value; + tmp = -12 - tmp; + tmp <<= 2; + tx_power = cpu_to_le32((unsigned char)tmp); + } + } + } + + devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power)); + + if (le32_to_cpu(tx_power) != 0) { + if (priv->caps & CAP_SUPPORT_TXPOWER) { + /* turn radio on first */ + if (!priv->radio_on) + disassociate(usbdev, 1); + + ret = rndis_set_oid(usbdev, OID_802_11_TX_POWER_LEVEL, + &tx_power, sizeof(tx_power)); + if (ret != 0) + ret = -EOPNOTSUPP; + return ret; + } else { + /* txpower unsupported, just turn radio on */ + if (!priv->radio_on) + return disassociate(usbdev, 1); + return 0; /* all ready on */ + } + } + + /* tx_power == 0, turn off radio */ + return disassociate(usbdev, 0); +} + + +static int rndis_iw_get_rate(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + __le32 tmp; + int ret, len; + + len = sizeof(tmp); + ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len); + if (ret == 0) { + wrqu->bitrate.value = le32_to_cpu(tmp) * 100; + wrqu->bitrate.disabled = 0; + wrqu->bitrate.flags = 1; + } + return ret; +} + + +static int rndis_iw_set_mlme(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + unsigned char bssid[ETH_ALEN]; + + get_bssid(usbdev, bssid); + + if (memcmp(bssid, mlme->addr.sa_data, ETH_ALEN)) + return -EINVAL; + + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + return deauthenticate(usbdev); + case IW_MLME_DISASSOC: + return disassociate(usbdev, priv->radio_on); + default: + return -EOPNOTSUPP; + } + + return 0; +} + + +static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + unsigned long flags; + + spin_lock_irqsave(&priv->stats_lock, flags); + memcpy(&priv->iwstats, &priv->privstats, sizeof(priv->iwstats)); + spin_unlock_irqrestore(&priv->stats_lock, flags); + + return &priv->iwstats; +} + + +#define IW_IOCTL(x) [(x) - SIOCSIWCOMMIT] +static const iw_handler rndis_iw_handler[] = +{ + IW_IOCTL(SIOCSIWCOMMIT) = rndis_iw_commit, + IW_IOCTL(SIOCGIWNAME) = rndis_iw_get_name, + IW_IOCTL(SIOCSIWFREQ) = rndis_iw_set_freq, + IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq, + IW_IOCTL(SIOCSIWMODE) = rndis_iw_set_mode, + IW_IOCTL(SIOCGIWMODE) = rndis_iw_get_mode, + IW_IOCTL(SIOCGIWRANGE) = rndis_iw_get_range, + IW_IOCTL(SIOCSIWAP) = rndis_iw_set_bssid, + IW_IOCTL(SIOCGIWAP) = rndis_iw_get_bssid, + IW_IOCTL(SIOCSIWSCAN) = rndis_iw_set_scan, + IW_IOCTL(SIOCGIWSCAN) = rndis_iw_get_scan, + IW_IOCTL(SIOCSIWESSID) = rndis_iw_set_essid, + IW_IOCTL(SIOCGIWESSID) = rndis_iw_get_essid, + IW_IOCTL(SIOCSIWNICKN) = rndis_iw_set_nick, + IW_IOCTL(SIOCGIWNICKN) = rndis_iw_get_nick, + IW_IOCTL(SIOCGIWRATE) = rndis_iw_get_rate, + IW_IOCTL(SIOCSIWRTS) = rndis_iw_set_rts, + IW_IOCTL(SIOCGIWRTS) = rndis_iw_get_rts, + IW_IOCTL(SIOCSIWFRAG) = rndis_iw_set_frag, + IW_IOCTL(SIOCGIWFRAG) = rndis_iw_get_frag, + IW_IOCTL(SIOCSIWTXPOW) = rndis_iw_set_txpower, + IW_IOCTL(SIOCGIWTXPOW) = rndis_iw_get_txpower, + IW_IOCTL(SIOCSIWENCODE) = rndis_iw_set_encode, + IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext, + IW_IOCTL(SIOCSIWAUTH) = rndis_iw_set_auth, + IW_IOCTL(SIOCGIWAUTH) = rndis_iw_get_auth, + IW_IOCTL(SIOCSIWGENIE) = rndis_iw_set_genie, + IW_IOCTL(SIOCGIWGENIE) = rndis_iw_get_genie, + IW_IOCTL(SIOCSIWMLME) = rndis_iw_set_mlme, +}; + +static const iw_handler rndis_wext_private_handler[] = { +}; + +static const struct iw_priv_args rndis_wext_private_args[] = { +}; + + +static const struct iw_handler_def rndis_iw_handlers = { + .num_standard = ARRAY_SIZE(rndis_iw_handler), + .num_private = ARRAY_SIZE(rndis_wext_private_handler), + .num_private_args = ARRAY_SIZE(rndis_wext_private_args), + .standard = (iw_handler *)rndis_iw_handler, + .private = (iw_handler *)rndis_wext_private_handler, + .private_args = (struct iw_priv_args *)rndis_wext_private_args, + .get_wireless_stats = rndis_get_wireless_stats, +}; + + +static void rndis_wext_worker(struct work_struct *work) +{ + struct rndis_wext_private *priv = + container_of(work, struct rndis_wext_private, work); + struct usbnet *usbdev = priv->usbdev; + union iwreq_data evt; + unsigned char bssid[ETH_ALEN]; + int ret; + + if (test_and_clear_bit(WORK_CONNECTION_EVENT, &priv->work_pending)) { + ret = get_bssid(usbdev, bssid); + + if (!ret) { + evt.data.flags = 0; + evt.data.length = 0; + memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN); + wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL); + } + } + + if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending)) + set_multicast_list(usbdev); +} + +static void rndis_wext_set_multicast_list(struct net_device *dev) +{ + struct usbnet *usbdev = dev->priv; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + + set_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending); + queue_work(priv->workqueue, &priv->work); +} + +static void rndis_wext_link_change(struct usbnet *dev, int state) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + union iwreq_data evt; + + if (state) { + /* queue work to avoid recursive calls into rndis_command */ + set_bit(WORK_CONNECTION_EVENT, &priv->work_pending); + queue_work(priv->workqueue, &priv->work); + } else { + evt.data.flags = 0; + evt.data.length = 0; + memset(evt.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(dev->net, SIOCGIWAP, &evt, NULL); + } +} + + +static int rndis_wext_get_caps(struct usbnet *dev) +{ + struct { + __le32 num_items; + __le32 items[8]; + } networks_supported; + int len, retval, i, n; + __le32 tx_power; + struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + + /* determine if supports setting txpower */ + len = sizeof(tx_power); + retval = rndis_query_oid(dev, OID_802_11_TX_POWER_LEVEL, &tx_power, + &len); + if (retval == 0 && le32_to_cpu(tx_power) != 0xFF) + priv->caps |= CAP_SUPPORT_TXPOWER; + + /* determine supported modes */ + len = sizeof(networks_supported); + retval = rndis_query_oid(dev, OID_802_11_NETWORK_TYPES_SUPPORTED, + &networks_supported, &len); + if (retval >= 0) { + n = le32_to_cpu(networks_supported.num_items); + if (n > 8) + n = 8; + for (i = 0; i < n; i++) { + switch (le32_to_cpu(networks_supported.items[i])) { + case Ndis802_11FH: + case Ndis802_11DS: + priv->caps |= CAP_MODE_80211B; + break; + case Ndis802_11OFDM5: + priv->caps |= CAP_MODE_80211A; + break; + case Ndis802_11OFDM24: + priv->caps |= CAP_MODE_80211G; + break; + } + } + if (priv->caps & CAP_MODE_80211A) + strcat(priv->name, "a"); + if (priv->caps & CAP_MODE_80211B) + strcat(priv->name, "b"); + if (priv->caps & CAP_MODE_80211G) + strcat(priv->name, "g"); + } + + return retval; +} + + +#define STATS_UPDATE_JIFFIES (HZ) +static void rndis_update_wireless_stats(struct work_struct *work) +{ + struct rndis_wext_private *priv = + container_of(work, struct rndis_wext_private, stats_work.work); + struct usbnet *usbdev = priv->usbdev; + struct iw_statistics iwstats; + __le32 rssi, tmp; + int len, ret, bitrate, j; + unsigned long flags; + int update_jiffies = STATS_UPDATE_JIFFIES; + void *buf; + + spin_lock_irqsave(&priv->stats_lock, flags); + memcpy(&iwstats, &priv->privstats, sizeof(iwstats)); + spin_unlock_irqrestore(&priv->stats_lock, flags); + + /* only update stats when connected */ + if (!is_associated(usbdev)) { + iwstats.qual.qual = 0; + iwstats.qual.level = 0; + iwstats.qual.updated = IW_QUAL_QUAL_UPDATED + | IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_INVALID + | IW_QUAL_QUAL_INVALID + | IW_QUAL_LEVEL_INVALID; + goto end; + } + + len = sizeof(rssi); + ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); + + devdbg(usbdev, "stats: OID_802_11_RSSI -> %d, rssi:%d", ret, + le32_to_cpu(rssi)); + if (ret == 0) { + memset(&iwstats.qual, 0, sizeof(iwstats.qual)); + iwstats.qual.qual = level_to_qual(le32_to_cpu(rssi)); + iwstats.qual.level = le32_to_cpu(rssi); + iwstats.qual.updated = IW_QUAL_QUAL_UPDATED + | IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_INVALID; + } + + memset(&iwstats.discard, 0, sizeof(iwstats.discard)); + + len = sizeof(tmp); + ret = rndis_query_oid(usbdev, OID_GEN_XMIT_ERROR, &tmp, &len); + if (ret == 0) + iwstats.discard.misc += le32_to_cpu(tmp); + + len = sizeof(tmp); + ret = rndis_query_oid(usbdev, OID_GEN_RCV_ERROR, &tmp, &len); + if (ret == 0) + iwstats.discard.misc += le32_to_cpu(tmp); + + len = sizeof(tmp); + ret = rndis_query_oid(usbdev, OID_GEN_RCV_NO_BUFFER, &tmp, &len); + if (ret == 0) + iwstats.discard.misc += le32_to_cpu(tmp); + + /* Workaround transfer stalls on poor quality links. */ + len = sizeof(tmp); + ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len); + if (ret == 0) { + bitrate = le32_to_cpu(tmp) * 100; + if (bitrate > 11000000) + goto end; + + /* Decrease stats worker interval to catch stalls. + * faster. Faster than 400-500ms causes packet loss, + * Slower doesn't catch stalls fast enough. + */ + j = msecs_to_jiffies(priv->param_workaround_interval); + if (j > STATS_UPDATE_JIFFIES) + j = STATS_UPDATE_JIFFIES; + else if (j <= 0) + j = 1; + update_jiffies = j; + + /* Send scan OID. Use of both OIDs is required to get device + * working. + */ + tmp = ccpu2(1); + rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, + sizeof(tmp)); + + len = CONTROL_BUFFER_SIZE; + buf = kmalloc(len, GFP_KERNEL); + if (!buf) + goto end; + + rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); + kfree(buf); + } +end: + spin_lock_irqsave(&priv->stats_lock, flags); + memcpy(&priv->privstats, &iwstats, sizeof(iwstats)); + spin_unlock_irqrestore(&priv->stats_lock, flags); + + if (update_jiffies >= HZ) + update_jiffies = round_jiffies_relative(update_jiffies); + else { + j = round_jiffies_relative(update_jiffies); + if (abs(j - update_jiffies) <= 10) + update_jiffies = j; + } + + queue_delayed_work(priv->workqueue, &priv->stats_work, update_jiffies); +} + + +static int bcm4320_early_init(struct usbnet *dev) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + char buf[8]; + + /* Early initialization settings, setting these won't have effect + * if called after generic_rndis_bind(). + */ + + priv->param_country[0] = modparam_country[0]; + priv->param_country[1] = modparam_country[1]; + priv->param_country[2] = 0; + priv->param_frameburst = modparam_frameburst; + priv->param_afterburner = modparam_afterburner; + priv->param_power_save = modparam_power_save; + priv->param_power_output = modparam_power_output; + priv->param_roamtrigger = modparam_roamtrigger; + priv->param_roamdelta = modparam_roamdelta; + priv->param_workaround_interval = modparam_workaround_interval; + + priv->param_country[0] = toupper(priv->param_country[0]); + priv->param_country[1] = toupper(priv->param_country[1]); + /* doesn't support EU as country code, use FI instead */ + if (!strcmp(priv->param_country, "EU")) + strcpy(priv->param_country, "FI"); + + if (priv->param_power_save < 0) + priv->param_power_save = 0; + else if (priv->param_power_save > 2) + priv->param_power_save = 2; + + if (priv->param_roamtrigger < -80) + priv->param_roamtrigger = -80; + else if (priv->param_roamtrigger > -60) + priv->param_roamtrigger = -60; + + if (priv->param_roamdelta < 0) + priv->param_roamdelta = 0; + else if (priv->param_roamdelta > 2) + priv->param_roamdelta = 2; + + if (priv->param_workaround_interval < 0) + priv->param_workaround_interval = 500; + + rndis_set_config_parameter_str(dev, "Country", priv->param_country); + rndis_set_config_parameter_str(dev, "FrameBursting", + priv->param_frameburst ? "1" : "0"); + rndis_set_config_parameter_str(dev, "Afterburner", + priv->param_afterburner ? "1" : "0"); + sprintf(buf, "%d", priv->param_power_save); + rndis_set_config_parameter_str(dev, "PowerSaveMode", buf); + sprintf(buf, "%d", priv->param_power_output); + rndis_set_config_parameter_str(dev, "PwrOut", buf); + sprintf(buf, "%d", priv->param_roamtrigger); + rndis_set_config_parameter_str(dev, "RoamTrigger", buf); + sprintf(buf, "%d", priv->param_roamdelta); + rndis_set_config_parameter_str(dev, "RoamDelta", buf); + + return 0; +} + + +static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf) +{ + struct net_device *net = dev->net; + struct rndis_wext_private *priv; + int retval, len; + __le32 tmp; + + /* allocate rndis private data */ + priv = kmalloc(sizeof(struct rndis_wext_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* These have to be initialized before calling generic_rndis_bind(). + * Otherwise we'll be in big trouble in rndis_wext_early_init(). + */ + dev->driver_priv = priv; + memset(priv, 0, sizeof(*priv)); + memset(priv->name, 0, sizeof(priv->name)); + strcpy(priv->name, "IEEE802.11"); + net->wireless_handlers = &rndis_iw_handlers; + priv->usbdev = dev; + + mutex_init(&priv->command_lock); + spin_lock_init(&priv->stats_lock); + + /* try bind rndis_host */ + retval = generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_WIRELESS); + if (retval < 0) + goto fail; + + /* generic_rndis_bind set packet filter to multicast_all+ + * promisc mode which doesn't work well for our devices (device + * picks up rssi to closest station instead of to access point). + * + * rndis_host wants to avoid all OID as much as possible + * so do promisc/multicast handling in rndis_wext. + */ + dev->net->set_multicast_list = rndis_wext_set_multicast_list; + tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; + retval = rndis_set_oid(dev, OID_GEN_CURRENT_PACKET_FILTER, &tmp, + sizeof(tmp)); + + len = sizeof(tmp); + retval = rndis_query_oid(dev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp, &len); + priv->multicast_size = le32_to_cpu(tmp); + if (retval < 0 || priv->multicast_size < 0) + priv->multicast_size = 0; + if (priv->multicast_size > 0) + dev->net->flags |= IFF_MULTICAST; + else + dev->net->flags &= ~IFF_MULTICAST; + + priv->iwstats.qual.qual = 0; + priv->iwstats.qual.level = 0; + priv->iwstats.qual.updated = IW_QUAL_QUAL_UPDATED + | IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_INVALID + | IW_QUAL_QUAL_INVALID + | IW_QUAL_LEVEL_INVALID; + + rndis_wext_get_caps(dev); + set_default_iw_params(dev); + + /* turn radio on */ + priv->radio_on = 1; + disassociate(dev, 1); + + /* because rndis_command() sleeps we need to use workqueue */ + priv->workqueue = create_singlethread_workqueue("rndis_wlan"); + INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats); + queue_delayed_work(priv->workqueue, &priv->stats_work, + round_jiffies_relative(STATS_UPDATE_JIFFIES)); + INIT_WORK(&priv->work, rndis_wext_worker); + + return 0; + +fail: + kfree(priv); + return retval; +} + + +static void rndis_wext_unbind(struct usbnet *dev, struct usb_interface *intf) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + + /* turn radio off */ + disassociate(dev, 0); + + cancel_delayed_work_sync(&priv->stats_work); + cancel_work_sync(&priv->work); + flush_workqueue(priv->workqueue); + destroy_workqueue(priv->workqueue); + + if (priv && priv->wpa_ie_len) + kfree(priv->wpa_ie); + kfree(priv); + + rndis_unbind(dev, intf); +} + + +static int rndis_wext_reset(struct usbnet *dev) +{ + return deauthenticate(dev); +} + + +static const struct driver_info bcm4320b_info = { + .description = "Wireless RNDIS device, BCM4320b based", + .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .bind = rndis_wext_bind, + .unbind = rndis_wext_unbind, + .status = rndis_status, + .rx_fixup = rndis_rx_fixup, + .tx_fixup = rndis_tx_fixup, + .reset = rndis_wext_reset, + .early_init = bcm4320_early_init, + .link_change = rndis_wext_link_change, +}; + +static const struct driver_info bcm4320a_info = { + .description = "Wireless RNDIS device, BCM4320a based", + .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .bind = rndis_wext_bind, + .unbind = rndis_wext_unbind, + .status = rndis_status, + .rx_fixup = rndis_rx_fixup, + .tx_fixup = rndis_tx_fixup, + .reset = rndis_wext_reset, + .early_init = bcm4320_early_init, + .link_change = rndis_wext_link_change, +}; + +static const struct driver_info rndis_wext_info = { + .description = "Wireless RNDIS device", + .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .bind = rndis_wext_bind, + .unbind = rndis_wext_unbind, + .status = rndis_status, + .rx_fixup = rndis_rx_fixup, + .tx_fixup = rndis_tx_fixup, + .reset = rndis_wext_reset, + .early_init = bcm4320_early_init, + .link_change = rndis_wext_link_change, +}; + +/*-------------------------------------------------------------------------*/ + +static const struct usb_device_id products [] = { +#define RNDIS_MASTER_INTERFACE \ + .bInterfaceClass = USB_CLASS_COMM, \ + .bInterfaceSubClass = 2 /* ACM */, \ + .bInterfaceProtocol = 0x0ff + +/* INF driver for these devices have DriverVer >= 4.xx.xx.xx and many custom + * parameters available. Chipset marked as 'BCM4320SKFBG' in NDISwrapper-wiki. + */ +{ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0411, + .idProduct = 0x00bc, /* Buffalo WLI-U2-KG125S */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0baf, + .idProduct = 0x011b, /* U.S. Robotics USR5421 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x050d, + .idProduct = 0x011b, /* Belkin F5D7051 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x1799, /* Belkin has two vendor ids */ + .idProduct = 0x011b, /* Belkin F5D7051 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x13b1, + .idProduct = 0x0014, /* Linksys WUSB54GSv2 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x13b1, + .idProduct = 0x0026, /* Linksys WUSB54GSC */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0b05, + .idProduct = 0x1717, /* Asus WL169gE */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0a5c, + .idProduct = 0xd11b, /* Eminent EM4045 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x1690, + .idProduct = 0x0715, /* BT Voyager 1055 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320b_info, +}, +/* These devices have DriverVer < 4.xx.xx.xx and do not have any custom + * parameters available, hardware probably contain older firmware version with + * no way of updating. Chipset marked as 'BCM4320????' in NDISwrapper-wiki. + */ +{ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x13b1, + .idProduct = 0x000e, /* Linksys WUSB54GSv1 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320a_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0baf, + .idProduct = 0x0111, /* U.S. Robotics USR5420 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320a_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0411, + .idProduct = 0x004b, /* BUFFALO WLI-USB-G54 */ + RNDIS_MASTER_INTERFACE, + .driver_info = (unsigned long) &bcm4320a_info, +}, +/* Generic Wireless RNDIS devices that we don't have exact + * idVendor/idProduct/chip yet. + */ +{ + /* RNDIS is MSFT's un-official variant of CDC ACM */ + USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), + .driver_info = (unsigned long) &rndis_wext_info, +}, { + /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */ + USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1), + .driver_info = (unsigned long) &rndis_wext_info, +}, + { }, // END +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver rndis_wlan_driver = { + .name = "rndis_wlan", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, +}; + +static int __init rndis_wlan_init(void) +{ + return usb_register(&rndis_wlan_driver); +} +module_init(rndis_wlan_init); + +static void __exit rndis_wlan_exit(void) +{ + usb_deregister(&rndis_wlan_driver); +} +module_exit(rndis_wlan_exit); + +MODULE_AUTHOR("Bjorge Dijkstra"); +MODULE_AUTHOR("Jussi Kivilinna"); +MODULE_DESCRIPTION("Driver for RNDIS based USB Wireless adapters"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ab52f22..b31f0c2 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1736,7 +1736,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) WARNING(rt2x00dev, "TX status report missed for entry %p\n", entry_done); - rt2x00lib_txdone(entry_done, TX_FAIL_OTHER, 0); + rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER, + 0); entry_done = rt2x00_get_data_entry_done(ring); } diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 07f37b0..27ebd68 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -36,6 +36,7 @@ MODULE_LICENSE("GPL"); static struct pci_device_id rtl8180_table[] __devinitdata = { /* rtl8185 */ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, + { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) }, /* rtl8180 */ diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h index 1fede7f..08c9793 100644 --- a/include/asm-alpha/socket.h +++ b/include/asm-alpha/socket.h @@ -60,4 +60,6 @@ #define SO_SECURITY_ENCRYPTION_TRANSPORT 20 #define SO_SECURITY_ENCRYPTION_NETWORK 21 +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-arm/socket.h b/include/asm-arm/socket.h index 65a1a64..6817be9 100644 --- a/include/asm-arm/socket.h +++ b/include/asm-arm/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-avr32/socket.h b/include/asm-avr32/socket.h index a0d0507..35863f2 100644 --- a/include/asm-avr32/socket.h +++ b/include/asm-avr32/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* __ASM_AVR32_SOCKET_H */ diff --git a/include/asm-blackfin/socket.h b/include/asm-blackfin/socket.h index 5213c96..2ca702e 100644 --- a/include/asm-blackfin/socket.h +++ b/include/asm-blackfin/socket.h @@ -50,4 +50,7 @@ #define SO_PASSSEC 34 #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS + +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-cris/socket.h b/include/asm-cris/socket.h index 5b18dfd..9df0ca8 100644 --- a/include/asm-cris/socket.h +++ b/include/asm-cris/socket.h @@ -54,6 +54,8 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-frv/socket.h b/include/asm-frv/socket.h index a823bef..e51ca67 100644 --- a/include/asm-frv/socket.h +++ b/include/asm-frv/socket.h @@ -52,5 +52,7 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-h8300/socket.h b/include/asm-h8300/socket.h index 39911d8..da2520d 100644 --- a/include/asm-h8300/socket.h +++ b/include/asm-h8300/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h index 9e42ce4..d5ef0aa 100644 --- a/include/asm-ia64/socket.h +++ b/include/asm-ia64/socket.h @@ -61,4 +61,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_IA64_SOCKET_H */ diff --git a/include/asm-m32r/socket.h b/include/asm-m32r/socket.h index 793d5d3..9a0e200 100644 --- a/include/asm-m32r/socket.h +++ b/include/asm-m32r/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_M32R_SOCKET_H */ diff --git a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h index 6d21b90..dbc64e9 100644 --- a/include/asm-m68k/socket.h +++ b/include/asm-m68k/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h index 9594568..63f60254 100644 --- a/include/asm-mips/socket.h +++ b/include/asm-mips/socket.h @@ -73,6 +73,8 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #ifdef __KERNEL__ /** sock_type - Socket types diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h index 99e868f..69a7a0d 100644 --- a/include/asm-parisc/socket.h +++ b/include/asm-parisc/socket.h @@ -52,4 +52,6 @@ #define SO_PEERSEC 0x401d #define SO_PASSSEC 0x401e +#define SO_MARK 0x401f + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-powerpc/socket.h b/include/asm-powerpc/socket.h index 403e9fd..f5a4e168 100644 --- a/include/asm-powerpc/socket.h +++ b/include/asm-powerpc/socket.h @@ -59,4 +59,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/include/asm-s390/socket.h b/include/asm-s390/socket.h index 1161ebe..c786ab6 100644 --- a/include/asm-s390/socket.h +++ b/include/asm-s390/socket.h @@ -60,4 +60,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-sh/socket.h b/include/asm-sh/socket.h index c48d6fc..6d4bf65 100644 --- a/include/asm-sh/socket.h +++ b/include/asm-sh/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* __ASM_SH_SOCKET_H */ diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h index 7c14239..2e2bd0b 100644 --- a/include/asm-sparc/socket.h +++ b/include/asm-sparc/socket.h @@ -52,6 +52,8 @@ #define SO_TIMESTAMPNS 0x0021 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 0x0022 + /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h index 986441d..44a625a 100644 --- a/include/asm-sparc64/socket.h +++ b/include/asm-sparc64/socket.h @@ -57,4 +57,5 @@ #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 #define SO_SECURITY_ENCRYPTION_NETWORK 0x5004 +#define SO_MARK 0x0022 #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h index a4c2493..e199a2b 100644 --- a/include/asm-v850/socket.h +++ b/include/asm-v850/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* __V850_SOCKET_H__ */ diff --git a/include/asm-x86/socket.h b/include/asm-x86/socket.h index 99ca648..80af9c4 100644 --- a/include/asm-x86/socket.h +++ b/include/asm-x86/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h index 1f5aeac..6100682 100644 --- a/include/asm-xtensa/socket.h +++ b/include/asm-xtensa/socket.h @@ -63,4 +63,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _XTENSA_SOCKET_H */ diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 8d9eaae..fc4e3db 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -17,8 +17,6 @@ struct ipv4_devconf DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1); }; -extern struct ipv4_devconf ipv4_devconf; - struct in_device { struct net_device *dev; diff --git a/include/linux/input.h b/include/linux/input.h index 2075d6d..056a17a 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -371,6 +371,8 @@ struct input_absinfo { #define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */ #define KEY_DISPLAY_OFF 245 /* display device to off state */ +#define KEY_WIMAX 246 + #define BTN_MISC 0x100 #define BTN_0 0x100 #define BTN_1 0x101 diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 5d35a4c..4aaefc3 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -457,14 +457,22 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk) #define inet_v6_ipv6only(__sk) 0 #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -#define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\ - (((__sk)->sk_hash == (__hash)) && \ +#define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\ + (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \ ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ ((__sk)->sk_family == AF_INET6) && \ ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \ ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) +#define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \ + (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \ + (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports)) && \ + ((__sk)->sk_family == PF_INET6) && \ + (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr))) && \ + (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr))) && \ + (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) + #endif /* __KERNEL__ */ #endif /* _IPV6_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b0813c3..047d432 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1414,12 +1414,16 @@ extern void dev_set_rx_mode(struct net_device *dev); extern void __dev_set_rx_mode(struct net_device *dev); extern int dev_unicast_delete(struct net_device *dev, void *addr, int alen); extern int dev_unicast_add(struct net_device *dev, void *addr, int alen); +extern int dev_unicast_sync(struct net_device *to, struct net_device *from); +extern void dev_unicast_unsync(struct net_device *to, struct net_device *from); extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); extern int dev_mc_sync(struct net_device *to, struct net_device *from); extern void dev_mc_unsync(struct net_device *to, struct net_device *from); extern int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all); extern int __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly); +extern int __dev_addr_sync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count); +extern void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count); extern void dev_set_promiscuity(struct net_device *dev, int inc); extern void dev_set_allmulti(struct net_device *dev, int inc); extern void netdev_state_change(struct net_device *dev); diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h index 2343549..3bbde0c 100644 --- a/include/linux/netfilter/nf_conntrack_pptp.h +++ b/include/linux/netfilter/nf_conntrack_pptp.h @@ -4,7 +4,7 @@ #include <linux/netfilter/nf_conntrack_common.h> -extern const char *pptp_msg_name[]; +extern const char *const pptp_msg_name[]; /* state of the control session */ enum pptp_ctrlsess_state { diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index 9fff197..8e5ce1c 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -30,9 +30,9 @@ extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, struct nf_conntrack_expect *exp, const char *dptr); -extern int ct_sip_get_info(struct nf_conn *ct, const char *dptr, size_t dlen, - unsigned int *matchoff, unsigned int *matchlen, - enum sip_header_pos pos); +extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr, + size_t dlen, unsigned int *matchoff, + unsigned int *matchlen, enum sip_header_pos pos); extern int ct_sip_lnlen(const char *line, const char *limit); extern const char *ct_sip_search(const char *needle, const char *haystack, size_t needle_len, size_t haystack_len, diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index b99ede5..b2c62cc 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -214,7 +214,7 @@ struct xt_match /* Free to use by each match */ unsigned long data; - char *table; + const char *table; unsigned int matchsize; unsigned int compatsize; unsigned int hooks; @@ -261,7 +261,7 @@ struct xt_target /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; - char *table; + const char *table; unsigned int targetsize; unsigned int compatsize; unsigned int hooks; @@ -277,7 +277,7 @@ struct xt_table struct list_head list; /* A unique name... */ - char name[XT_TABLE_MAXNAMELEN]; + const char name[XT_TABLE_MAXNAMELEN]; /* What hooks you will enter on */ unsigned int valid_hooks; @@ -335,9 +335,10 @@ extern int xt_check_target(const struct xt_target *target, unsigned short family unsigned int size, const char *table, unsigned int hook, unsigned short proto, int inv_proto); -extern int xt_register_table(struct xt_table *table, - struct xt_table_info *bootstrap, - struct xt_table_info *newinfo); +extern struct xt_table *xt_register_table(struct net *net, + struct xt_table *table, + struct xt_table_info *bootstrap, + struct xt_table_info *newinfo); extern void *xt_unregister_table(struct xt_table *table); extern struct xt_table_info *xt_replace_table(struct xt_table *table, @@ -352,11 +353,12 @@ extern struct xt_target *xt_request_find_target(int af, const char *name, extern int xt_find_revision(int af, const char *name, u8 revision, int target, int *err); -extern struct xt_table *xt_find_table_lock(int af, const char *name); +extern struct xt_table *xt_find_table_lock(struct net *net, int af, + const char *name); extern void xt_table_unlock(struct xt_table *t); -extern int xt_proto_init(int af); -extern void xt_proto_fini(int af); +extern int xt_proto_init(struct net *net, int af); +extern void xt_proto_fini(struct net *net, int af); extern struct xt_table_info *xt_alloc_table_info(unsigned int size); extern void xt_free_table_info(struct xt_table_info *info); @@ -430,15 +432,15 @@ extern short xt_compat_calc_jump(int af, unsigned int offset); extern int xt_compat_match_offset(struct xt_match *match); extern int xt_compat_match_from_user(struct xt_entry_match *m, - void **dstptr, int *size); + void **dstptr, unsigned int *size); extern int xt_compat_match_to_user(struct xt_entry_match *m, - void __user **dstptr, int *size); + void __user **dstptr, unsigned int *size); extern int xt_compat_target_offset(struct xt_target *target); extern void xt_compat_target_from_user(struct xt_entry_target *t, - void **dstptr, int *size); + void **dstptr, unsigned int *size); extern int xt_compat_target_to_user(struct xt_entry_target *t, - void __user **dstptr, int *size); + void __user **dstptr, unsigned int *size); #endif /* CONFIG_COMPAT */ #endif /* __KERNEL__ */ diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index d2492a3..f3fd83e 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h @@ -6,9 +6,6 @@ #define _XT_CONNTRACK_H #include <linux/netfilter/nf_conntrack_tuple_common.h> -#ifdef __KERNEL__ -# include <linux/in.h> -#endif #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) #define XT_CONNTRACK_STATE_INVALID (1 << 0) @@ -18,14 +15,21 @@ #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) /* flags, invflags: */ -#define XT_CONNTRACK_STATE 0x01 -#define XT_CONNTRACK_PROTO 0x02 -#define XT_CONNTRACK_ORIGSRC 0x04 -#define XT_CONNTRACK_ORIGDST 0x08 -#define XT_CONNTRACK_REPLSRC 0x10 -#define XT_CONNTRACK_REPLDST 0x20 -#define XT_CONNTRACK_STATUS 0x40 -#define XT_CONNTRACK_EXPIRES 0x80 +enum { + XT_CONNTRACK_STATE = 1 << 0, + XT_CONNTRACK_PROTO = 1 << 1, + XT_CONNTRACK_ORIGSRC = 1 << 2, + XT_CONNTRACK_ORIGDST = 1 << 3, + XT_CONNTRACK_REPLSRC = 1 << 4, + XT_CONNTRACK_REPLDST = 1 << 5, + XT_CONNTRACK_STATUS = 1 << 6, + XT_CONNTRACK_EXPIRES = 1 << 7, + XT_CONNTRACK_ORIGSRC_PORT = 1 << 8, + XT_CONNTRACK_ORIGDST_PORT = 1 << 9, + XT_CONNTRACK_REPLSRC_PORT = 1 << 10, + XT_CONNTRACK_REPLDST_PORT = 1 << 11, + XT_CONNTRACK_DIRECTION = 1 << 12, +}; /* This is exposed to userspace, so remains frozen in time. */ struct ip_conntrack_old_tuple @@ -70,8 +74,10 @@ struct xt_conntrack_mtinfo1 { union nf_inet_addr repldst_addr, repldst_mask; u_int32_t expires_min, expires_max; u_int16_t l4proto; + __be16 origsrc_port, origdst_port; + __be16 replsrc_port, repldst_port; + u_int16_t match_flags, invert_flags; u_int8_t state_mask, status_mask; - u_int8_t match_flags, invert_flags; }; #endif /*_XT_CONNTRACK_H*/ diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h index c19972e..58b818e 100644 --- a/include/linux/netfilter/xt_hashlimit.h +++ b/include/linux/netfilter/xt_hashlimit.h @@ -9,13 +9,16 @@ /* details of this structure hidden by the implementation */ struct xt_hashlimit_htable; -#define XT_HASHLIMIT_HASH_DIP 0x0001 -#define XT_HASHLIMIT_HASH_DPT 0x0002 -#define XT_HASHLIMIT_HASH_SIP 0x0004 -#define XT_HASHLIMIT_HASH_SPT 0x0008 +enum { + XT_HASHLIMIT_HASH_DIP = 1 << 0, + XT_HASHLIMIT_HASH_DPT = 1 << 1, + XT_HASHLIMIT_HASH_SIP = 1 << 2, + XT_HASHLIMIT_HASH_SPT = 1 << 3, + XT_HASHLIMIT_INVERT = 1 << 4, +}; struct hashlimit_cfg { - u_int32_t mode; /* bitmask of IPT_HASHLIMIT_HASH_* */ + u_int32_t mode; /* bitmask of XT_HASHLIMIT_HASH_* */ u_int32_t avg; /* Average secs between packets * scale */ u_int32_t burst; /* Period multiplier for upper limit. */ @@ -37,4 +40,28 @@ struct xt_hashlimit_info { struct xt_hashlimit_info *master; } u; }; + +struct hashlimit_cfg1 { + u_int32_t mode; /* bitmask of XT_HASHLIMIT_HASH_* */ + u_int32_t avg; /* Average secs between packets * scale */ + u_int32_t burst; /* Period multiplier for upper limit. */ + + /* user specified */ + u_int32_t size; /* how many buckets */ + u_int32_t max; /* max number of entries */ + u_int32_t gc_interval; /* gc interval */ + u_int32_t expire; /* when do entries expire? */ + + u_int8_t srcmask, dstmask; +}; + +struct xt_hashlimit_mtinfo1 { + char name[IFNAMSIZ]; + struct hashlimit_cfg1 cfg; + + /* Used internally by the kernel */ + struct xt_hashlimit_htable *hinfo __attribute__((aligned(8))); + struct xt_hashlimit_mtinfo1 *master __attribute__((aligned(8))); +}; + #endif /*_XT_HASHLIMIT_H*/ diff --git a/include/linux/netfilter/xt_owner.h b/include/linux/netfilter/xt_owner.h index eacd34e..c84e52c 100644 --- a/include/linux/netfilter/xt_owner.h +++ b/include/linux/netfilter/xt_owner.h @@ -8,8 +8,8 @@ enum { }; struct xt_owner_match_info { - u_int32_t uid; - u_int32_t gid; + u_int32_t uid_min, uid_max; + u_int32_t gid_min, gid_max; u_int8_t match, invert; }; diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 53dd4df..db223ca 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -271,8 +271,9 @@ struct arpt_error xt_register_target(tgt); }) #define arpt_unregister_target(tgt) xt_unregister_target(tgt) -extern int arpt_register_table(struct arpt_table *table, - const struct arpt_replace *repl); +extern struct arpt_table *arpt_register_table(struct net *net, + struct arpt_table *table, + const struct arpt_replace *repl); extern void arpt_unregister_table(struct arpt_table *table); extern unsigned int arpt_do_table(struct sk_buff *skb, unsigned int hook, diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 45fcad9..bfc889f 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -244,8 +244,9 @@ ipt_get_target(struct ipt_entry *e) #include <linux/init.h> extern void ipt_init(void) __init; -extern int ipt_register_table(struct xt_table *table, - const struct ipt_replace *repl); +extern struct xt_table *ipt_register_table(struct net *net, + struct xt_table *table, + const struct ipt_replace *repl); extern void ipt_unregister_table(struct xt_table *table); /* Standard entry. */ diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 110801d..f2507dc 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -305,8 +305,9 @@ ip6t_get_target(struct ip6t_entry *e) #include <linux/init.h> extern void ip6t_init(void) __init; -extern int ip6t_register_table(struct xt_table *table, - const struct ip6t_replace *repl); +extern struct xt_table *ip6t_register_table(struct net *net, + struct xt_table *table, + const struct ip6t_replace *repl); extern void ip6t_unregister_table(struct xt_table *table); extern unsigned int ip6t_do_table(struct sk_buff *skb, unsigned int hook, diff --git a/include/linux/netlink.h b/include/linux/netlink.h index bd13b6f..fb0713b 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -219,7 +219,7 @@ struct netlink_callback int (*dump)(struct sk_buff * skb, struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); int family; - long args[5]; + long args[6]; }; struct netlink_notify diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index d9db5f6..6db69ff 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h @@ -298,6 +298,12 @@ struct sadb_x_sec_ctx { #define SADB_X_EALG_BLOWFISHCBC 7 #define SADB_EALG_NULL 11 #define SADB_X_EALG_AESCBC 12 +#define SADB_X_EALG_AES_CCM_ICV8 14 +#define SADB_X_EALG_AES_CCM_ICV12 15 +#define SADB_X_EALG_AES_CCM_ICV16 16 +#define SADB_X_EALG_AES_GCM_ICV8 18 +#define SADB_X_EALG_AES_GCM_ICV12 19 +#define SADB_X_EALG_AES_GCM_ICV16 20 #define SADB_X_EALG_CAMELLIACBC 22 #define SADB_EALG_MAX 253 /* last EALG */ /* private allocations should use 249-255 (RFC2407) */ diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index 30b8571..1c1dba9 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -328,6 +328,56 @@ enum #define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1) +/* Flow filter */ + +enum +{ + FLOW_KEY_SRC, + FLOW_KEY_DST, + FLOW_KEY_PROTO, + FLOW_KEY_PROTO_SRC, + FLOW_KEY_PROTO_DST, + FLOW_KEY_IIF, + FLOW_KEY_PRIORITY, + FLOW_KEY_MARK, + FLOW_KEY_NFCT, + FLOW_KEY_NFCT_SRC, + FLOW_KEY_NFCT_DST, + FLOW_KEY_NFCT_PROTO_SRC, + FLOW_KEY_NFCT_PROTO_DST, + FLOW_KEY_RTCLASSID, + FLOW_KEY_SKUID, + FLOW_KEY_SKGID, + __FLOW_KEY_MAX, +}; + +#define FLOW_KEY_MAX (__FLOW_KEY_MAX - 1) + +enum +{ + FLOW_MODE_MAP, + FLOW_MODE_HASH, +}; + +enum +{ + TCA_FLOW_UNSPEC, + TCA_FLOW_KEYS, + TCA_FLOW_MODE, + TCA_FLOW_BASECLASS, + TCA_FLOW_RSHIFT, + TCA_FLOW_ADDEND, + TCA_FLOW_MASK, + TCA_FLOW_XOR, + TCA_FLOW_DIVISOR, + TCA_FLOW_ACT, + TCA_FLOW_POLICE, + TCA_FLOW_EMATCHES, + __TCA_FLOW_MAX +}; + +#define TCA_FLOW_MAX (__TCA_FLOW_MAX - 1) + /* Basic filter */ enum diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 3276135..dbb7ac3 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -150,6 +150,11 @@ struct tc_sfq_qopt unsigned flows; /* Maximal number of flows */ }; +struct tc_sfq_xstats +{ + __s32 allot; +}; + /* * NOTE: limit, divisor and flows are hardwired to code at the moment. * diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 0ce5e0b..e3ab21d 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -33,11 +33,13 @@ * RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device. * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. * RFKILL_TYPE_UWB: switch is on a ultra wideband device. + * RFKILL_TYPE_WIMAX: switch is on a WiMAX device. */ enum rfkill_type { RFKILL_TYPE_WLAN , RFKILL_TYPE_BLUETOOTH, RFKILL_TYPE_UWB, + RFKILL_TYPE_WIMAX, RFKILL_TYPE_MAX, }; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c618fbf..dfe975a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -108,9 +108,6 @@ struct nf_bridge_info { atomic_t use; struct net_device *physindev; struct net_device *physoutdev; -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - struct net_device *netoutdev; -#endif unsigned int mask; unsigned long data[32 / sizeof(unsigned long)]; }; diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 86d3eff..5df62ef 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -227,7 +227,7 @@ enum LINUX_MIB_XFRMINNOSTATES, /* XfrmInNoStates */ LINUX_MIB_XFRMINSTATEPROTOERROR, /* XfrmInStateProtoError */ LINUX_MIB_XFRMINSTATEMODEERROR, /* XfrmInStateModeError */ - LINUX_MIB_XFRMINSEQOUTOFWINDOW, /* XfrmInSeqOutOfWindow */ + LINUX_MIB_XFRMINSTATESEQERROR, /* XfrmInStateSeqError */ LINUX_MIB_XFRMINSTATEEXPIRED, /* XfrmInStateExpired */ LINUX_MIB_XFRMINSTATEMISMATCH, /* XfrmInStateMismatch */ LINUX_MIB_XFRMINSTATEINVALID, /* XfrmInStateInvalid */ @@ -241,6 +241,7 @@ enum LINUX_MIB_XFRMOUTNOSTATES, /* XfrmOutNoStates */ LINUX_MIB_XFRMOUTSTATEPROTOERROR, /* XfrmOutStateProtoError */ LINUX_MIB_XFRMOUTSTATEMODEERROR, /* XfrmOutStateModeError */ + LINUX_MIB_XFRMOUTSTATESEQERROR, /* XfrmOutStateSeqError */ LINUX_MIB_XFRMOUTSTATEEXPIRED, /* XfrmOutStateExpired */ LINUX_MIB_XFRMOUTPOLBLOCK, /* XfrmOutPolBlock */ LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 89faebf..bf4ae4e 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -440,8 +440,8 @@ enum enum { NET_IPV4_ROUTE_FLUSH=1, - NET_IPV4_ROUTE_MIN_DELAY=2, - NET_IPV4_ROUTE_MAX_DELAY=3, + NET_IPV4_ROUTE_MIN_DELAY=2, /* obsolete since 2.6.25 */ + NET_IPV4_ROUTE_MAX_DELAY=3, /* obsolete since 2.6.25 */ NET_IPV4_ROUTE_GC_THRESH=4, NET_IPV4_ROUTE_MAX_SIZE=5, NET_IPV4_ROUTE_GC_MIN_INTERVAL=6, diff --git a/include/linux/types.h b/include/linux/types.h index f4f8d19..b94c0e4 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -126,7 +126,7 @@ typedef __s64 int64_t; #endif /* this is a special 64bit data type that is 8-byte aligned */ -#define aligned_u64 unsigned long long __attribute__((aligned(8))) +#define aligned_u64 __u64 __attribute__((aligned(8))) #define aligned_be64 __be64 __attribute__((aligned(8))) #define aligned_le64 __le64 __attribute__((aligned(8))) diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h new file mode 100644 index 0000000..edc1d4a --- /dev/null +++ b/include/linux/usb/rndis_host.h @@ -0,0 +1,274 @@ +/* + * Host Side support for RNDIS Networking Links + * Copyright (C) 2005 by David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __RNDIS_HOST_H +#define __RNDIS_HOST_H + + +/* + * CONTROL uses CDC "encapsulated commands" with funky notifications. + * - control-out: SEND_ENCAPSULATED + * - interrupt-in: RESPONSE_AVAILABLE + * - control-in: GET_ENCAPSULATED + * + * We'll try to ignore the RESPONSE_AVAILABLE notifications. + * + * REVISIT some RNDIS implementations seem to have curious issues still + * to be resolved. + */ +struct rndis_msg_hdr { + __le32 msg_type; /* RNDIS_MSG_* */ + __le32 msg_len; + // followed by data that varies between messages + __le32 request_id; + __le32 status; + // ... and more +} __attribute__ ((packed)); + +/* MS-Windows uses this strange size, but RNDIS spec says 1024 minimum */ +#define CONTROL_BUFFER_SIZE 1025 + +/* RNDIS defines an (absurdly huge) 10 second control timeout, + * but ActiveSync seems to use a more usual 5 second timeout + * (which matches the USB 2.0 spec). + */ +#define RNDIS_CONTROL_TIMEOUT_MS (5 * 1000) + + +#define ccpu2 __constant_cpu_to_le32 + +#define RNDIS_MSG_COMPLETION ccpu2(0x80000000) + +/* codes for "msg_type" field of rndis messages; + * only the data channel uses packet messages (maybe batched); + * everything else goes on the control channel. + */ +#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */ +#define RNDIS_MSG_INIT ccpu2(0x00000002) +#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION) +#define RNDIS_MSG_HALT ccpu2(0x00000003) +#define RNDIS_MSG_QUERY ccpu2(0x00000004) +#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION) +#define RNDIS_MSG_SET ccpu2(0x00000005) +#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION) +#define RNDIS_MSG_RESET ccpu2(0x00000006) +#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION) +#define RNDIS_MSG_INDICATE ccpu2(0x00000007) +#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008) +#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION) + +/* codes for "status" field of completion messages */ +#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000) +#define RNDIS_STATUS_FAILURE ccpu2(0xc0000001) +#define RNDIS_STATUS_INVALID_DATA ccpu2(0xc0010015) +#define RNDIS_STATUS_NOT_SUPPORTED ccpu2(0xc00000bb) +#define RNDIS_STATUS_MEDIA_CONNECT ccpu2(0x4001000b) +#define RNDIS_STATUS_MEDIA_DISCONNECT ccpu2(0x4001000c) + +/* codes for OID_GEN_PHYSICAL_MEDIUM */ +#define RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED ccpu2(0x00000000) +#define RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN ccpu2(0x00000001) +#define RNDIS_PHYSICAL_MEDIUM_CABLE_MODEM ccpu2(0x00000002) +#define RNDIS_PHYSICAL_MEDIUM_PHONE_LINE ccpu2(0x00000003) +#define RNDIS_PHYSICAL_MEDIUM_POWER_LINE ccpu2(0x00000004) +#define RNDIS_PHYSICAL_MEDIUM_DSL ccpu2(0x00000005) +#define RNDIS_PHYSICAL_MEDIUM_FIBRE_CHANNEL ccpu2(0x00000006) +#define RNDIS_PHYSICAL_MEDIUM_1394 ccpu2(0x00000007) +#define RNDIS_PHYSICAL_MEDIUM_WIRELESS_WAN ccpu2(0x00000008) +#define RNDIS_PHYSICAL_MEDIUM_MAX ccpu2(0x00000009) + +struct rndis_data_hdr { + __le32 msg_type; /* RNDIS_MSG_PACKET */ + __le32 msg_len; // rndis_data_hdr + data_len + pad + __le32 data_offset; // 36 -- right after header + __le32 data_len; // ... real packet size + + __le32 oob_data_offset; // zero + __le32 oob_data_len; // zero + __le32 num_oob; // zero + __le32 packet_data_offset; // zero + + __le32 packet_data_len; // zero + __le32 vc_handle; // zero + __le32 reserved; // zero +} __attribute__ ((packed)); + +struct rndis_init { /* OUT */ + // header and: + __le32 msg_type; /* RNDIS_MSG_INIT */ + __le32 msg_len; // 24 + __le32 request_id; + __le32 major_version; // of rndis (1.0) + __le32 minor_version; + __le32 max_transfer_size; +} __attribute__ ((packed)); + +struct rndis_init_c { /* IN */ + // header and: + __le32 msg_type; /* RNDIS_MSG_INIT_C */ + __le32 msg_len; + __le32 request_id; + __le32 status; + __le32 major_version; // of rndis (1.0) + __le32 minor_version; + __le32 device_flags; + __le32 medium; // zero == 802.3 + __le32 max_packets_per_message; + __le32 max_transfer_size; + __le32 packet_alignment; // max 7; (1<<n) bytes + __le32 af_list_offset; // zero + __le32 af_list_size; // zero +} __attribute__ ((packed)); + +struct rndis_halt { /* OUT (no reply) */ + // header and: + __le32 msg_type; /* RNDIS_MSG_HALT */ + __le32 msg_len; + __le32 request_id; +} __attribute__ ((packed)); + +struct rndis_query { /* OUT */ + // header and: + __le32 msg_type; /* RNDIS_MSG_QUERY */ + __le32 msg_len; + __le32 request_id; + __le32 oid; + __le32 len; + __le32 offset; +/*?*/ __le32 handle; // zero +} __attribute__ ((packed)); + +struct rndis_query_c { /* IN */ + // header and: + __le32 msg_type; /* RNDIS_MSG_QUERY_C */ + __le32 msg_len; + __le32 request_id; + __le32 status; + __le32 len; + __le32 offset; +} __attribute__ ((packed)); + +struct rndis_set { /* OUT */ + // header and: + __le32 msg_type; /* RNDIS_MSG_SET */ + __le32 msg_len; + __le32 request_id; + __le32 oid; + __le32 len; + __le32 offset; +/*?*/ __le32 handle; // zero +} __attribute__ ((packed)); + +struct rndis_set_c { /* IN */ + // header and: + __le32 msg_type; /* RNDIS_MSG_SET_C */ + __le32 msg_len; + __le32 request_id; + __le32 status; +} __attribute__ ((packed)); + +struct rndis_reset { /* IN */ + // header and: + __le32 msg_type; /* RNDIS_MSG_RESET */ + __le32 msg_len; + __le32 reserved; +} __attribute__ ((packed)); + +struct rndis_reset_c { /* OUT */ + // header and: + __le32 msg_type; /* RNDIS_MSG_RESET_C */ + __le32 msg_len; + __le32 status; + __le32 addressing_lost; +} __attribute__ ((packed)); + +struct rndis_indicate { /* IN (unrequested) */ + // header and: + __le32 msg_type; /* RNDIS_MSG_INDICATE */ + __le32 msg_len; + __le32 status; + __le32 length; + __le32 offset; +/**/ __le32 diag_status; + __le32 error_offset; +/**/ __le32 message; +} __attribute__ ((packed)); + +struct rndis_keepalive { /* OUT (optionally IN) */ + // header and: + __le32 msg_type; /* RNDIS_MSG_KEEPALIVE */ + __le32 msg_len; + __le32 request_id; +} __attribute__ ((packed)); + +struct rndis_keepalive_c { /* IN (optionally OUT) */ + // header and: + __le32 msg_type; /* RNDIS_MSG_KEEPALIVE_C */ + __le32 msg_len; + __le32 request_id; + __le32 status; +} __attribute__ ((packed)); + +/* NOTE: about 30 OIDs are "mandatory" for peripherals to support ... and + * there are gobs more that may optionally be supported. We'll avoid as much + * of that mess as possible. + */ +#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101) +#define OID_GEN_MAXIMUM_FRAME_SIZE ccpu2(0x00010106) +#define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e) +#define OID_GEN_PHYSICAL_MEDIUM ccpu2(0x00010202) + +/* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */ +#define RNDIS_PACKET_TYPE_DIRECTED ccpu2(0x00000001) +#define RNDIS_PACKET_TYPE_MULTICAST ccpu2(0x00000002) +#define RNDIS_PACKET_TYPE_ALL_MULTICAST ccpu2(0x00000004) +#define RNDIS_PACKET_TYPE_BROADCAST ccpu2(0x00000008) +#define RNDIS_PACKET_TYPE_SOURCE_ROUTING ccpu2(0x00000010) +#define RNDIS_PACKET_TYPE_PROMISCUOUS ccpu2(0x00000020) +#define RNDIS_PACKET_TYPE_SMT ccpu2(0x00000040) +#define RNDIS_PACKET_TYPE_ALL_LOCAL ccpu2(0x00000080) +#define RNDIS_PACKET_TYPE_GROUP ccpu2(0x00001000) +#define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL ccpu2(0x00002000) +#define RNDIS_PACKET_TYPE_FUNCTIONAL ccpu2(0x00004000) +#define RNDIS_PACKET_TYPE_MAC_FRAME ccpu2(0x00008000) + +/* default filter used with RNDIS devices */ +#define RNDIS_DEFAULT_FILTER ( \ + RNDIS_PACKET_TYPE_DIRECTED | \ + RNDIS_PACKET_TYPE_BROADCAST | \ + RNDIS_PACKET_TYPE_ALL_MULTICAST | \ + RNDIS_PACKET_TYPE_PROMISCUOUS) + +/* Flags to require specific physical medium type for generic_rndis_bind() */ +#define FLAG_RNDIS_PHYM_NOT_WIRELESS 0x0001 +#define FLAG_RNDIS_PHYM_WIRELESS 0x0002 + + +extern void rndis_status(struct usbnet *dev, struct urb *urb); +extern int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf); +extern int +generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags); +extern void rndis_unbind(struct usbnet *dev, struct usb_interface *intf); +extern int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb); +extern struct sk_buff * +rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags); + +#endif /* __RNDIS_HOST_H */ + diff --git a/drivers/net/usb/usbnet.h b/include/linux/usb/usbnet.h index 1fae434..e0501da 100644 --- a/drivers/net/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -31,6 +31,7 @@ struct usbnet { struct usb_interface *intf; struct driver_info *driver_info; const char *driver_name; + void *driver_priv; wait_queue_head_t *wait; struct mutex phy_mutex; unsigned char suspend_count; @@ -87,6 +88,8 @@ struct driver_info { #define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */ #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ +#define FLAG_WLAN 0x0080 /* use "wlan%d" names */ + /* init device ... can sleep, or cause probe() failure */ int (*bind)(struct usbnet *, struct usb_interface *); @@ -113,6 +116,15 @@ struct driver_info { struct sk_buff *(*tx_fixup)(struct usbnet *dev, struct sk_buff *skb, gfp_t flags); + /* early initialization code, can sleep. This is for minidrivers + * having 'subminidrivers' that need to do extra initialization + * right after minidriver have initialized hardware. */ + int (*early_init)(struct usbnet *dev); + + /* called by minidriver when link state changes, state: 0=disconnect, + * 1=connect */ + void (*link_change)(struct usbnet *dev, int state); + /* for new devices, use the descriptor-reading code instead */ int in; /* rx endpoint */ int out; /* tx endpoint */ diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 9b5b00c..e31b8c8 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -96,6 +96,13 @@ struct xfrm_algo { char alg_key[0]; }; +struct xfrm_algo_aead { + char alg_name[64]; + int alg_key_len; /* in bits */ + int alg_icv_len; /* in bits */ + char alg_key[0]; +}; + struct xfrm_stats { __u32 replay_window; __u32 replay; @@ -270,6 +277,7 @@ enum xfrm_attr_type_t { XFRMA_LASTUSED, XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ XFRMA_MIGRATE, + XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) diff --git a/include/net/arp.h b/include/net/arp.h index 752eb47..c236270 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -13,15 +13,17 @@ extern int arp_find(unsigned char *haddr, struct sk_buff *skb); extern int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg); extern void arp_send(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, - unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th); + const unsigned char *dest_hw, + const unsigned char *src_hw, const unsigned char *th); extern int arp_bind_neighbour(struct dst_entry *dst); extern int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir); extern void arp_ifdown(struct net_device *dev); extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, - unsigned char *dest_hw, unsigned char *src_hw, - unsigned char *target_hw); + const unsigned char *dest_hw, + const unsigned char *src_hw, + const unsigned char *target_hw); extern void arp_xmit(struct sk_buff *skb); extern struct neigh_ops arp_broken_ops; diff --git a/include/net/esp.h b/include/net/esp.h index c05f529..d584513 100644 --- a/include/net/esp.h +++ b/include/net/esp.h @@ -1,58 +1,20 @@ #ifndef _NET_ESP_H #define _NET_ESP_H -#include <linux/crypto.h> -#include <net/xfrm.h> -#include <linux/scatterlist.h> +#include <linux/skbuff.h> -#define ESP_NUM_FAST_SG 4 +struct crypto_aead; -struct esp_data -{ - struct scatterlist sgbuf[ESP_NUM_FAST_SG]; - - /* Confidentiality */ - struct { - int padlen; /* 0..255 */ - /* ivlen is offset from enc_data, where encrypted data start. - * It is logically different of crypto_tfm_alg_ivsize(tfm). - * We assume that it is either zero (no ivec), or - * >= crypto_tfm_alg_ivsize(tfm). */ - int ivlen; - int ivinitted; - u8 *ivec; /* ivec buffer */ - struct crypto_blkcipher *tfm; /* crypto handle */ - } conf; - - /* Integrity. It is active when icv_full_len != 0 */ - struct { - u8 *work_icv; - int icv_full_len; - int icv_trunc_len; - struct crypto_hash *tfm; - } auth; +struct esp_data { + /* 0..255 */ + int padlen; + + /* Confidentiality & Integrity */ + struct crypto_aead *aead; }; extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); -static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb, - int offset, int len) -{ - struct hash_desc desc; - int err; - - desc.tfm = esp->auth.tfm; - desc.flags = 0; - - err = crypto_hash_init(&desc); - if (unlikely(err)) - return err; - err = skb_icv_walk(skb, &desc, offset, len, crypto_hash_update); - if (unlikely(err)) - return err; - return crypto_hash_final(&desc, esp->auth.work_icv); -} - struct ip_esp_hdr; static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb) diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 668056b..fdff630 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -57,34 +57,37 @@ extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk); * * The sockhash lock must be held as a reader here. */ -extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, +extern struct sock *__inet6_lookup_established(struct net *net, + struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const u16 hnum, const int dif); -extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, +extern struct sock *inet6_lookup_listener(struct net *net, + struct inet_hashinfo *hashinfo, const struct in6_addr *daddr, const unsigned short hnum, const int dif); -static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo, +static inline struct sock *__inet6_lookup(struct net *net, + struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const u16 hnum, const int dif) { - struct sock *sk = __inet6_lookup_established(hashinfo, saddr, sport, - daddr, hnum, dif); + struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr, + sport, daddr, hnum, dif); if (sk) return sk; - return inet6_lookup_listener(hashinfo, daddr, hnum, dif); + return inet6_lookup_listener(net, hashinfo, daddr, hnum, dif); } -extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, +extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const __be16 dport, const int dif); diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 761bdc0..c23c4ed 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -74,6 +74,7 @@ struct inet_ehash_bucket { * ports are created in O(1) time? I thought so. ;-) -DaveM */ struct inet_bind_bucket { + struct net *ib_net; unsigned short port; signed short fastreuse; struct hlist_node node; @@ -194,6 +195,7 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo) extern struct inet_bind_bucket * inet_bind_bucket_create(struct kmem_cache *cachep, + struct net *net, struct inet_bind_hashbucket *head, const unsigned short snum); extern void inet_bind_bucket_destroy(struct kmem_cache *cachep, @@ -300,15 +302,17 @@ out: wake_up(&hashinfo->lhash_wait); } -extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo, +extern struct sock *__inet_lookup_listener(struct net *net, + struct inet_hashinfo *hashinfo, const __be32 daddr, const unsigned short hnum, const int dif); -static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, - __be32 daddr, __be16 dport, int dif) +static inline struct sock *inet_lookup_listener(struct net *net, + struct inet_hashinfo *hashinfo, + __be32 daddr, __be16 dport, int dif) { - return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif); + return __inet_lookup_listener(net, hashinfo, daddr, ntohs(dport), dif); } /* Socket demux engine toys. */ @@ -342,26 +346,26 @@ typedef __u64 __bitwise __addrpair; (((__force __u64)(__be32)(__daddr)) << 32) | \ ((__force __u64)(__be32)(__saddr))); #endif /* __BIG_ENDIAN */ -#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ - (((__sk)->sk_hash == (__hash)) && \ +#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ + (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \ ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) -#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ - (((__sk)->sk_hash == (__hash)) && \ +#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ + (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \ ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) #else /* 32-bit arch */ #define INET_ADDR_COOKIE(__name, __saddr, __daddr) -#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif) \ - (((__sk)->sk_hash == (__hash)) && \ +#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif) \ + (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \ (inet_sk(__sk)->daddr == (__saddr)) && \ (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) -#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ - (((__sk)->sk_hash == (__hash)) && \ +#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ + (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \ (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ @@ -374,32 +378,36 @@ typedef __u64 __bitwise __addrpair; * * Local BH must be disabled here. */ -extern struct sock * __inet_lookup_established(struct inet_hashinfo *hashinfo, +extern struct sock * __inet_lookup_established(struct net *net, + struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const u16 hnum, const int dif); static inline struct sock * - inet_lookup_established(struct inet_hashinfo *hashinfo, + inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif) { - return __inet_lookup_established(hashinfo, saddr, sport, daddr, + return __inet_lookup_established(net, hashinfo, saddr, sport, daddr, ntohs(dport), dif); } -static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo, +static inline struct sock *__inet_lookup(struct net *net, + struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif) { u16 hnum = ntohs(dport); - struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr, - hnum, dif); - return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif); + struct sock *sk = __inet_lookup_established(net, hashinfo, + saddr, sport, daddr, hnum, dif); + + return sk ? : __inet_lookup_listener(net, hashinfo, daddr, hnum, dif); } -static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, +static inline struct sock *inet_lookup(struct net *net, + struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif) @@ -407,12 +415,17 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, struct sock *sk; local_bh_disable(); - sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif); + sk = __inet_lookup(net, hashinfo, saddr, sport, daddr, dport, dif); local_bh_enable(); return sk; } +extern int __inet_hash_connect(struct inet_timewait_death_row *death_row, + struct sock *sk, + int (*check_established)(struct inet_timewait_death_row *, + struct sock *, __u16, struct inet_timewait_sock **), + void (*hash)(struct inet_hashinfo *, struct sock *)); extern int inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk); #endif /* _INET_HASHTABLES_H */ diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 9daa60b..90d1175 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -69,6 +69,7 @@ struct fib_nh { struct fib_info { struct hlist_node fib_hash; struct hlist_node fib_lhash; + struct net *fib_net; int fib_treeref; atomic_t fib_clntref; int fib_dead; @@ -218,7 +219,8 @@ extern void fib_select_default(struct net *net, const struct flowi *flp, /* Exported by fib_semantics.c */ extern int ip_fib_check_default(__be32 gw, struct net_device *dev); -extern int fib_sync_down(__be32 local, struct net_device *dev, int force); +extern int fib_sync_down_dev(struct net_device *dev, int force); +extern int fib_sync_down_addr(struct net *net, __be32 local); extern int fib_sync_up(struct net_device *dev); extern __be32 __fib_res_prefsrc(struct fib_result *res); extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index b8c1d60..28738b7 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -12,6 +12,7 @@ #include <net/netns/packet.h> #include <net/netns/ipv4.h> #include <net/netns/ipv6.h> +#include <net/netns/x_tables.h> struct proc_dir_entry; struct net_device; @@ -56,6 +57,9 @@ struct net { #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netns_ipv6 ipv6; #endif +#ifdef CONFIG_NETFILTER + struct netns_xt xt; +#endif }; #ifdef CONFIG_NET diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 857d899..90b3e7f 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -129,6 +129,8 @@ struct nf_conn /* Extensions */ struct nf_ct_ext *ext; + + struct rcu_head rcu; }; static inline struct nf_conn * @@ -143,7 +145,7 @@ nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash) /* Alter reply tuple (maybe alter helper). */ extern void -nf_conntrack_alter_reply(struct nf_conn *conntrack, +nf_conntrack_alter_reply(struct nf_conn *ct, const struct nf_conntrack_tuple *newreply); /* Is this tuple taken? (ignoring any belonging to the given @@ -171,13 +173,12 @@ static inline void nf_ct_put(struct nf_conn *ct) extern int nf_ct_l3proto_try_module_get(unsigned short l3proto); extern void nf_ct_l3proto_module_put(unsigned short l3proto); -extern struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced); +extern struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced); extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, - int size); + unsigned int size); extern struct nf_conntrack_tuple_hash * -__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack); +__nf_conntrack_find(const struct nf_conntrack_tuple *tuple); extern void nf_conntrack_hash_insert(struct nf_conn *ct); @@ -215,9 +216,9 @@ static inline void nf_ct_refresh(struct nf_conn *ct, /* These are for NAT. Icky. */ /* Update TCP window tracking data when NAT mangles the packet */ -extern void nf_conntrack_tcp_update(struct sk_buff *skb, +extern void nf_conntrack_tcp_update(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conn *conntrack, + struct nf_conn *ct, int dir); /* Fake conntrack entry for untracked connections */ diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 7ad0828..9ee2646 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -68,11 +68,11 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb) int print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, - struct nf_conntrack_l3proto *l3proto, - struct nf_conntrack_l4proto *proto); + const struct nf_conntrack_l3proto *l3proto, + const struct nf_conntrack_l4proto *proto); extern struct hlist_head *nf_conntrack_hash; -extern rwlock_t nf_conntrack_lock ; +extern spinlock_t nf_conntrack_lock ; extern struct hlist_head unconfirmed; #endif /* _NF_CONNTRACK_CORE_H */ diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 6c3fd25..cb608a1 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -49,6 +49,8 @@ struct nf_conntrack_expect /* Direction relative to the master connection. */ enum ip_conntrack_dir dir; #endif + + struct rcu_head rcu; }; #define NF_CT_EXPECT_PERMANENT 0x1 diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 2f3af00..4ca125e 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -43,12 +43,8 @@ extern struct nf_conntrack_helper * __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple); extern struct nf_conntrack_helper * -nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple); - -extern struct nf_conntrack_helper * __nf_conntrack_helper_find_byname(const char *name); -extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index d5526bc..b886e3a 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -43,7 +43,7 @@ struct nf_conntrack_l3proto const struct nf_conntrack_tuple *); /* Returns verdict for packet, or -1 for invalid. */ - int (*packet)(struct nf_conn *conntrack, + int (*packet)(struct nf_conn *ct, const struct sk_buff *skb, enum ip_conntrack_info ctinfo); @@ -51,7 +51,7 @@ struct nf_conntrack_l3proto * Called when a new connection for this protocol found; * returns TRUE if it's OK. If so, packet() called next. */ - int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb); + int (*new)(struct nf_conn *ct, const struct sk_buff *skb); /* * Called before tracking. diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index fb50c21..efc16ec 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -23,9 +23,6 @@ struct nf_conntrack_l4proto /* L4 Protocol number. */ u_int8_t l4proto; - /* Protocol name */ - const char *name; - /* Try to fill in the third arg: dataoff is offset past network protocol hdr. Return true if possible. */ int (*pkt_to_tuple)(const struct sk_buff *skb, @@ -38,15 +35,8 @@ struct nf_conntrack_l4proto int (*invert_tuple)(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); - /* Print out the per-protocol part of the tuple. Return like seq_* */ - int (*print_tuple)(struct seq_file *s, - const struct nf_conntrack_tuple *); - - /* Print out the private part of the conntrack. */ - int (*print_conntrack)(struct seq_file *s, const struct nf_conn *); - /* Returns verdict for packet, or -1 for invalid. */ - int (*packet)(struct nf_conn *conntrack, + int (*packet)(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info ctinfo, @@ -55,16 +45,23 @@ struct nf_conntrack_l4proto /* Called when a new connection for this protocol found; * returns TRUE if it's OK. If so, packet() called next. */ - int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb, + int (*new)(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff); /* Called when a conntrack entry is destroyed */ - void (*destroy)(struct nf_conn *conntrack); + void (*destroy)(struct nf_conn *ct); int (*error)(struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum); + /* Print out the per-protocol part of the tuple. Return like seq_* */ + int (*print_tuple)(struct seq_file *s, + const struct nf_conntrack_tuple *); + + /* Print out the private part of the conntrack. */ + int (*print_conntrack)(struct seq_file *s, const struct nf_conn *); + /* convert protoinfo to nfnetink attributes */ int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, const struct nf_conn *ct); @@ -87,6 +84,8 @@ struct nf_conntrack_l4proto struct ctl_table *ctl_compat_table; #endif #endif + /* Protocol name */ + const char *name; /* Module (if any) which this is connected to. */ struct module *me; diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 45cb17c..e69ab2e 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -132,34 +132,33 @@ struct nf_conntrack_tuple_hash #endif /* __KERNEL__ */ -static inline int nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1, - const struct nf_conntrack_tuple *t2) +static inline int __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1, + const struct nf_conntrack_tuple *t2) { return (t1->src.u3.all[0] == t2->src.u3.all[0] && t1->src.u3.all[1] == t2->src.u3.all[1] && t1->src.u3.all[2] == t2->src.u3.all[2] && t1->src.u3.all[3] == t2->src.u3.all[3] && t1->src.u.all == t2->src.u.all && - t1->src.l3num == t2->src.l3num && - t1->dst.protonum == t2->dst.protonum); + t1->src.l3num == t2->src.l3num); } -static inline int nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1, - const struct nf_conntrack_tuple *t2) +static inline int __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1, + const struct nf_conntrack_tuple *t2) { return (t1->dst.u3.all[0] == t2->dst.u3.all[0] && t1->dst.u3.all[1] == t2->dst.u3.all[1] && t1->dst.u3.all[2] == t2->dst.u3.all[2] && t1->dst.u3.all[3] == t2->dst.u3.all[3] && t1->dst.u.all == t2->dst.u.all && - t1->src.l3num == t2->src.l3num && t1->dst.protonum == t2->dst.protonum); } static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1, const struct nf_conntrack_tuple *t2) { - return nf_ct_tuple_src_equal(t1, t2) && nf_ct_tuple_dst_equal(t1, t2); + return __nf_ct_tuple_src_equal(t1, t2) && + __nf_ct_tuple_dst_equal(t1, t2); } static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1, @@ -199,7 +198,7 @@ static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t, const struct nf_conntrack_tuple_mask *mask) { return nf_ct_tuple_src_mask_cmp(t, tuple, mask) && - nf_ct_tuple_dst_equal(t, tuple); + __nf_ct_tuple_dst_equal(t, tuple); } #endif /* _NF_CONNTRACK_TUPLE_H */ diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h index 037e824..8c6b5ae 100644 --- a/include/net/netfilter/nf_log.h +++ b/include/net/netfilter/nf_log.h @@ -54,6 +54,6 @@ void nf_log_packet(int pf, const struct net_device *in, const struct net_device *out, const struct nf_loginfo *li, - const char *fmt, ...); + const char *fmt, ...) __attribute__ ((format(printf,7,8))); #endif /* _NF_LOG_H */ diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 15a0b05..a9b4f60 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -27,5 +27,11 @@ struct netns_ipv4 { struct sock *fibnl; struct netns_frags frags; +#ifdef CONFIG_NETFILTER + struct xt_table *iptable_filter; + struct xt_table *iptable_mangle; + struct xt_table *iptable_raw; + struct xt_table *arptable_filter; +#endif }; #endif diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 187c424..1dd7de4 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h @@ -31,5 +31,10 @@ struct netns_ipv6 { struct ipv6_devconf *devconf_all; struct ipv6_devconf *devconf_dflt; struct netns_frags frags; +#ifdef CONFIG_NETFILTER + struct xt_table *ip6table_filter; + struct xt_table *ip6table_mangle; + struct xt_table *ip6table_raw; +#endif }; #endif diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h new file mode 100644 index 0000000..0cb63ed --- /dev/null +++ b/include/net/netns/x_tables.h @@ -0,0 +1,10 @@ +#ifndef __NETNS_X_TABLES_H +#define __NETNS_X_TABLES_H + +#include <linux/list.h> +#include <linux/net.h> + +struct netns_xt { + struct list_head tables[NPROTO]; +}; +#endif diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 8716eb7..d349c66 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -131,14 +131,14 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, extern int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb, struct nlattr *rate_tlv, struct tcf_exts *exts, - struct tcf_ext_map *map); + const struct tcf_ext_map *map); extern void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts); extern void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, struct tcf_exts *src); extern int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, - struct tcf_ext_map *map); + const struct tcf_ext_map *map); extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts, - struct tcf_ext_map *map); + const struct tcf_ext_map *map); /** * struct tcf_pkt_info - packet information diff --git a/include/net/raw.h b/include/net/raw.h index cca81d8..1828f81 100644 --- a/include/net/raw.h +++ b/include/net/raw.h @@ -41,7 +41,6 @@ extern void raw_proc_exit(void); struct raw_iter_state { struct seq_net_private p; int bucket; - unsigned short family; struct raw_hashinfo *h; }; @@ -49,8 +48,8 @@ struct raw_iter_state { void *raw_seq_start(struct seq_file *seq, loff_t *pos); void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos); void raw_seq_stop(struct seq_file *seq, void *v); -int raw_seq_open(struct inode *ino, struct file *file, struct raw_hashinfo *h, - unsigned short family); +int raw_seq_open(struct inode *ino, struct file *file, + struct raw_hashinfo *h, const struct seq_operations *ops); #endif diff --git a/include/net/route.h b/include/net/route.h index 4eabf00..eadad59 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -27,6 +27,7 @@ #include <net/dst.h> #include <net/inetpeer.h> #include <net/flow.h> +#include <net/sock.h> #include <linux/in_route.h> #include <linux/rtnetlink.h> #include <linux/route.h> @@ -61,6 +62,7 @@ struct rtable struct in_device *idev; + int rt_genid; unsigned rt_flags; __u16 rt_type; @@ -149,6 +151,7 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst, int flags) { struct flowi fl = { .oif = oif, + .mark = sk->sk_mark, .nl_u = { .ip4_u = { .daddr = dst, .saddr = src, .tos = tos } }, diff --git a/include/net/sock.h b/include/net/sock.h index 9023244..e3fb4c0 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -262,6 +262,8 @@ struct sock { __u32 sk_sndmsg_off; int sk_write_pending; void *sk_security; + __u32 sk_mark; + /* XXX 4 bytes hole on 64 bit */ void (*sk_state_change)(struct sock *sk); void (*sk_data_ready)(struct sock *sk, int bytes); void (*sk_write_space)(struct sock *sk); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 5ebb9ba..ac72116 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -159,6 +159,7 @@ struct xfrm_state struct xfrm_algo *aalg; struct xfrm_algo *ealg; struct xfrm_algo *calg; + struct xfrm_algo_aead *aead; /* Data for encapsulator */ struct xfrm_encap_tmpl *encap; @@ -201,7 +202,7 @@ struct xfrm_state /* Reference to data common to all the instances of this * transformer. */ - struct xfrm_type *type; + const struct xfrm_type *type; struct xfrm_mode *inner_mode; struct xfrm_mode *outer_mode; @@ -278,7 +279,7 @@ struct xfrm_state_afinfo { unsigned int proto; unsigned int eth_proto; struct module *owner; - struct xfrm_type *type_map[IPPROTO_MAX]; + const struct xfrm_type *type_map[IPPROTO_MAX]; struct xfrm_mode *mode_map[XFRM_MODE_MAX]; int (*init_flags)(struct xfrm_state *x); void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, @@ -321,8 +322,8 @@ struct xfrm_type u32 (*get_mtu)(struct xfrm_state *, int size); }; -extern int xfrm_register_type(struct xfrm_type *type, unsigned short family); -extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family); +extern int xfrm_register_type(const struct xfrm_type *type, unsigned short family); +extern int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family); struct xfrm_mode { /* @@ -1108,6 +1109,10 @@ static inline int xfrm_id_proto_match(u8 proto, u8 userproto) /* * xfrm algorithm information */ +struct xfrm_algo_aead_info { + u16 icv_truncbits; +}; + struct xfrm_algo_auth_info { u16 icv_truncbits; u16 icv_fullbits; @@ -1127,6 +1132,7 @@ struct xfrm_algo_desc { char *compat; u8 available:1; union { + struct xfrm_algo_aead_info aead; struct xfrm_algo_auth_info auth; struct xfrm_algo_encr_info encr; struct xfrm_algo_comp_info comp; @@ -1343,6 +1349,8 @@ extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id); extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe); extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe); extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe); +extern struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len, + int probe); struct hash_desc; struct scatterlist; diff --git a/kernel/audit.c b/kernel/audit.c index f93c271..801c946 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1200,13 +1200,17 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, static inline int audit_expand(struct audit_buffer *ab, int extra) { struct sk_buff *skb = ab->skb; - int ret = pskb_expand_head(skb, skb_headroom(skb), extra, - ab->gfp_mask); + int oldtail = skb_tailroom(skb); + int ret = pskb_expand_head(skb, 0, extra, ab->gfp_mask); + int newtail = skb_tailroom(skb); + if (ret < 0) { audit_log_lost("out of memory in audit_expand"); return 0; } - return skb_tailroom(skb); + + skb->truesize += newtail - oldtail; + return newtail; } /* diff --git a/net/802/tr.c b/net/802/tr.c index 3f16b17..18c6647 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -76,7 +76,7 @@ static DEFINE_SPINLOCK(rif_lock); static struct timer_list rif_timer; -int sysctl_tr_rif_timeout = 60*10*HZ; +static int sysctl_tr_rif_timeout = 60*10*HZ; static inline unsigned long rif_hash(const unsigned char *addr) { diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 8059fa4..77f04e4 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -563,6 +563,7 @@ static int vlan_dev_stop(struct net_device *dev) struct net_device *real_dev = vlan_dev_info(dev)->real_dev; dev_mc_unsync(real_dev, dev); + dev_unicast_unsync(real_dev, dev); if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(real_dev, -1); if (dev->flags & IFF_PROMISC) @@ -634,9 +635,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1); } -static void vlan_dev_set_multicast_list(struct net_device *vlan_dev) +static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) { dev_mc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); + dev_unicast_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); } /* @@ -702,7 +704,8 @@ void vlan_setup(struct net_device *dev) dev->open = vlan_dev_open; dev->stop = vlan_dev_stop; dev->set_mac_address = vlan_dev_set_mac_address; - dev->set_multicast_list = vlan_dev_set_multicast_list; + dev->set_rx_mode = vlan_dev_set_rx_mode; + dev->set_multicast_list = vlan_dev_set_rx_mode; dev->change_rx_flags = vlan_dev_change_rx_flags; dev->do_ioctl = vlan_dev_ioctl; dev->destructor = free_netdev; diff --git a/net/9p/conv.c b/net/9p/conv.c index aa2aa98..3fe35d5 100644 --- a/net/9p/conv.c +++ b/net/9p/conv.c @@ -128,11 +128,6 @@ static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) return ret; } -static inline void buf_put_string(struct cbuf *buf, const char *s) -{ - buf_put_stringn(buf, s, strlen(s)); -} - static u8 buf_get_int8(struct cbuf *buf) { u8 ret = 0; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 1bc0e85..8fc64e3 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1037,16 +1037,13 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) int err = 0; if (addr_len != sizeof(struct sockaddr_ax25) && - addr_len != sizeof(struct full_sockaddr_ax25)) { - /* support for old structure may go away some time */ + addr_len != sizeof(struct full_sockaddr_ax25)) + /* support for old structure may go away some time + * ax25_bind(): uses old (6 digipeater) socket structure. + */ if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || - (addr_len > sizeof(struct full_sockaddr_ax25))) { + (addr_len > sizeof(struct full_sockaddr_ax25))) return -EINVAL; - } - - printk(KERN_WARNING "ax25_bind(): %s uses old (6 digipeater) socket structure.\n", - current->comm); - } if (addr->fsa_ax25.sax25_family != AF_AX25) return -EINVAL; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 17f7fb7..e13cf5e 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -12,6 +12,8 @@ #undef BT_DBG #define BT_DBG(D...) #endif +static struct workqueue_struct *btaddconn; +static struct workqueue_struct *btdelconn; static inline char *typetostr(int type) { @@ -279,6 +281,8 @@ static void add_conn(struct work_struct *work) struct hci_conn *conn = container_of(work, struct hci_conn, work); int i; + flush_workqueue(btdelconn); + if (device_add(&conn->dev) < 0) { BT_ERR("Failed to register connection device"); return; @@ -313,7 +317,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn) INIT_WORK(&conn->work, add_conn); - schedule_work(&conn->work); + queue_work(btaddconn, &conn->work); } static int __match_tty(struct device *dev, void *data) @@ -349,7 +353,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn) INIT_WORK(&conn->work, del_conn); - schedule_work(&conn->work); + queue_work(btdelconn, &conn->work); } int hci_register_sysfs(struct hci_dev *hdev) @@ -398,28 +402,54 @@ int __init bt_sysfs_init(void) { int err; + btaddconn = create_singlethread_workqueue("btaddconn"); + if (!btaddconn) { + err = -ENOMEM; + goto out; + } + + btdelconn = create_singlethread_workqueue("btdelconn"); + if (!btdelconn) { + err = -ENOMEM; + goto out_del; + } + bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); - if (IS_ERR(bt_platform)) - return PTR_ERR(bt_platform); + if (IS_ERR(bt_platform)) { + err = PTR_ERR(bt_platform); + goto out_platform; + } err = bus_register(&bt_bus); - if (err < 0) { - platform_device_unregister(bt_platform); - return err; - } + if (err < 0) + goto out_bus; bt_class = class_create(THIS_MODULE, "bluetooth"); if (IS_ERR(bt_class)) { - bus_unregister(&bt_bus); - platform_device_unregister(bt_platform); - return PTR_ERR(bt_class); + err = PTR_ERR(bt_class); + goto out_class; } return 0; + +out_class: + bus_unregister(&bt_bus); +out_bus: + platform_device_unregister(bt_platform); +out_platform: + destroy_workqueue(btdelconn); +out_del: + destroy_workqueue(btaddconn); +out: + return err; } void bt_sysfs_cleanup(void) { + destroy_workqueue(btaddconn); + + destroy_workqueue(btdelconn); + class_destroy(bt_class); bus_unregister(&bt_bus); diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 80014ba..1c0efd8 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -828,10 +828,6 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, nf_bridge_pull_encap_header(skb); nf_bridge_save_header(skb); -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - if (nf_bridge->netoutdev) - realoutdev = nf_bridge->netoutdev; -#endif NF_HOOK(pf, NF_INET_POST_ROUTING, skb, NULL, realoutdev, br_nf_dev_queue_xmit); diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c index 41a7807..9853402 100644 --- a/net/bridge/netfilter/ebt_802_3.c +++ b/net/bridge/netfilter/ebt_802_3.c @@ -15,8 +15,8 @@ static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; - struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb); + const struct ebt_802_3_info *info = data; + const struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb); __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; if (info->bitmask & EBT_802_3_SAP) { @@ -40,7 +40,7 @@ static struct ebt_match filter_802_3; static int ebt_802_3_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; + const struct ebt_802_3_info *info = data; if (datalen < sizeof(struct ebt_802_3_info)) return -EINVAL; @@ -50,8 +50,7 @@ static int ebt_802_3_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_802_3 = -{ +static struct ebt_match filter_802_3 __read_mostly = { .name = EBT_802_3_MATCH, .match = ebt_filter_802_3, .check = ebt_802_3_check, @@ -70,4 +69,5 @@ static void __exit ebt_802_3_fini(void) module_init(ebt_802_3_init); module_exit(ebt_802_3_fini); +MODULE_DESCRIPTION("Ebtables: DSAP/SSAP field and SNAP type matching"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c index 6436d30..70b6dca 100644 --- a/net/bridge/netfilter/ebt_among.c +++ b/net/bridge/netfilter/ebt_among.c @@ -25,7 +25,7 @@ static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh, const struct ebt_mac_wormhash_tuple *p; int start, limit, i; uint32_t cmp[2] = { 0, 0 }; - int key = (const unsigned char) mac[5]; + int key = ((const unsigned char *)mac)[5]; memcpy(((char *) cmp) + 2, mac, 6); start = wh->table[key]; @@ -73,15 +73,18 @@ static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash static int get_ip_dst(const struct sk_buff *skb, __be32 *addr) { if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { - struct iphdr _iph, *ih; + const struct iphdr *ih; + struct iphdr _iph; ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); if (ih == NULL) return -1; *addr = ih->daddr; } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { - struct arphdr _arph, *ah; - __be32 buf, *bp; + const struct arphdr *ah; + struct arphdr _arph; + const __be32 *bp; + __be32 buf; ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); if (ah == NULL || @@ -101,15 +104,18 @@ static int get_ip_dst(const struct sk_buff *skb, __be32 *addr) static int get_ip_src(const struct sk_buff *skb, __be32 *addr) { if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { - struct iphdr _iph, *ih; + const struct iphdr *ih; + struct iphdr _iph; ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); if (ih == NULL) return -1; *addr = ih->saddr; } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { - struct arphdr _arph, *ah; - __be32 buf, *bp; + const struct arphdr *ah; + struct arphdr _arph; + const __be32 *bp; + __be32 buf; ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); if (ah == NULL || @@ -130,7 +136,7 @@ static int ebt_filter_among(const struct sk_buff *skb, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_among_info *info = (struct ebt_among_info *) data; + const struct ebt_among_info *info = data; const char *dmac, *smac; const struct ebt_mac_wormhash *wh_dst, *wh_src; __be32 dip = 0, sip = 0; @@ -175,7 +181,7 @@ static int ebt_among_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_among_info *info = (struct ebt_among_info *) data; + const struct ebt_among_info *info = data; int expected_length = sizeof(struct ebt_among_info); const struct ebt_mac_wormhash *wh_dst, *wh_src; int err; @@ -206,7 +212,7 @@ static int ebt_among_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_among = { +static struct ebt_match filter_among __read_mostly = { .name = EBT_AMONG_MATCH, .match = ebt_filter_among, .check = ebt_among_check, @@ -225,4 +231,5 @@ static void __exit ebt_among_fini(void) module_init(ebt_among_init); module_exit(ebt_among_fini); +MODULE_DESCRIPTION("Ebtables: Combined MAC/IP address list matching"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c index 1814139..7c535be 100644 --- a/net/bridge/netfilter/ebt_arp.c +++ b/net/bridge/netfilter/ebt_arp.c @@ -18,8 +18,9 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_arp_info *info = (struct ebt_arp_info *)data; - struct arphdr _arph, *ah; + const struct ebt_arp_info *info = data; + const struct arphdr *ah; + struct arphdr _arph; ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); if (ah == NULL) @@ -35,7 +36,8 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in return EBT_NOMATCH; if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) { - __be32 saddr, daddr, *sap, *dap; + const __be32 *sap, *dap; + __be32 saddr, daddr; if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP)) return EBT_NOMATCH; @@ -61,7 +63,8 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in } if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) { - unsigned char _mac[ETH_ALEN], *mp; + const unsigned char *mp; + unsigned char _mac[ETH_ALEN]; uint8_t verdict, i; if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER)) @@ -100,7 +103,7 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in static int ebt_arp_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_arp_info *info = (struct ebt_arp_info *)data; + const struct ebt_arp_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info))) return -EINVAL; @@ -113,8 +116,7 @@ static int ebt_arp_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_arp = -{ +static struct ebt_match filter_arp __read_mostly = { .name = EBT_ARP_MATCH, .match = ebt_filter_arp, .check = ebt_arp_check, @@ -133,4 +135,5 @@ static void __exit ebt_arp_fini(void) module_init(ebt_arp_init); module_exit(ebt_arp_fini); +MODULE_DESCRIPTION("Ebtables: ARP protocol packet match"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c index 48a80e4..0c42795 100644 --- a/net/bridge/netfilter/ebt_arpreply.c +++ b/net/bridge/netfilter/ebt_arpreply.c @@ -19,10 +19,13 @@ static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data; - __be32 _sip, *siptr, _dip, *diptr; - struct arphdr _ah, *ap; - unsigned char _sha[ETH_ALEN], *shp; + struct ebt_arpreply_info *info = (void *)data; + const __be32 *siptr, *diptr; + __be32 _sip, _dip; + const struct arphdr *ap; + struct arphdr _ah; + const unsigned char *shp; + unsigned char _sha[ETH_ALEN]; ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); if (ap == NULL) @@ -58,7 +61,7 @@ static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr, static int ebt_target_reply_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data; + const struct ebt_arpreply_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_arpreply_info))) return -EINVAL; @@ -73,8 +76,7 @@ static int ebt_target_reply_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_target reply_target = -{ +static struct ebt_target reply_target __read_mostly = { .name = EBT_ARPREPLY_TARGET, .target = ebt_target_reply, .check = ebt_target_reply_check, @@ -93,4 +95,5 @@ static void __exit ebt_arpreply_fini(void) module_init(ebt_arpreply_init); module_exit(ebt_arpreply_fini); +MODULE_DESCRIPTION("Ebtables: ARP reply target"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index 74262e9..e700cbf 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c @@ -18,7 +18,7 @@ static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_nat_info *info = (struct ebt_nat_info *)data; + const struct ebt_nat_info *info = data; if (skb_make_writable(skb, 0)) return NF_DROP; @@ -30,7 +30,7 @@ static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr, static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_nat_info *info = (struct ebt_nat_info *)data; + const struct ebt_nat_info *info = data; if (BASE_CHAIN && info->target == EBT_RETURN) return -EINVAL; @@ -46,8 +46,7 @@ static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_target dnat = -{ +static struct ebt_target dnat __read_mostly = { .name = EBT_DNAT_TARGET, .target = ebt_target_dnat, .check = ebt_target_dnat_check, @@ -66,4 +65,5 @@ static void __exit ebt_dnat_fini(void) module_init(ebt_dnat_init); module_exit(ebt_dnat_fini); +MODULE_DESCRIPTION("Ebtables: Destination MAC address translation"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index 69f7f0a..65caa00 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c @@ -28,9 +28,11 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_ip_info *info = (struct ebt_ip_info *)data; - struct iphdr _iph, *ih; - struct tcpudphdr _ports, *pptr; + const struct ebt_ip_info *info = data; + const struct iphdr *ih; + struct iphdr _iph; + const struct tcpudphdr *pptr; + struct tcpudphdr _ports; ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); if (ih == NULL) @@ -79,7 +81,7 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, static int ebt_ip_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_ip_info *info = (struct ebt_ip_info *)data; + const struct ebt_ip_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info))) return -EINVAL; @@ -105,8 +107,7 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_ip = -{ +static struct ebt_match filter_ip __read_mostly = { .name = EBT_IP_MATCH, .match = ebt_filter_ip, .check = ebt_ip_check, @@ -125,4 +126,5 @@ static void __exit ebt_ip_fini(void) module_init(ebt_ip_init); module_exit(ebt_ip_fini); +MODULE_DESCRIPTION("Ebtables: IPv4 protocol packet match"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c index d48fa5c..8cbdc01c 100644 --- a/net/bridge/netfilter/ebt_limit.c +++ b/net/bridge/netfilter/ebt_limit.c @@ -69,7 +69,7 @@ user2credits(u_int32_t user) static int ebt_limit_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_limit_info *info = (struct ebt_limit_info *)data; + struct ebt_limit_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info))) return -EINVAL; @@ -90,8 +90,7 @@ static int ebt_limit_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match ebt_limit_reg = -{ +static struct ebt_match ebt_limit_reg __read_mostly = { .name = EBT_LIMIT_MATCH, .match = ebt_limit_match, .check = ebt_limit_check, @@ -110,4 +109,5 @@ static void __exit ebt_limit_fini(void) module_init(ebt_limit_init); module_exit(ebt_limit_fini); +MODULE_DESCRIPTION("Ebtables: Rate-limit match"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 3be9e98..0b209e4 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -24,7 +24,7 @@ static DEFINE_SPINLOCK(ebt_log_lock); static int ebt_log_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_log_info *info = (struct ebt_log_info *)data; + struct ebt_log_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_log_info))) return -EINVAL; @@ -50,7 +50,7 @@ struct arppayload unsigned char ip_dst[4]; }; -static void print_MAC(unsigned char *p) +static void print_MAC(const unsigned char *p) { int i; @@ -84,7 +84,8 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, if ((bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto == htons(ETH_P_IP)){ - struct iphdr _iph, *ih; + const struct iphdr *ih; + struct iphdr _iph; ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); if (ih == NULL) { @@ -99,7 +100,8 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, ih->protocol == IPPROTO_UDPLITE || ih->protocol == IPPROTO_SCTP || ih->protocol == IPPROTO_DCCP) { - struct tcpudphdr _ports, *pptr; + const struct tcpudphdr *pptr; + struct tcpudphdr _ports; pptr = skb_header_pointer(skb, ih->ihl*4, sizeof(_ports), &_ports); @@ -116,7 +118,8 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, if ((bitmask & EBT_LOG_ARP) && ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) || (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) { - struct arphdr _arph, *ah; + const struct arphdr *ah; + struct arphdr _arph; ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); if (ah == NULL) { @@ -132,7 +135,8 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, if (ah->ar_hrd == htons(1) && ah->ar_hln == ETH_ALEN && ah->ar_pln == sizeof(__be32)) { - struct arppayload _arpp, *ap; + const struct arppayload *ap; + struct arppayload _arpp; ap = skb_header_pointer(skb, sizeof(_arph), sizeof(_arpp), &_arpp); @@ -160,7 +164,7 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_log_info *info = (struct ebt_log_info *)data; + const struct ebt_log_info *info = data; struct nf_loginfo li; li.type = NF_LOG_TYPE_LOG; @@ -208,4 +212,5 @@ static void __exit ebt_log_fini(void) module_init(ebt_log_init); module_exit(ebt_log_fini); +MODULE_DESCRIPTION("Ebtables: Packet logging to syslog"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 6cba543..36723f4 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c @@ -21,7 +21,7 @@ static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; + const struct ebt_mark_t_info *info = data; int action = info->target & -16; if (action == MARK_SET_VALUE) @@ -39,7 +39,7 @@ static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr, static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; + const struct ebt_mark_t_info *info = data; int tmp; if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) @@ -57,8 +57,7 @@ static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_target mark_target = -{ +static struct ebt_target mark_target __read_mostly = { .name = EBT_MARK_TARGET, .target = ebt_target_mark, .check = ebt_target_mark_check, @@ -77,4 +76,5 @@ static void __exit ebt_mark_fini(void) module_init(ebt_mark_init); module_exit(ebt_mark_fini); +MODULE_DESCRIPTION("Ebtables: Packet mark modification"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c index 6b0d216..9b0a454 100644 --- a/net/bridge/netfilter/ebt_mark_m.c +++ b/net/bridge/netfilter/ebt_mark_m.c @@ -16,7 +16,7 @@ static int ebt_filter_mark(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; + const struct ebt_mark_m_info *info = data; if (info->bitmask & EBT_MARK_OR) return !(!!(skb->mark & info->mask) ^ info->invert); @@ -26,7 +26,7 @@ static int ebt_filter_mark(const struct sk_buff *skb, static int ebt_mark_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; + const struct ebt_mark_m_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_m_info))) return -EINVAL; @@ -39,8 +39,7 @@ static int ebt_mark_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_mark = -{ +static struct ebt_match filter_mark __read_mostly = { .name = EBT_MARK_MATCH, .match = ebt_filter_mark, .check = ebt_mark_check, @@ -59,4 +58,5 @@ static void __exit ebt_mark_m_fini(void) module_init(ebt_mark_m_init); module_exit(ebt_mark_m_fini); +MODULE_DESCRIPTION("Ebtables: Packet mark match"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c index 4fffd70..676db32 100644 --- a/net/bridge/netfilter/ebt_pkttype.c +++ b/net/bridge/netfilter/ebt_pkttype.c @@ -18,7 +18,7 @@ static int ebt_filter_pkttype(const struct sk_buff *skb, const void *data, unsigned int datalen) { - struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data; + const struct ebt_pkttype_info *info = data; return (skb->pkt_type != info->pkt_type) ^ info->invert; } @@ -26,7 +26,7 @@ static int ebt_filter_pkttype(const struct sk_buff *skb, static int ebt_pkttype_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data; + const struct ebt_pkttype_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_pkttype_info))) return -EINVAL; @@ -36,8 +36,7 @@ static int ebt_pkttype_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_pkttype = -{ +static struct ebt_match filter_pkttype __read_mostly = { .name = EBT_PKTTYPE_MATCH, .match = ebt_filter_pkttype, .check = ebt_pkttype_check, @@ -56,4 +55,5 @@ static void __exit ebt_pkttype_fini(void) module_init(ebt_pkttype_init); module_exit(ebt_pkttype_fini); +MODULE_DESCRIPTION("Ebtables: Link layer packet type match"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c index 422cb83..bfdf2fb 100644 --- a/net/bridge/netfilter/ebt_redirect.c +++ b/net/bridge/netfilter/ebt_redirect.c @@ -19,7 +19,7 @@ static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; + const struct ebt_redirect_info *info = data; if (skb_make_writable(skb, 0)) return NF_DROP; @@ -36,7 +36,7 @@ static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr, static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; + const struct ebt_redirect_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_redirect_info))) return -EINVAL; @@ -51,8 +51,7 @@ static int ebt_target_redirect_check(const char *tablename, unsigned int hookmas return 0; } -static struct ebt_target redirect_target = -{ +static struct ebt_target redirect_target __read_mostly = { .name = EBT_REDIRECT_TARGET, .target = ebt_target_redirect, .check = ebt_target_redirect_check, @@ -71,4 +70,5 @@ static void __exit ebt_redirect_fini(void) module_init(ebt_redirect_init); module_exit(ebt_redirect_fini); +MODULE_DESCRIPTION("Ebtables: Packet redirection to localhost"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index 425ac92..e252dab 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c @@ -20,7 +20,7 @@ static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_nat_info *info = (struct ebt_nat_info *) data; + const struct ebt_nat_info *info = data; if (skb_make_writable(skb, 0)) return NF_DROP; @@ -28,7 +28,8 @@ static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr, memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN); if (!(info->target & NAT_ARP_BIT) && eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { - struct arphdr _ah, *ap; + const struct arphdr *ap; + struct arphdr _ah; ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); if (ap == NULL) @@ -45,7 +46,7 @@ out: static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_nat_info *info = (struct ebt_nat_info *) data; + const struct ebt_nat_info *info = data; int tmp; if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) @@ -67,8 +68,7 @@ static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_target snat = -{ +static struct ebt_target snat __read_mostly = { .name = EBT_SNAT_TARGET, .target = ebt_target_snat, .check = ebt_target_snat_check, @@ -87,4 +87,5 @@ static void __exit ebt_snat_fini(void) module_init(ebt_snat_init); module_exit(ebt_snat_fini); +MODULE_DESCRIPTION("Ebtables: Source MAC address translation"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c index 31b7736..40f36d3 100644 --- a/net/bridge/netfilter/ebt_stp.c +++ b/net/bridge/netfilter/ebt_stp.c @@ -40,10 +40,10 @@ struct stp_config_pdu { #define NR16(p) (p[0] << 8 | p[1]) #define NR32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) -static int ebt_filter_config(struct ebt_stp_info *info, - struct stp_config_pdu *stpc) +static int ebt_filter_config(const struct ebt_stp_info *info, + const struct stp_config_pdu *stpc) { - struct ebt_stp_config_info *c; + const struct ebt_stp_config_info *c; uint16_t v16; uint32_t v32; int verdict, i; @@ -122,9 +122,10 @@ static int ebt_filter_config(struct ebt_stp_info *info, static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_stp_info *info = (struct ebt_stp_info *)data; - struct stp_header _stph, *sp; - uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; + const struct ebt_stp_info *info = data; + const struct stp_header *sp; + struct stp_header _stph; + const uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph); if (sp == NULL) @@ -140,7 +141,8 @@ static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in if (sp->type == BPDU_TYPE_CONFIG && info->bitmask & EBT_STP_CONFIG_MASK) { - struct stp_config_pdu _stpc, *st; + const struct stp_config_pdu *st; + struct stp_config_pdu _stpc; st = skb_header_pointer(skb, sizeof(_stph), sizeof(_stpc), &_stpc); @@ -154,10 +156,10 @@ static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in static int ebt_stp_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_stp_info *info = (struct ebt_stp_info *)data; - int len = EBT_ALIGN(sizeof(struct ebt_stp_info)); - uint8_t bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; - uint8_t msk[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + const struct ebt_stp_info *info = data; + const unsigned int len = EBT_ALIGN(sizeof(struct ebt_stp_info)); + const uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; + const uint8_t msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK || !(info->bitmask & EBT_STP_MASK)) @@ -172,8 +174,7 @@ static int ebt_stp_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_stp = -{ +static struct ebt_match filter_stp __read_mostly = { .name = EBT_STP_MATCH, .match = ebt_filter_stp, .check = ebt_stp_check, @@ -192,4 +193,5 @@ static void __exit ebt_stp_fini(void) module_init(ebt_stp_init); module_exit(ebt_stp_fini); +MODULE_DESCRIPTION("Ebtables: Spanning Tree Protocol packet match"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 8e7b00b..2d4c9ef 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -249,7 +249,7 @@ static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data; + const struct ebt_ulog_info *uloginfo = data; ebt_ulog_packet(hooknr, skb, in, out, uloginfo, NULL); } @@ -258,7 +258,7 @@ static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, static int ebt_ulog_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data; + struct ebt_ulog_info *uloginfo = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) || uloginfo->nlgroup > 31) @@ -272,7 +272,7 @@ static int ebt_ulog_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_watcher ulog = { +static struct ebt_watcher ulog __read_mostly = { .name = EBT_ULOG_WATCHER, .watcher = ebt_ulog, .check = ebt_ulog_check, @@ -340,5 +340,4 @@ module_init(ebt_ulog_init); module_exit(ebt_ulog_fini); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); -MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet" - " frames"); +MODULE_DESCRIPTION("Ebtables: Packet logging to netlink using ULOG"); diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c index 0ddf749..ab60b0d 100644 --- a/net/bridge/netfilter/ebt_vlan.c +++ b/net/bridge/netfilter/ebt_vlan.c @@ -31,8 +31,7 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages"); MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>"); -MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v" - MODULE_VERS); +MODULE_DESCRIPTION("Ebtables: 802.1Q VLAN tag match"); MODULE_LICENSE("GPL"); @@ -46,8 +45,9 @@ ebt_filter_vlan(const struct sk_buff *skb, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_vlan_info *info = (struct ebt_vlan_info *) data; - struct vlan_hdr _frame, *fp; + const struct ebt_vlan_info *info = data; + const struct vlan_hdr *fp; + struct vlan_hdr _frame; unsigned short TCI; /* Whole TCI, given from parsed frame */ unsigned short id; /* VLAN ID, given from frame TCI */ @@ -91,7 +91,7 @@ ebt_check_vlan(const char *tablename, unsigned int hooknr, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_vlan_info *info = (struct ebt_vlan_info *) data; + struct ebt_vlan_info *info = data; /* Parameters buffer overflow check */ if (datalen != EBT_ALIGN(sizeof(struct ebt_vlan_info))) { @@ -169,7 +169,7 @@ ebt_check_vlan(const char *tablename, return 0; } -static struct ebt_match filter_vlan = { +static struct ebt_match filter_vlan __read_mostly = { .name = EBT_VLAN_MATCH, .match = ebt_filter_vlan, .check = ebt_check_vlan, diff --git a/net/core/dev.c b/net/core/dev.c index c9c593e..edaff27 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2962,6 +2962,102 @@ int dev_unicast_add(struct net_device *dev, void *addr, int alen) } EXPORT_SYMBOL(dev_unicast_add); +int __dev_addr_sync(struct dev_addr_list **to, int *to_count, + struct dev_addr_list **from, int *from_count) +{ + struct dev_addr_list *da, *next; + int err = 0; + + da = *from; + while (da != NULL) { + next = da->next; + if (!da->da_synced) { + err = __dev_addr_add(to, to_count, + da->da_addr, da->da_addrlen, 0); + if (err < 0) + break; + da->da_synced = 1; + da->da_users++; + } else if (da->da_users == 1) { + __dev_addr_delete(to, to_count, + da->da_addr, da->da_addrlen, 0); + __dev_addr_delete(from, from_count, + da->da_addr, da->da_addrlen, 0); + } + da = next; + } + return err; +} + +void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, + struct dev_addr_list **from, int *from_count) +{ + struct dev_addr_list *da, *next; + + da = *from; + while (da != NULL) { + next = da->next; + if (da->da_synced) { + __dev_addr_delete(to, to_count, + da->da_addr, da->da_addrlen, 0); + da->da_synced = 0; + __dev_addr_delete(from, from_count, + da->da_addr, da->da_addrlen, 0); + } + da = next; + } +} + +/** + * dev_unicast_sync - Synchronize device's unicast list to another device + * @to: destination device + * @from: source device + * + * Add newly added addresses to the destination device and release + * addresses that have no users left. The source device must be + * locked by netif_tx_lock_bh. + * + * This function is intended to be called from the dev->set_rx_mode + * function of layered software devices. + */ +int dev_unicast_sync(struct net_device *to, struct net_device *from) +{ + int err = 0; + + netif_tx_lock_bh(to); + err = __dev_addr_sync(&to->uc_list, &to->uc_count, + &from->uc_list, &from->uc_count); + if (!err) + __dev_set_rx_mode(to); + netif_tx_unlock_bh(to); + return err; +} +EXPORT_SYMBOL(dev_unicast_sync); + +/** + * dev_unicast_unsync - Remove synchronized addresses from the destination + * device + * @to: destination device + * @from: source device + * + * Remove all addresses that were added to the destination device by + * dev_unicast_sync(). This function is intended to be called from the + * dev->stop function of layered software devices. + */ +void dev_unicast_unsync(struct net_device *to, struct net_device *from) +{ + netif_tx_lock_bh(from); + netif_tx_lock_bh(to); + + __dev_addr_unsync(&to->uc_list, &to->uc_count, + &from->uc_list, &from->uc_count); + __dev_set_rx_mode(to); + + netif_tx_unlock_bh(to); + netif_tx_unlock_bh(from); +} +EXPORT_SYMBOL(dev_unicast_unsync); + static void __dev_addr_discard(struct dev_addr_list **list) { struct dev_addr_list *tmp; diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index cadbfbf..cec5825 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -113,32 +113,15 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) * locked by netif_tx_lock_bh. * * This function is intended to be called from the dev->set_multicast_list - * function of layered software devices. + * or dev->set_rx_mode function of layered software devices. */ int dev_mc_sync(struct net_device *to, struct net_device *from) { - struct dev_addr_list *da, *next; int err = 0; netif_tx_lock_bh(to); - da = from->mc_list; - while (da != NULL) { - next = da->next; - if (!da->da_synced) { - err = __dev_addr_add(&to->mc_list, &to->mc_count, - da->da_addr, da->da_addrlen, 0); - if (err < 0) - break; - da->da_synced = 1; - da->da_users++; - } else if (da->da_users == 1) { - __dev_addr_delete(&to->mc_list, &to->mc_count, - da->da_addr, da->da_addrlen, 0); - __dev_addr_delete(&from->mc_list, &from->mc_count, - da->da_addr, da->da_addrlen, 0); - } - da = next; - } + err = __dev_addr_sync(&to->mc_list, &to->mc_count, + &from->mc_list, &from->mc_count); if (!err) __dev_set_rx_mode(to); netif_tx_unlock_bh(to); @@ -160,23 +143,11 @@ EXPORT_SYMBOL(dev_mc_sync); */ void dev_mc_unsync(struct net_device *to, struct net_device *from) { - struct dev_addr_list *da, *next; - netif_tx_lock_bh(from); netif_tx_lock_bh(to); - da = from->mc_list; - while (da != NULL) { - next = da->next; - if (da->da_synced) { - __dev_addr_delete(&to->mc_list, &to->mc_count, - da->da_addr, da->da_addrlen, 0); - da->da_synced = 0; - __dev_addr_delete(&from->mc_list, &from->mc_count, - da->da_addr, da->da_addrlen, 0); - } - da = next; - } + __dev_addr_unsync(&to->mc_list, &to->mc_count, + &from->mc_list, &from->mc_count); __dev_set_rx_mode(to); netif_tx_unlock_bh(to); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index eebccdb..bfcdfae 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -170,8 +170,6 @@ #define VERSION "pktgen v2.69: Packet Generator for packet performance testing.\n" -/* The buckets are exponential in 'width' */ -#define LAT_BUCKETS_MAX 32 #define IP_NAME_SZ 32 #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ #define MPLS_STACK_BOTTOM htonl(0x00000100) @@ -2044,7 +2042,6 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us) __u64 now; start = now = getCurUs(); - printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now)); while (now < spin_until_us) { /* TODO: optimize sleeping behavior */ if (spin_until_us - now > jiffies_to_usecs(1) + 1) diff --git a/net/core/sock.c b/net/core/sock.c index 1c4b1cd..433715f 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -667,6 +667,13 @@ set_rcvbuf: else clear_bit(SOCK_PASSSEC, &sock->flags); break; + case SO_MARK: + if (!capable(CAP_NET_ADMIN)) + ret = -EPERM; + else { + sk->sk_mark = val; + } + break; /* We implement the SO_SNDLOWAT etc to not be settable (1003.1g 5.3) */ @@ -836,6 +843,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname, case SO_PEERSEC: return security_socket_getpeersec_stream(sock, optval, optlen, len); + case SO_MARK: + v.val = sk->sk_mark; + break; + default: return -ENOPROTOOPT; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 9e38b0d..c982ad8 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -218,7 +218,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) return; } - sk = inet_lookup(&dccp_hashinfo, iph->daddr, dh->dccph_dport, + sk = inet_lookup(&init_net, &dccp_hashinfo, iph->daddr, dh->dccph_dport, iph->saddr, dh->dccph_sport, inet_iif(skb)); if (sk == NULL) { ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); @@ -436,7 +436,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) if (req != NULL) return dccp_check_req(sk, skb, req, prev); - nsk = inet_lookup_established(&dccp_hashinfo, + nsk = inet_lookup_established(&init_net, &dccp_hashinfo, iph->saddr, dh->dccph_sport, iph->daddr, dh->dccph_dport, inet_iif(skb)); @@ -817,7 +817,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) /* Step 2: * Look up flow ID in table and get corresponding socket */ - sk = __inet_lookup(&dccp_hashinfo, + sk = __inet_lookup(&init_net, &dccp_hashinfo, iph->saddr, dh->dccph_sport, iph->daddr, dh->dccph_dport, inet_iif(skb)); /* diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index f42b75c..ed0a005 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -101,8 +101,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int err; __u64 seq; - sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport, - &hdr->saddr, dh->dccph_sport, inet6_iif(skb)); + sk = inet6_lookup(&init_net, &dccp_hashinfo, &hdr->daddr, dh->dccph_dport, + &hdr->saddr, dh->dccph_sport, inet6_iif(skb)); if (sk == NULL) { ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); @@ -366,7 +366,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) if (req != NULL) return dccp_check_req(sk, skb, req, prev); - nsk = __inet6_lookup_established(&dccp_hashinfo, + nsk = __inet6_lookup_established(&init_net, &dccp_hashinfo, &iph->saddr, dh->dccph_sport, &iph->daddr, ntohs(dh->dccph_dport), inet6_iif(skb)); @@ -797,7 +797,7 @@ static int dccp_v6_rcv(struct sk_buff *skb) /* Step 2: * Look up flow ID in table and get corresponding socket */ - sk = __inet6_lookup(&dccp_hashinfo, &ipv6_hdr(skb)->saddr, + sk = __inet6_lookup(&init_net, &dccp_hashinfo, &ipv6_hdr(skb)->saddr, dh->dccph_sport, &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport), inet6_iif(skb)); diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 24e2b72..19880b0 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -343,6 +343,7 @@ config INET_ESP tristate "IP: ESP transformation" select XFRM select CRYPTO + select CRYPTO_AEAD select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_CBC diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index d76803a..9d4555e 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -300,7 +300,7 @@ static void ah_destroy(struct xfrm_state *x) } -static struct xfrm_type ah_type = +static const struct xfrm_type ah_type = { .description = "AH4", .owner = THIS_MODULE, diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 5976c59..8e17f65 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -558,8 +558,9 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt) */ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, - unsigned char *dest_hw, unsigned char *src_hw, - unsigned char *target_hw) + const unsigned char *dest_hw, + const unsigned char *src_hw, + const unsigned char *target_hw) { struct sk_buff *skb; struct arphdr *arp; @@ -672,8 +673,8 @@ void arp_xmit(struct sk_buff *skb) */ void arp_send(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, - unsigned char *dest_hw, unsigned char *src_hw, - unsigned char *target_hw) + const unsigned char *dest_hw, const unsigned char *src_hw, + const unsigned char *target_hw) { struct sk_buff *skb; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 21f71bf..f282b26 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -64,7 +64,7 @@ #include <net/rtnetlink.h> #include <net/net_namespace.h> -struct ipv4_devconf ipv4_devconf = { +static struct ipv4_devconf ipv4_devconf = { .data = { [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1, [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1, @@ -485,46 +485,41 @@ errout: return err; } -static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) +static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh) { struct nlattr *tb[IFA_MAX+1]; struct in_ifaddr *ifa; struct ifaddrmsg *ifm; struct net_device *dev; struct in_device *in_dev; - int err = -EINVAL; + int err; err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); if (err < 0) goto errout; ifm = nlmsg_data(nlh); - if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) { - err = -EINVAL; + err = -EINVAL; + if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) goto errout; - } - dev = __dev_get_by_index(&init_net, ifm->ifa_index); - if (dev == NULL) { - err = -ENODEV; + dev = __dev_get_by_index(net, ifm->ifa_index); + err = -ENODEV; + if (dev == NULL) goto errout; - } in_dev = __in_dev_get_rtnl(dev); - if (in_dev == NULL) { - err = -ENOBUFS; + err = -ENOBUFS; + if (in_dev == NULL) goto errout; - } ifa = inet_alloc_ifa(); - if (ifa == NULL) { + if (ifa == NULL) /* * A potential indev allocation can be left alive, it stays * assigned to its device and is destroy with it. */ - err = -ENOBUFS; goto errout; - } ipv4_devconf_setall(in_dev); in_dev_hold(in_dev); @@ -568,7 +563,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg if (net != &init_net) return -EINVAL; - ifa = rtm_to_ifaddr(nlh); + ifa = rtm_to_ifaddr(net, nlh); if (IS_ERR(ifa)) return PTR_ERR(ifa); @@ -1182,7 +1177,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) s_ip_idx = ip_idx = cb->args[1]; idx = 0; - for_each_netdev(&init_net, dev) { + for_each_netdev(net, dev) { if (idx < s_idx) goto cont; if (idx > s_idx) @@ -1216,7 +1211,9 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh, struct sk_buff *skb; u32 seq = nlh ? nlh->nlmsg_seq : 0; int err = -ENOBUFS; + struct net *net; + net = ifa->ifa_dev->dev->nd_net; skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL); if (skb == NULL) goto errout; @@ -1228,10 +1225,10 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh, kfree_skb(skb); goto errout; } - err = rtnl_notify(skb, &init_net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); + err = rtnl_notify(skb, net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); errout: if (err < 0) - rtnl_set_sk_err(&init_net, RTNLGRP_IPV4_IFADDR, err); + rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err); } #ifdef CONFIG_SYSCTL diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 28ea5c7..258d176 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -1,27 +1,118 @@ +#include <crypto/aead.h> +#include <crypto/authenc.h> #include <linux/err.h> #include <linux/module.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/esp.h> #include <linux/scatterlist.h> -#include <linux/crypto.h> #include <linux/kernel.h> #include <linux/pfkeyv2.h> -#include <linux/random.h> +#include <linux/rtnetlink.h> +#include <linux/slab.h> #include <linux/spinlock.h> #include <linux/in6.h> #include <net/icmp.h> #include <net/protocol.h> #include <net/udp.h> +struct esp_skb_cb { + struct xfrm_skb_cb xfrm; + void *tmp; +}; + +#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) + +/* + * Allocate an AEAD request structure with extra space for SG and IV. + * + * For alignment considerations the IV is placed at the front, followed + * by the request and finally the SG list. + * + * TODO: Use spare space in skb for this where possible. + */ +static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags) +{ + unsigned int len; + + len = crypto_aead_ivsize(aead); + if (len) { + len += crypto_aead_alignmask(aead) & + ~(crypto_tfm_ctx_alignment() - 1); + len = ALIGN(len, crypto_tfm_ctx_alignment()); + } + + len += sizeof(struct aead_givcrypt_request) + crypto_aead_reqsize(aead); + len = ALIGN(len, __alignof__(struct scatterlist)); + + len += sizeof(struct scatterlist) * nfrags; + + return kmalloc(len, GFP_ATOMIC); +} + +static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp) +{ + return crypto_aead_ivsize(aead) ? + PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp; +} + +static inline struct aead_givcrypt_request *esp_tmp_givreq( + struct crypto_aead *aead, u8 *iv) +{ + struct aead_givcrypt_request *req; + + req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead), + crypto_tfm_ctx_alignment()); + aead_givcrypt_set_tfm(req, aead); + return req; +} + +static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv) +{ + struct aead_request *req; + + req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead), + crypto_tfm_ctx_alignment()); + aead_request_set_tfm(req, aead); + return req; +} + +static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead, + struct aead_request *req) +{ + return (void *)ALIGN((unsigned long)(req + 1) + + crypto_aead_reqsize(aead), + __alignof__(struct scatterlist)); +} + +static inline struct scatterlist *esp_givreq_sg( + struct crypto_aead *aead, struct aead_givcrypt_request *req) +{ + return (void *)ALIGN((unsigned long)(req + 1) + + crypto_aead_reqsize(aead), + __alignof__(struct scatterlist)); +} + +static void esp_output_done(struct crypto_async_request *base, int err) +{ + struct sk_buff *skb = base->data; + + kfree(ESP_SKB_CB(skb)->tmp); + xfrm_output_resume(skb, err); +} + static int esp_output(struct xfrm_state *x, struct sk_buff *skb) { int err; struct ip_esp_hdr *esph; - struct crypto_blkcipher *tfm; - struct blkcipher_desc desc; + struct crypto_aead *aead; + struct aead_givcrypt_request *req; + struct scatterlist *sg; + struct scatterlist *asg; struct esp_data *esp; struct sk_buff *trailer; + void *tmp; + u8 *iv; u8 *tail; int blksize; int clen; @@ -36,18 +127,27 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) clen = skb->len; esp = x->data; - alen = esp->auth.icv_trunc_len; - tfm = esp->conf.tfm; - desc.tfm = tfm; - desc.flags = 0; - blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); + aead = esp->aead; + alen = crypto_aead_authsize(aead); + + blksize = ALIGN(crypto_aead_blocksize(aead), 4); clen = ALIGN(clen + 2, blksize); - if (esp->conf.padlen) - clen = ALIGN(clen, esp->conf.padlen); + if (esp->padlen) + clen = ALIGN(clen, esp->padlen); + + if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0) + goto error; + nfrags = err; - if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) + tmp = esp_alloc_tmp(aead, nfrags + 1); + if (!tmp) goto error; + iv = esp_tmp_iv(aead, tmp); + req = esp_tmp_givreq(aead, iv); + asg = esp_givreq_sg(aead, req); + sg = asg + 1; + /* Fill padding... */ tail = skb_tail_pointer(trailer); do { @@ -56,28 +156,34 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) tail[i] = i + 1; } while (0); tail[clen - skb->len - 2] = (clen - skb->len) - 2; - pskb_put(skb, trailer, clen - skb->len); + tail[clen - skb->len - 1] = *skb_mac_header(skb); + pskb_put(skb, trailer, clen - skb->len + alen); skb_push(skb, -skb_network_offset(skb)); esph = ip_esp_hdr(skb); - *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb); *skb_mac_header(skb) = IPPROTO_ESP; - spin_lock_bh(&x->lock); - /* this is non-NULL only with UDP Encapsulation */ if (x->encap) { struct xfrm_encap_tmpl *encap = x->encap; struct udphdr *uh; __be32 *udpdata32; + unsigned int sport, dport; + int encap_type; + + spin_lock_bh(&x->lock); + sport = encap->encap_sport; + dport = encap->encap_dport; + encap_type = encap->encap_type; + spin_unlock_bh(&x->lock); uh = (struct udphdr *)esph; - uh->source = encap->encap_sport; - uh->dest = encap->encap_dport; - uh->len = htons(skb->len + alen - skb_transport_offset(skb)); + uh->source = sport; + uh->dest = dport; + uh->len = htons(skb->len - skb_transport_offset(skb)); uh->check = 0; - switch (encap->encap_type) { + switch (encap_type) { default: case UDP_ENCAP_ESPINUDP: esph = (struct ip_esp_hdr *)(uh + 1); @@ -95,131 +201,45 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esph->spi = x->id.spi; esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq); - if (esp->conf.ivlen) { - if (unlikely(!esp->conf.ivinitted)) { - get_random_bytes(esp->conf.ivec, esp->conf.ivlen); - esp->conf.ivinitted = 1; - } - crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); - } - - do { - struct scatterlist *sg = &esp->sgbuf[0]; - - if (unlikely(nfrags > ESP_NUM_FAST_SG)) { - sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); - if (!sg) - goto unlock; - } - sg_init_table(sg, nfrags); - skb_to_sgvec(skb, sg, - esph->enc_data + - esp->conf.ivlen - - skb->data, clen); - err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); - if (unlikely(sg != &esp->sgbuf[0])) - kfree(sg); - } while (0); - - if (unlikely(err)) - goto unlock; - - if (esp->conf.ivlen) { - memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen); - crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen); - } + sg_init_table(sg, nfrags); + skb_to_sgvec(skb, sg, + esph->enc_data + crypto_aead_ivsize(aead) - skb->data, + clen + alen); + sg_init_one(asg, esph, sizeof(*esph)); + + aead_givcrypt_set_callback(req, 0, esp_output_done, skb); + aead_givcrypt_set_crypt(req, sg, sg, clen, iv); + aead_givcrypt_set_assoc(req, asg, sizeof(*esph)); + aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq); + + ESP_SKB_CB(skb)->tmp = tmp; + err = crypto_aead_givencrypt(req); + if (err == -EINPROGRESS) + goto error; - if (esp->auth.icv_full_len) { - err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data, - sizeof(*esph) + esp->conf.ivlen + clen); - memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen); - } + if (err == -EBUSY) + err = NET_XMIT_DROP; -unlock: - spin_unlock_bh(&x->lock); + kfree(tmp); error: return err; } -/* - * Note: detecting truncated vs. non-truncated authentication data is very - * expensive, so we only support truncated data, which is the recommended - * and common case. - */ -static int esp_input(struct xfrm_state *x, struct sk_buff *skb) +static int esp_input_done2(struct sk_buff *skb, int err) { struct iphdr *iph; - struct ip_esp_hdr *esph; + struct xfrm_state *x = xfrm_input_state(skb); struct esp_data *esp = x->data; - struct crypto_blkcipher *tfm = esp->conf.tfm; - struct blkcipher_desc desc = { .tfm = tfm }; - struct sk_buff *trailer; - int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); - int alen = esp->auth.icv_trunc_len; - int elen = skb->len - sizeof(*esph) - esp->conf.ivlen - alen; - int nfrags; + struct crypto_aead *aead = esp->aead; + int alen = crypto_aead_authsize(aead); + int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead); + int elen = skb->len - hlen; int ihl; u8 nexthdr[2]; - struct scatterlist *sg; int padlen; - int err = -EINVAL; - - if (!pskb_may_pull(skb, sizeof(*esph))) - goto out; - - if (elen <= 0 || (elen & (blksize-1))) - goto out; - - if ((err = skb_cow_data(skb, 0, &trailer)) < 0) - goto out; - nfrags = err; - - skb->ip_summed = CHECKSUM_NONE; - - spin_lock(&x->lock); - - /* If integrity check is required, do this. */ - if (esp->auth.icv_full_len) { - u8 sum[alen]; - err = esp_mac_digest(esp, skb, 0, skb->len - alen); - if (err) - goto unlock; - - if (skb_copy_bits(skb, skb->len - alen, sum, alen)) - BUG(); - - if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { - err = -EBADMSG; - goto unlock; - } - } - - esph = (struct ip_esp_hdr *)skb->data; - - /* Get ivec. This can be wrong, check against another impls. */ - if (esp->conf.ivlen) - crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen); - - sg = &esp->sgbuf[0]; - - if (unlikely(nfrags > ESP_NUM_FAST_SG)) { - err = -ENOMEM; - sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); - if (!sg) - goto unlock; - } - sg_init_table(sg, nfrags); - skb_to_sgvec(skb, sg, - sizeof(*esph) + esp->conf.ivlen, - elen); - err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); - if (unlikely(sg != &esp->sgbuf[0])) - kfree(sg); - -unlock: - spin_unlock(&x->lock); + kfree(ESP_SKB_CB(skb)->tmp); if (unlikely(err)) goto out; @@ -229,15 +249,11 @@ unlock: err = -EINVAL; padlen = nexthdr[0]; - if (padlen+2 >= elen) + if (padlen + 2 + alen >= elen) goto out; /* ... check padding bits here. Silly. :-) */ - /* RFC4303: Drop dummy packets without any error */ - if (nexthdr[1] == IPPROTO_NONE) - goto out; - iph = ip_hdr(skb); ihl = iph->ihl * 4; @@ -279,10 +295,87 @@ unlock: } pskb_trim(skb, skb->len - alen - padlen - 2); - __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen); + __skb_pull(skb, hlen); skb_set_transport_header(skb, -ihl); - return nexthdr[1]; + err = nexthdr[1]; + + /* RFC4303: Drop dummy packets without any error */ + if (err == IPPROTO_NONE) + err = -EINVAL; + +out: + return err; +} + +static void esp_input_done(struct crypto_async_request *base, int err) +{ + struct sk_buff *skb = base->data; + + xfrm_input_resume(skb, esp_input_done2(skb, err)); +} + +/* + * Note: detecting truncated vs. non-truncated authentication data is very + * expensive, so we only support truncated data, which is the recommended + * and common case. + */ +static int esp_input(struct xfrm_state *x, struct sk_buff *skb) +{ + struct ip_esp_hdr *esph; + struct esp_data *esp = x->data; + struct crypto_aead *aead = esp->aead; + struct aead_request *req; + struct sk_buff *trailer; + int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead); + int nfrags; + void *tmp; + u8 *iv; + struct scatterlist *sg; + struct scatterlist *asg; + int err = -EINVAL; + + if (!pskb_may_pull(skb, sizeof(*esph))) + goto out; + + if (elen <= 0) + goto out; + + if ((err = skb_cow_data(skb, 0, &trailer)) < 0) + goto out; + nfrags = err; + + err = -ENOMEM; + tmp = esp_alloc_tmp(aead, nfrags + 1); + if (!tmp) + goto out; + + ESP_SKB_CB(skb)->tmp = tmp; + iv = esp_tmp_iv(aead, tmp); + req = esp_tmp_req(aead, iv); + asg = esp_req_sg(aead, req); + sg = asg + 1; + + skb->ip_summed = CHECKSUM_NONE; + + esph = (struct ip_esp_hdr *)skb->data; + + /* Get ivec. This can be wrong, check against another impls. */ + iv = esph->enc_data; + + sg_init_table(sg, nfrags); + skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen); + sg_init_one(asg, esph, sizeof(*esph)); + + aead_request_set_callback(req, 0, esp_input_done, skb); + aead_request_set_crypt(req, sg, sg, elen, iv); + aead_request_set_assoc(req, asg, sizeof(*esph)); + + err = crypto_aead_decrypt(req); + if (err == -EINPROGRESS) + goto out; + + err = esp_input_done2(skb, err); out: return err; @@ -291,11 +384,11 @@ out: static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) { struct esp_data *esp = x->data; - u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); - u32 align = max_t(u32, blksize, esp->conf.padlen); + u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4); + u32 align = max_t(u32, blksize, esp->padlen); u32 rem; - mtu -= x->props.header_len + esp->auth.icv_trunc_len; + mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); rem = mtu & (align - 1); mtu &= ~(align - 1); @@ -342,80 +435,143 @@ static void esp_destroy(struct xfrm_state *x) if (!esp) return; - crypto_free_blkcipher(esp->conf.tfm); - esp->conf.tfm = NULL; - kfree(esp->conf.ivec); - esp->conf.ivec = NULL; - crypto_free_hash(esp->auth.tfm); - esp->auth.tfm = NULL; - kfree(esp->auth.work_icv); - esp->auth.work_icv = NULL; + crypto_free_aead(esp->aead); kfree(esp); } -static int esp_init_state(struct xfrm_state *x) +static int esp_init_aead(struct xfrm_state *x) { - struct esp_data *esp = NULL; - struct crypto_blkcipher *tfm; - u32 align; + struct esp_data *esp = x->data; + struct crypto_aead *aead; + int err; + + aead = crypto_alloc_aead(x->aead->alg_name, 0, 0); + err = PTR_ERR(aead); + if (IS_ERR(aead)) + goto error; + + esp->aead = aead; + + err = crypto_aead_setkey(aead, x->aead->alg_key, + (x->aead->alg_key_len + 7) / 8); + if (err) + goto error; + + err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8); + if (err) + goto error; + +error: + return err; +} +static int esp_init_authenc(struct xfrm_state *x) +{ + struct esp_data *esp = x->data; + struct crypto_aead *aead; + struct crypto_authenc_key_param *param; + struct rtattr *rta; + char *key; + char *p; + char authenc_name[CRYPTO_MAX_ALG_NAME]; + unsigned int keylen; + int err; + + err = -EINVAL; if (x->ealg == NULL) goto error; - esp = kzalloc(sizeof(*esp), GFP_KERNEL); - if (esp == NULL) - return -ENOMEM; + err = -ENAMETOOLONG; + if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", + x->aalg ? x->aalg->alg_name : "digest_null", + x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) + goto error; + + aead = crypto_alloc_aead(authenc_name, 0, 0); + err = PTR_ERR(aead); + if (IS_ERR(aead)) + goto error; + + esp->aead = aead; + + keylen = (x->aalg ? (x->aalg->alg_key_len + 7) / 8 : 0) + + (x->ealg->alg_key_len + 7) / 8 + RTA_SPACE(sizeof(*param)); + err = -ENOMEM; + key = kmalloc(keylen, GFP_KERNEL); + if (!key) + goto error; + + p = key; + rta = (void *)p; + rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM; + rta->rta_len = RTA_LENGTH(sizeof(*param)); + param = RTA_DATA(rta); + p += RTA_SPACE(sizeof(*param)); if (x->aalg) { struct xfrm_algo_desc *aalg_desc; - struct crypto_hash *hash; - hash = crypto_alloc_hash(x->aalg->alg_name, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(hash)) - goto error; - - esp->auth.tfm = hash; - if (crypto_hash_setkey(hash, x->aalg->alg_key, - (x->aalg->alg_key_len + 7) / 8)) - goto error; + memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8); + p += (x->aalg->alg_key_len + 7) / 8; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); + err = -EINVAL; if (aalg_desc->uinfo.auth.icv_fullbits/8 != - crypto_hash_digestsize(hash)) { + crypto_aead_authsize(aead)) { NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", x->aalg->alg_name, - crypto_hash_digestsize(hash), + crypto_aead_authsize(aead), aalg_desc->uinfo.auth.icv_fullbits/8); - goto error; + goto free_key; } - esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; - esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; - - esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL); - if (!esp->auth.work_icv) - goto error; + err = crypto_aead_setauthsize( + aead, aalg_desc->uinfo.auth.icv_truncbits / 8); + if (err) + goto free_key; } - tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - goto error; - esp->conf.tfm = tfm; - esp->conf.ivlen = crypto_blkcipher_ivsize(tfm); - esp->conf.padlen = 0; - if (esp->conf.ivlen) { - esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); - if (unlikely(esp->conf.ivec == NULL)) - goto error; - esp->conf.ivinitted = 0; - } - if (crypto_blkcipher_setkey(tfm, x->ealg->alg_key, - (x->ealg->alg_key_len + 7) / 8)) + param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); + memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8); + + err = crypto_aead_setkey(aead, key, keylen); + +free_key: + kfree(key); + +error: + return err; +} + +static int esp_init_state(struct xfrm_state *x) +{ + struct esp_data *esp; + struct crypto_aead *aead; + u32 align; + int err; + + esp = kzalloc(sizeof(*esp), GFP_KERNEL); + if (esp == NULL) + return -ENOMEM; + + x->data = esp; + + if (x->aead) + err = esp_init_aead(x); + else + err = esp_init_authenc(x); + + if (err) goto error; - x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; + + aead = esp->aead; + + esp->padlen = 0; + + x->props.header_len = sizeof(struct ip_esp_hdr) + + crypto_aead_ivsize(aead); if (x->props.mode == XFRM_MODE_TUNNEL) x->props.header_len += sizeof(struct iphdr); else if (x->props.mode == XFRM_MODE_BEET) @@ -434,21 +590,17 @@ static int esp_init_state(struct xfrm_state *x) break; } } - x->data = esp; - align = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); - if (esp->conf.padlen) - align = max_t(u32, align, esp->conf.padlen); - x->props.trailer_len = align + 1 + esp->auth.icv_trunc_len; - return 0; + + align = ALIGN(crypto_aead_blocksize(aead), 4); + if (esp->padlen) + align = max_t(u32, align, esp->padlen); + x->props.trailer_len = align + 1 + crypto_aead_authsize(esp->aead); error: - x->data = esp; - esp_destroy(x); - x->data = NULL; - return -EINVAL; + return err; } -static struct xfrm_type esp_type = +static const struct xfrm_type esp_type = { .description = "ESP4", .owner = THIS_MODULE, diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index d282618..86ff271 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -808,7 +808,7 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) First of all, we scan fib_info list searching for stray nexthop entries, then ignite fib_flush. */ - if (fib_sync_down(ifa->ifa_local, NULL, 0)) + if (fib_sync_down_addr(dev->nd_net, ifa->ifa_local)) fib_flush(dev->nd_net); } } @@ -898,7 +898,7 @@ static void nl_fib_lookup_exit(struct net *net) static void fib_disable_ip(struct net_device *dev, int force) { - if (fib_sync_down(0, dev, force)) + if (fib_sync_down_dev(dev, force)) fib_flush(dev->nd_net); rt_cache_flush(0); arp_ifdown(dev); @@ -975,6 +975,7 @@ static struct notifier_block fib_netdev_notifier = { static int __net_init ip_fib_net_init(struct net *net) { + int err; unsigned int i; net->ipv4.fib_table_hash = kzalloc( @@ -985,7 +986,14 @@ static int __net_init ip_fib_net_init(struct net *net) for (i = 0; i < FIB_TABLE_HASHSZ; i++) INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]); - return fib4_rules_init(net); + err = fib4_rules_init(net); + if (err < 0) + goto fail; + return 0; + +fail: + kfree(net->ipv4.fib_table_hash); + return err; } static void __net_exit ip_fib_net_exit(struct net *net) diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index a15b2f1..76b9c68 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -424,19 +424,43 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) if (fa && fa->fa_tos == tos && fa->fa_info->fib_priority == fi->fib_priority) { - struct fib_alias *fa_orig; + struct fib_alias *fa_first, *fa_match; err = -EEXIST; if (cfg->fc_nlflags & NLM_F_EXCL) goto out; + /* We have 2 goals: + * 1. Find exact match for type, scope, fib_info to avoid + * duplicate routes + * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it + */ + fa_match = NULL; + fa_first = fa; + fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list); + list_for_each_entry_continue(fa, &f->fn_alias, fa_list) { + if (fa->fa_tos != tos) + break; + if (fa->fa_info->fib_priority != fi->fib_priority) + break; + if (fa->fa_type == cfg->fc_type && + fa->fa_scope == cfg->fc_scope && + fa->fa_info == fi) { + fa_match = fa; + break; + } + } + if (cfg->fc_nlflags & NLM_F_REPLACE) { struct fib_info *fi_drop; u8 state; - if (fi->fib_treeref > 1) + fa = fa_first; + if (fa_match) { + if (fa == fa_match) + err = 0; goto out; - + } write_lock_bh(&fib_hash_lock); fi_drop = fa->fa_info; fa->fa_info = fi; @@ -459,20 +483,11 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) * uses the same scope, type, and nexthop * information. */ - fa_orig = fa; - fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list); - list_for_each_entry_continue(fa, &f->fn_alias, fa_list) { - if (fa->fa_tos != tos) - break; - if (fa->fa_info->fib_priority != fi->fib_priority) - break; - if (fa->fa_type == cfg->fc_type && - fa->fa_scope == cfg->fc_scope && - fa->fa_info == fi) - goto out; - } + if (fa_match) + goto out; + if (!(cfg->fc_nlflags & NLM_F_APPEND)) - fa = fa_orig; + fa = fa_first; } err = -ENOENT; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index c791286..a13c847 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -229,6 +229,8 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) head = &fib_info_hash[hash]; hlist_for_each_entry(fi, node, head, fib_hash) { + if (fi->fib_net != nfi->fib_net) + continue; if (fi->fib_nhs != nfi->fib_nhs) continue; if (nfi->fib_protocol == fi->fib_protocol && @@ -687,6 +689,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) struct fib_info *fi = NULL; struct fib_info *ofi; int nhs = 1; + struct net *net = cfg->fc_nlinfo.nl_net; /* Fast check to catch the most weird cases */ if (fib_props[cfg->fc_type].scope > cfg->fc_scope) @@ -727,6 +730,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) goto failure; fib_info_cnt++; + fi->fib_net = net; fi->fib_protocol = cfg->fc_protocol; fi->fib_flags = cfg->fc_flags; fi->fib_priority = cfg->fc_priority; @@ -798,8 +802,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) if (nhs != 1 || nh->nh_gw) goto err_inval; nh->nh_scope = RT_SCOPE_NOWHERE; - nh->nh_dev = dev_get_by_index(cfg->fc_nlinfo.nl_net, - fi->fib_nh->nh_oif); + nh->nh_dev = dev_get_by_index(net, fi->fib_nh->nh_oif); err = -ENODEV; if (nh->nh_dev == NULL) goto failure; @@ -813,8 +816,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) if (fi->fib_prefsrc) { if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || fi->fib_prefsrc != cfg->fc_dst) - if (inet_addr_type(cfg->fc_nlinfo.nl_net, - fi->fib_prefsrc) != RTN_LOCAL) + if (inet_addr_type(net, fi->fib_prefsrc) != RTN_LOCAL) goto err_inval; } @@ -1031,70 +1033,74 @@ nla_put_failure: referring to it. - device went down -> we must shutdown all nexthops going via it. */ - -int fib_sync_down(__be32 local, struct net_device *dev, int force) +int fib_sync_down_addr(struct net *net, __be32 local) { int ret = 0; - int scope = RT_SCOPE_NOWHERE; - - if (force) - scope = -1; + unsigned int hash = fib_laddr_hashfn(local); + struct hlist_head *head = &fib_info_laddrhash[hash]; + struct hlist_node *node; + struct fib_info *fi; - if (local && fib_info_laddrhash) { - unsigned int hash = fib_laddr_hashfn(local); - struct hlist_head *head = &fib_info_laddrhash[hash]; - struct hlist_node *node; - struct fib_info *fi; + if (fib_info_laddrhash == NULL || local == 0) + return 0; - hlist_for_each_entry(fi, node, head, fib_lhash) { - if (fi->fib_prefsrc == local) { - fi->fib_flags |= RTNH_F_DEAD; - ret++; - } + hlist_for_each_entry(fi, node, head, fib_lhash) { + if (fi->fib_net != net) + continue; + if (fi->fib_prefsrc == local) { + fi->fib_flags |= RTNH_F_DEAD; + ret++; } } + return ret; +} - if (dev) { - struct fib_info *prev_fi = NULL; - unsigned int hash = fib_devindex_hashfn(dev->ifindex); - struct hlist_head *head = &fib_info_devhash[hash]; - struct hlist_node *node; - struct fib_nh *nh; +int fib_sync_down_dev(struct net_device *dev, int force) +{ + int ret = 0; + int scope = RT_SCOPE_NOWHERE; + struct fib_info *prev_fi = NULL; + unsigned int hash = fib_devindex_hashfn(dev->ifindex); + struct hlist_head *head = &fib_info_devhash[hash]; + struct hlist_node *node; + struct fib_nh *nh; - hlist_for_each_entry(nh, node, head, nh_hash) { - struct fib_info *fi = nh->nh_parent; - int dead; + if (force) + scope = -1; - BUG_ON(!fi->fib_nhs); - if (nh->nh_dev != dev || fi == prev_fi) - continue; - prev_fi = fi; - dead = 0; - change_nexthops(fi) { - if (nh->nh_flags&RTNH_F_DEAD) - dead++; - else if (nh->nh_dev == dev && - nh->nh_scope != scope) { - nh->nh_flags |= RTNH_F_DEAD; + hlist_for_each_entry(nh, node, head, nh_hash) { + struct fib_info *fi = nh->nh_parent; + int dead; + + BUG_ON(!fi->fib_nhs); + if (nh->nh_dev != dev || fi == prev_fi) + continue; + prev_fi = fi; + dead = 0; + change_nexthops(fi) { + if (nh->nh_flags&RTNH_F_DEAD) + dead++; + else if (nh->nh_dev == dev && + nh->nh_scope != scope) { + nh->nh_flags |= RTNH_F_DEAD; #ifdef CONFIG_IP_ROUTE_MULTIPATH - spin_lock_bh(&fib_multipath_lock); - fi->fib_power -= nh->nh_power; - nh->nh_power = 0; - spin_unlock_bh(&fib_multipath_lock); + spin_lock_bh(&fib_multipath_lock); + fi->fib_power -= nh->nh_power; + nh->nh_power = 0; + spin_unlock_bh(&fib_multipath_lock); #endif - dead++; - } + dead++; + } #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (force > 1 && nh->nh_dev == dev) { - dead = fi->fib_nhs; - break; - } -#endif - } endfor_nexthops(fi) - if (dead == fi->fib_nhs) { - fi->fib_flags |= RTNH_F_DEAD; - ret++; + if (force > 1 && nh->nh_dev == dev) { + dead = fi->fib_nhs; + break; } +#endif + } endfor_nexthops(fi) + if (dead == fi->fib_nhs) { + fi->fib_flags |= RTNH_F_DEAD; + ret++; } } diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index f2f4703..35851c9 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1205,20 +1205,45 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) * and we need to allocate a new one of those as well. */ - if (fa && fa->fa_info->fib_priority == fi->fib_priority) { - struct fib_alias *fa_orig; + if (fa && fa->fa_tos == tos && + fa->fa_info->fib_priority == fi->fib_priority) { + struct fib_alias *fa_first, *fa_match; err = -EEXIST; if (cfg->fc_nlflags & NLM_F_EXCL) goto out; + /* We have 2 goals: + * 1. Find exact match for type, scope, fib_info to avoid + * duplicate routes + * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it + */ + fa_match = NULL; + fa_first = fa; + fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list); + list_for_each_entry_continue(fa, fa_head, fa_list) { + if (fa->fa_tos != tos) + break; + if (fa->fa_info->fib_priority != fi->fib_priority) + break; + if (fa->fa_type == cfg->fc_type && + fa->fa_scope == cfg->fc_scope && + fa->fa_info == fi) { + fa_match = fa; + break; + } + } + if (cfg->fc_nlflags & NLM_F_REPLACE) { struct fib_info *fi_drop; u8 state; - if (fi->fib_treeref > 1) + fa = fa_first; + if (fa_match) { + if (fa == fa_match) + err = 0; goto out; - + } err = -ENOBUFS; new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); if (new_fa == NULL) @@ -1230,7 +1255,7 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) new_fa->fa_type = cfg->fc_type; new_fa->fa_scope = cfg->fc_scope; state = fa->fa_state; - new_fa->fa_state &= ~FA_S_ACCESSED; + new_fa->fa_state = state & ~FA_S_ACCESSED; list_replace_rcu(&fa->fa_list, &new_fa->fa_list); alias_free_mem_rcu(fa); @@ -1247,20 +1272,11 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) * uses the same scope, type, and nexthop * information. */ - fa_orig = fa; - list_for_each_entry(fa, fa_orig->fa_list.prev, fa_list) { - if (fa->fa_tos != tos) - break; - if (fa->fa_info->fib_priority != fi->fib_priority) - break; - if (fa->fa_type == cfg->fc_type && - fa->fa_scope == cfg->fc_scope && - fa->fa_info == fi) - goto out; - } + if (fa_match) + goto out; if (!(cfg->fc_nlflags & NLM_F_APPEND)) - fa = fa_orig; + fa = fa_first; } err = -ENOENT; if (!(cfg->fc_nlflags & NLM_F_CREATE)) @@ -1600,9 +1616,8 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t); fa_to_delete = NULL; - fa_head = fa->fa_list.prev; - - list_for_each_entry(fa, fa_head, fa_list) { + fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list); + list_for_each_entry_continue(fa, fa_head, fa_list) { struct fib_info *fi = fa->fa_info; if (fa->fa_tos != tos) @@ -1743,6 +1758,19 @@ static struct leaf *trie_nextleaf(struct leaf *l) return leaf_walk_rcu(p, c); } +static struct leaf *trie_leafindex(struct trie *t, int index) +{ + struct leaf *l = trie_firstleaf(t); + + while (index-- > 0) { + l = trie_nextleaf(l); + if (!l) + break; + } + return l; +} + + /* * Caller must hold RTNL. */ @@ -1848,7 +1876,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fib_alias *fa; __be32 xkey = htonl(key); - s_i = cb->args[4]; + s_i = cb->args[5]; i = 0; /* rcu_read_lock is hold by caller */ @@ -1869,12 +1897,12 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, plen, fa->fa_tos, fa->fa_info, NLM_F_MULTI) < 0) { - cb->args[4] = i; + cb->args[5] = i; return -1; } i++; } - cb->args[4] = i; + cb->args[5] = i; return skb->len; } @@ -1885,7 +1913,7 @@ static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb, struct hlist_node *node; int i, s_i; - s_i = cb->args[3]; + s_i = cb->args[4]; i = 0; /* rcu_read_lock is hold by caller */ @@ -1896,19 +1924,19 @@ static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb, } if (i > s_i) - cb->args[4] = 0; + cb->args[5] = 0; if (list_empty(&li->falh)) continue; if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) { - cb->args[3] = i; + cb->args[4] = i; return -1; } i++; } - cb->args[3] = i; + cb->args[4] = i; return skb->len; } @@ -1918,35 +1946,37 @@ static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct leaf *l; struct trie *t = (struct trie *) tb->tb_data; t_key key = cb->args[2]; + int count = cb->args[3]; rcu_read_lock(); /* Dump starting at last key. * Note: 0.0.0.0/0 (ie default) is first key. */ - if (!key) + if (count == 0) l = trie_firstleaf(t); else { + /* Normally, continue from last key, but if that is missing + * fallback to using slow rescan + */ l = fib_find_node(t, key); - if (!l) { - /* The table changed during the dump, rather than - * giving partial data, just make application retry. - */ - rcu_read_unlock(); - return -EBUSY; - } + if (!l) + l = trie_leafindex(t, count); } while (l) { cb->args[2] = l->key; if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) { + cb->args[3] = count; rcu_read_unlock(); return -1; } + ++count; l = trie_nextleaf(l); - memset(&cb->args[3], 0, - sizeof(cb->args) - 3*sizeof(cb->args[0])); + memset(&cb->args[4], 0, + sizeof(cb->args) - 4*sizeof(cb->args[0])); } + cb->args[3] = count; rcu_read_unlock(); return skb->len; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 7801cce..de5a41d 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -87,6 +87,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, struct hlist_node *node; struct inet_bind_bucket *tb; int ret; + struct net *net = sk->sk_net; local_bh_disable(); if (!snum) { @@ -100,7 +101,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; spin_lock(&head->lock); inet_bind_bucket_for_each(tb, node, &head->chain) - if (tb->port == rover) + if (tb->ib_net == net && tb->port == rover) goto next; break; next: @@ -127,7 +128,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, head = &hashinfo->bhash[inet_bhashfn(snum, hashinfo->bhash_size)]; spin_lock(&head->lock); inet_bind_bucket_for_each(tb, node, &head->chain) - if (tb->port == snum) + if (tb->ib_net == net && tb->port == snum) goto tb_found; } tb = NULL; @@ -147,7 +148,8 @@ tb_found: } tb_not_found: ret = 1; - if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, snum)) == NULL) + if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, + net, head, snum)) == NULL) goto fail_unlock; if (hlist_empty(&tb->owners)) { if (sk->sk_reuse && sk->sk_state != TCP_LISTEN) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 605ed2c..da97695 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -259,20 +259,22 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, const struct inet_diag_handler *handler; handler = inet_diag_lock_handler(nlh->nlmsg_type); - if (!handler) - return -ENOENT; + if (IS_ERR(handler)) { + err = PTR_ERR(handler); + goto unlock; + } hashinfo = handler->idiag_hashinfo; err = -EINVAL; if (req->idiag_family == AF_INET) { - sk = inet_lookup(hashinfo, req->id.idiag_dst[0], + sk = inet_lookup(&init_net, hashinfo, req->id.idiag_dst[0], req->id.idiag_dport, req->id.idiag_src[0], req->id.idiag_sport, req->id.idiag_if); } #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) else if (req->idiag_family == AF_INET6) { - sk = inet6_lookup(hashinfo, + sk = inet6_lookup(&init_net, hashinfo, (struct in6_addr *)req->id.idiag_dst, req->id.idiag_dport, (struct in6_addr *)req->id.idiag_src, @@ -708,8 +710,8 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) struct inet_hashinfo *hashinfo; handler = inet_diag_lock_handler(cb->nlh->nlmsg_type); - if (!handler) - goto no_handler; + if (IS_ERR(handler)) + goto unlock; hashinfo = handler->idiag_hashinfo; @@ -838,7 +840,6 @@ done: cb->args[2] = num; unlock: inet_diag_unlock_handler(handler); -no_handler: return skb->len; } diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 619c63c..48d4500 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -28,12 +28,14 @@ * The bindhash mutex for snum's hash chain must be held here. */ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep, + struct net *net, struct inet_bind_hashbucket *head, const unsigned short snum) { struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC); if (tb != NULL) { + tb->ib_net = net; tb->port = snum; tb->fastreuse = 0; INIT_HLIST_HEAD(&tb->owners); @@ -125,7 +127,8 @@ EXPORT_SYMBOL(inet_listen_wlock); * remote address for the connection. So always assume those are both * wildcarded during the search since they can never be otherwise. */ -static struct sock *inet_lookup_listener_slow(const struct hlist_head *head, +static struct sock *inet_lookup_listener_slow(struct net *net, + const struct hlist_head *head, const __be32 daddr, const unsigned short hnum, const int dif) @@ -137,7 +140,8 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head, sk_for_each(sk, node, head) { const struct inet_sock *inet = inet_sk(sk); - if (inet->num == hnum && !ipv6_only_sock(sk)) { + if (sk->sk_net == net && inet->num == hnum && + !ipv6_only_sock(sk)) { const __be32 rcv_saddr = inet->rcv_saddr; int score = sk->sk_family == PF_INET ? 1 : 0; @@ -163,7 +167,8 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head, } /* Optimize the common listener case. */ -struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo, +struct sock *__inet_lookup_listener(struct net *net, + struct inet_hashinfo *hashinfo, const __be32 daddr, const unsigned short hnum, const int dif) { @@ -178,9 +183,9 @@ struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo, if (inet->num == hnum && !sk->sk_node.next && (!inet->rcv_saddr || inet->rcv_saddr == daddr) && (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && - !sk->sk_bound_dev_if) + !sk->sk_bound_dev_if && sk->sk_net == net) goto sherry_cache; - sk = inet_lookup_listener_slow(head, daddr, hnum, dif); + sk = inet_lookup_listener_slow(net, head, daddr, hnum, dif); } if (sk) { sherry_cache: @@ -191,7 +196,8 @@ sherry_cache: } EXPORT_SYMBOL_GPL(__inet_lookup_listener); -struct sock * __inet_lookup_established(struct inet_hashinfo *hashinfo, +struct sock * __inet_lookup_established(struct net *net, + struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const u16 hnum, const int dif) @@ -210,13 +216,15 @@ struct sock * __inet_lookup_established(struct inet_hashinfo *hashinfo, prefetch(head->chain.first); read_lock(lock); sk_for_each(sk, node, &head->chain) { - if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif)) + if (INET_MATCH(sk, net, hash, acookie, + saddr, daddr, ports, dif)) goto hit; /* You sunk my battleship! */ } /* Must check for a TIME_WAIT'er before going to listener hash. */ sk_for_each(sk, node, &head->twchain) { - if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif)) + if (INET_TW_MATCH(sk, net, hash, acookie, + saddr, daddr, ports, dif)) goto hit; } sk = NULL; @@ -247,6 +255,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; + struct net *net = sk->sk_net; prefetch(head->chain.first); write_lock(lock); @@ -255,7 +264,8 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, sk_for_each(sk2, node, &head->twchain) { tw = inet_twsk(sk2); - if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) { + if (INET_TW_MATCH(sk2, net, hash, acookie, + saddr, daddr, ports, dif)) { if (twsk_unique(sk, sk2, twp)) goto unique; else @@ -266,7 +276,8 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, /* And established part... */ sk_for_each(sk2, node, &head->chain) { - if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) + if (INET_MATCH(sk2, net, hash, acookie, + saddr, daddr, ports, dif)) goto not_unique; } @@ -348,17 +359,18 @@ void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk) } EXPORT_SYMBOL_GPL(__inet_hash); -/* - * Bind a port for a connect operation and hash it. - */ -int inet_hash_connect(struct inet_timewait_death_row *death_row, - struct sock *sk) +int __inet_hash_connect(struct inet_timewait_death_row *death_row, + struct sock *sk, + int (*check_established)(struct inet_timewait_death_row *, + struct sock *, __u16, struct inet_timewait_sock **), + void (*hash)(struct inet_hashinfo *, struct sock *)) { struct inet_hashinfo *hinfo = death_row->hashinfo; const unsigned short snum = inet_sk(sk)->num; struct inet_bind_hashbucket *head; struct inet_bind_bucket *tb; int ret; + struct net *net = sk->sk_net; if (!snum) { int i, remaining, low, high, port; @@ -381,19 +393,19 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row, * unique enough. */ inet_bind_bucket_for_each(tb, node, &head->chain) { - if (tb->port == port) { + if (tb->ib_net == net && tb->port == port) { BUG_TRAP(!hlist_empty(&tb->owners)); if (tb->fastreuse >= 0) goto next_port; - if (!__inet_check_established(death_row, - sk, port, - &tw)) + if (!check_established(death_row, sk, + port, &tw)) goto ok; goto next_port; } } - tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, port); + tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, + net, head, port); if (!tb) { spin_unlock(&head->lock); break; @@ -415,7 +427,7 @@ ok: inet_bind_hash(sk, tb, port); if (sk_unhashed(sk)) { inet_sk(sk)->sport = htons(port); - __inet_hash_nolisten(hinfo, sk); + hash(hinfo, sk); } spin_unlock(&head->lock); @@ -432,17 +444,28 @@ ok: tb = inet_csk(sk)->icsk_bind_hash; spin_lock_bh(&head->lock); if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { - __inet_hash_nolisten(hinfo, sk); + hash(hinfo, sk); spin_unlock_bh(&head->lock); return 0; } else { spin_unlock(&head->lock); /* No definite answer... Walk to established hash table */ - ret = __inet_check_established(death_row, sk, snum, NULL); + ret = check_established(death_row, sk, snum, NULL); out: local_bh_enable(); return ret; } } +EXPORT_SYMBOL_GPL(__inet_hash_connect); + +/* + * Bind a port for a connect operation and hash it. + */ +int inet_hash_connect(struct inet_timewait_death_row *death_row, + struct sock *sk) +{ + return __inet_hash_connect(death_row, sk, + __inet_check_established, __inet_hash_nolisten); +} EXPORT_SYMBOL_GPL(inet_hash_connect); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 18070ca..341779e68 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -168,6 +168,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, } skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; /* Send it out. */ return ip_local_out(skb); @@ -385,6 +386,7 @@ packet_routed: (skb_shinfo(skb)->gso_segs ?: 1) - 1); skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; return ip_local_out(skb); @@ -476,6 +478,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) if (skb_shinfo(skb)->frag_list) { struct sk_buff *frag; int first_len = skb_pagelen(skb); + int truesizes = 0; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -499,7 +502,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) sock_hold(skb->sk); frag->sk = skb->sk; frag->destructor = sock_wfree; - skb->truesize -= frag->truesize; + truesizes += frag->truesize; } } @@ -510,6 +513,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) frag = skb_shinfo(skb)->frag_list; skb_shinfo(skb)->frag_list = NULL; skb->data_len = first_len - skb_headlen(skb); + skb->truesize -= truesizes; skb->len = first_len; iph->tot_len = htons(first_len); iph->frag_off = htons(IP_MF); @@ -1284,6 +1288,7 @@ int ip_push_pending_frames(struct sock *sk) iph->daddr = rt->rt_dst; skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; skb->dst = dst_clone(&rt->u.dst); if (iph->protocol == IPPROTO_ICMP) diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index f4af99a..ae1f45f 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -74,6 +74,7 @@ out: static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) { + int nexthdr; int err = -ENOMEM; struct ip_comp_hdr *ipch; @@ -84,13 +85,15 @@ static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) /* Remove ipcomp header and decompress original payload */ ipch = (void *)skb->data; + nexthdr = ipch->nexthdr; + skb->transport_header = skb->network_header + sizeof(*ipch); __skb_pull(skb, sizeof(*ipch)); err = ipcomp_decompress(x, skb); if (err) goto out; - err = ipch->nexthdr; + err = nexthdr; out: return err; @@ -434,7 +437,7 @@ error: goto out; } -static struct xfrm_type ipcomp_type = { +static const struct xfrm_type ipcomp_type = { .description = "IPCOMP4", .owner = THIS_MODULE, .proto = IPPROTO_COMP, diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index b4a810c..a7591ce 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -22,6 +22,7 @@ #include <linux/mutex.h> #include <linux/err.h> #include <net/compat.h> +#include <net/sock.h> #include <asm/uaccess.h> #include <linux/netfilter/x_tables.h> @@ -850,7 +851,7 @@ static int compat_table_info(const struct xt_table_info *info, } #endif -static int get_info(void __user *user, int *len, int compat) +static int get_info(struct net *net, void __user *user, int *len, int compat) { char name[ARPT_TABLE_MAXNAMELEN]; struct arpt_table *t; @@ -870,7 +871,7 @@ static int get_info(void __user *user, int *len, int compat) if (compat) xt_compat_lock(NF_ARP); #endif - t = try_then_request_module(xt_find_table_lock(NF_ARP, name), + t = try_then_request_module(xt_find_table_lock(net, NF_ARP, name), "arptable_%s", name); if (t && !IS_ERR(t)) { struct arpt_getinfo info; @@ -908,7 +909,8 @@ static int get_info(void __user *user, int *len, int compat) return ret; } -static int get_entries(struct arpt_get_entries __user *uptr, int *len) +static int get_entries(struct net *net, struct arpt_get_entries __user *uptr, + int *len) { int ret; struct arpt_get_entries get; @@ -926,7 +928,7 @@ static int get_entries(struct arpt_get_entries __user *uptr, int *len) return -EINVAL; } - t = xt_find_table_lock(NF_ARP, get.name); + t = xt_find_table_lock(net, NF_ARP, get.name); if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", @@ -947,7 +949,8 @@ static int get_entries(struct arpt_get_entries __user *uptr, int *len) return ret; } -static int __do_replace(const char *name, unsigned int valid_hooks, +static int __do_replace(struct net *net, const char *name, + unsigned int valid_hooks, struct xt_table_info *newinfo, unsigned int num_counters, void __user *counters_ptr) @@ -966,7 +969,7 @@ static int __do_replace(const char *name, unsigned int valid_hooks, goto out; } - t = try_then_request_module(xt_find_table_lock(NF_ARP, name), + t = try_then_request_module(xt_find_table_lock(net, NF_ARP, name), "arptable_%s", name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1019,7 +1022,7 @@ static int __do_replace(const char *name, unsigned int valid_hooks, return ret; } -static int do_replace(void __user *user, unsigned int len) +static int do_replace(struct net *net, void __user *user, unsigned int len) { int ret; struct arpt_replace tmp; @@ -1053,7 +1056,7 @@ static int do_replace(void __user *user, unsigned int len) duprintf("arp_tables: Translated table\n"); - ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo, + ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, tmp.num_counters, tmp.counters); if (ret) goto free_newinfo_untrans; @@ -1080,7 +1083,8 @@ static inline int add_counter_to_entry(struct arpt_entry *e, return 0; } -static int do_add_counters(void __user *user, unsigned int len, int compat) +static int do_add_counters(struct net *net, void __user *user, unsigned int len, + int compat) { unsigned int i; struct xt_counters_info tmp; @@ -1132,7 +1136,7 @@ static int do_add_counters(void __user *user, unsigned int len, int compat) goto free; } - t = xt_find_table_lock(NF_ARP, name); + t = xt_find_table_lock(net, NF_ARP, name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1435,7 +1439,8 @@ struct compat_arpt_replace { struct compat_arpt_entry entries[0]; }; -static int compat_do_replace(void __user *user, unsigned int len) +static int compat_do_replace(struct net *net, void __user *user, + unsigned int len) { int ret; struct compat_arpt_replace tmp; @@ -1471,7 +1476,7 @@ static int compat_do_replace(void __user *user, unsigned int len) duprintf("compat_do_replace: Translated table\n"); - ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo, + ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, tmp.num_counters, compat_ptr(tmp.counters)); if (ret) goto free_newinfo_untrans; @@ -1494,11 +1499,11 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, switch (cmd) { case ARPT_SO_SET_REPLACE: - ret = compat_do_replace(user, len); + ret = compat_do_replace(sk->sk_net, user, len); break; case ARPT_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 1); + ret = do_add_counters(sk->sk_net, user, len, 1); break; default: @@ -1584,7 +1589,8 @@ struct compat_arpt_get_entries { struct compat_arpt_entry entrytable[0]; }; -static int compat_get_entries(struct compat_arpt_get_entries __user *uptr, +static int compat_get_entries(struct net *net, + struct compat_arpt_get_entries __user *uptr, int *len) { int ret; @@ -1604,7 +1610,7 @@ static int compat_get_entries(struct compat_arpt_get_entries __user *uptr, } xt_compat_lock(NF_ARP); - t = xt_find_table_lock(NF_ARP, get.name); + t = xt_find_table_lock(net, NF_ARP, get.name); if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; struct xt_table_info info; @@ -1641,10 +1647,10 @@ static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, switch (cmd) { case ARPT_SO_GET_INFO: - ret = get_info(user, len, 1); + ret = get_info(sk->sk_net, user, len, 1); break; case ARPT_SO_GET_ENTRIES: - ret = compat_get_entries(user, len); + ret = compat_get_entries(sk->sk_net, user, len); break; default: ret = do_arpt_get_ctl(sk, cmd, user, len); @@ -1662,11 +1668,11 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned switch (cmd) { case ARPT_SO_SET_REPLACE: - ret = do_replace(user, len); + ret = do_replace(sk->sk_net, user, len); break; case ARPT_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 0); + ret = do_add_counters(sk->sk_net, user, len, 0); break; default: @@ -1686,11 +1692,11 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len switch (cmd) { case ARPT_SO_GET_INFO: - ret = get_info(user, len, 0); + ret = get_info(sk->sk_net, user, len, 0); break; case ARPT_SO_GET_ENTRIES: - ret = get_entries(user, len); + ret = get_entries(sk->sk_net, user, len); break; case ARPT_SO_GET_REVISION_TARGET: { @@ -1719,19 +1725,21 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len return ret; } -int arpt_register_table(struct arpt_table *table, - const struct arpt_replace *repl) +struct arpt_table *arpt_register_table(struct net *net, + struct arpt_table *table, + const struct arpt_replace *repl) { int ret; struct xt_table_info *newinfo; struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; + struct xt_table *new_table; newinfo = xt_alloc_table_info(repl->size); if (!newinfo) { ret = -ENOMEM; - return ret; + goto out; } /* choose the copy on our node/cpu */ @@ -1745,24 +1753,27 @@ int arpt_register_table(struct arpt_table *table, repl->underflow); duprintf("arpt_register_table: translate table gives %d\n", ret); - if (ret != 0) { - xt_free_table_info(newinfo); - return ret; - } + if (ret != 0) + goto out_free; - ret = xt_register_table(table, &bootstrap, newinfo); - if (ret != 0) { - xt_free_table_info(newinfo); - return ret; + new_table = xt_register_table(net, table, &bootstrap, newinfo); + if (IS_ERR(new_table)) { + ret = PTR_ERR(new_table); + goto out_free; } + return new_table; - return 0; +out_free: + xt_free_table_info(newinfo); +out: + return ERR_PTR(ret); } void arpt_unregister_table(struct arpt_table *table) { struct xt_table_info *private; void *loc_cpu_entry; + struct module *table_owner = table->me; private = xt_unregister_table(table); @@ -1770,6 +1781,8 @@ void arpt_unregister_table(struct arpt_table *table) loc_cpu_entry = private->entries[raw_smp_processor_id()]; ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + if (private->number > private->initial_entries) + module_put(table_owner); xt_free_table_info(private); } @@ -1809,11 +1822,26 @@ static struct nf_sockopt_ops arpt_sockopts = { .owner = THIS_MODULE, }; +static int __net_init arp_tables_net_init(struct net *net) +{ + return xt_proto_init(net, NF_ARP); +} + +static void __net_exit arp_tables_net_exit(struct net *net) +{ + xt_proto_fini(net, NF_ARP); +} + +static struct pernet_operations arp_tables_net_ops = { + .init = arp_tables_net_init, + .exit = arp_tables_net_exit, +}; + static int __init arp_tables_init(void) { int ret; - ret = xt_proto_init(NF_ARP); + ret = register_pernet_subsys(&arp_tables_net_ops); if (ret < 0) goto err1; @@ -1838,7 +1866,7 @@ err4: err3: xt_unregister_target(&arpt_standard_target); err2: - xt_proto_fini(NF_ARP); + unregister_pernet_subsys(&arp_tables_net_ops); err1: return ret; } @@ -1848,7 +1876,7 @@ static void __exit arp_tables_fini(void) nf_unregister_sockopt(&arpt_sockopts); xt_unregister_target(&arpt_error_target); xt_unregister_target(&arpt_standard_target); - xt_proto_fini(NF_ARP); + unregister_pernet_subsys(&arp_tables_net_ops); } EXPORT_SYMBOL(arpt_register_table); diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 7201511d..4e9c496 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -20,7 +20,7 @@ static struct struct arpt_replace repl; struct arpt_standard entries[3]; struct arpt_error term; -} initial_table __initdata = { +} initial_table __net_initdata = { .repl = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, @@ -61,7 +61,7 @@ static unsigned int arpt_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return arpt_do_table(skb, hook, in, out, &packet_filter); + return arpt_do_table(skb, hook, in, out, init_net.ipv4.arptable_filter); } static struct nf_hook_ops arpt_ops[] __read_mostly = { @@ -85,12 +85,31 @@ static struct nf_hook_ops arpt_ops[] __read_mostly = { }, }; +static int __net_init arptable_filter_net_init(struct net *net) +{ + /* Register table */ + net->ipv4.arptable_filter = + arpt_register_table(net, &packet_filter, &initial_table.repl); + if (IS_ERR(net->ipv4.arptable_filter)) + return PTR_ERR(net->ipv4.arptable_filter); + return 0; +} + +static void __net_exit arptable_filter_net_exit(struct net *net) +{ + arpt_unregister_table(net->ipv4.arptable_filter); +} + +static struct pernet_operations arptable_filter_net_ops = { + .init = arptable_filter_net_init, + .exit = arptable_filter_net_exit, +}; + static int __init arptable_filter_init(void) { int ret; - /* Register table */ - ret = arpt_register_table(&packet_filter, &initial_table.repl); + ret = register_pernet_subsys(&arptable_filter_net_ops); if (ret < 0) return ret; @@ -100,14 +119,14 @@ static int __init arptable_filter_init(void) return ret; cleanup_table: - arpt_unregister_table(&packet_filter); + unregister_pernet_subsys(&arptable_filter_net_ops); return ret; } static void __exit arptable_filter_fini(void) { nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); - arpt_unregister_table(&packet_filter); + unregister_pernet_subsys(&arptable_filter_net_ops); } module_init(arptable_filter_init); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 5109839..6bda110 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -512,6 +512,7 @@ static struct notifier_block ipq_nl_notifier = { .notifier_call = ipq_rcv_nl_event, }; +#ifdef CONFIG_SYSCTL static struct ctl_table_header *ipq_sysctl_header; static ctl_table ipq_table[] = { @@ -525,7 +526,9 @@ static ctl_table ipq_table[] = { }, { .ctl_name = 0 } }; +#endif +#ifdef CONFIG_PROC_FS static int ip_queue_show(struct seq_file *m, void *v) { read_lock_bh(&queue_lock); @@ -562,6 +565,7 @@ static const struct file_operations ip_queue_proc_fops = { .release = single_release, .owner = THIS_MODULE, }; +#endif static const struct nf_queue_handler nfqh = { .name = "ip_queue", @@ -571,7 +575,7 @@ static const struct nf_queue_handler nfqh = { static int __init ip_queue_init(void) { int status = -ENOMEM; - struct proc_dir_entry *proc; + struct proc_dir_entry *proc __maybe_unused; netlink_register_notifier(&ipq_nl_notifier); ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0, @@ -581,6 +585,7 @@ static int __init ip_queue_init(void) goto cleanup_netlink_notifier; } +#ifdef CONFIG_PROC_FS proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); if (proc) { proc->owner = THIS_MODULE; @@ -589,10 +594,11 @@ static int __init ip_queue_init(void) printk(KERN_ERR "ip_queue: failed to create proc entry\n"); goto cleanup_ipqnl; } - +#endif register_netdevice_notifier(&ipq_dev_notifier); +#ifdef CONFIG_SYSCTL ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); - +#endif status = nf_register_queue_handler(PF_INET, &nfqh); if (status < 0) { printk(KERN_ERR "ip_queue: failed to register queue handler\n"); @@ -601,10 +607,12 @@ static int __init ip_queue_init(void) return status; cleanup_sysctl: +#ifdef CONFIG_SYSCTL unregister_sysctl_table(ipq_sysctl_header); +#endif unregister_netdevice_notifier(&ipq_dev_notifier); proc_net_remove(&init_net, IPQ_PROC_FS_NAME); -cleanup_ipqnl: +cleanup_ipqnl: __maybe_unused netlink_kernel_release(ipqnl); mutex_lock(&ipqnl_mutex); mutex_unlock(&ipqnl_mutex); @@ -620,7 +628,9 @@ static void __exit ip_queue_fini(void) synchronize_net(); ipq_flush(NULL, 0); +#ifdef CONFIG_SYSCTL unregister_sysctl_table(ipq_sysctl_header); +#endif unregister_netdevice_notifier(&ipq_dev_notifier); proc_net_remove(&init_net, IPQ_PROC_FS_NAME); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 982b7f9..600737f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -291,7 +291,7 @@ static void trace_packet(struct sk_buff *skb, unsigned int hook, const struct net_device *in, const struct net_device *out, - char *tablename, + const char *tablename, struct xt_table_info *private, struct ipt_entry *e) { @@ -1092,7 +1092,7 @@ static int compat_table_info(const struct xt_table_info *info, } #endif -static int get_info(void __user *user, int *len, int compat) +static int get_info(struct net *net, void __user *user, int *len, int compat) { char name[IPT_TABLE_MAXNAMELEN]; struct xt_table *t; @@ -1112,7 +1112,7 @@ static int get_info(void __user *user, int *len, int compat) if (compat) xt_compat_lock(AF_INET); #endif - t = try_then_request_module(xt_find_table_lock(AF_INET, name), + t = try_then_request_module(xt_find_table_lock(net, AF_INET, name), "iptable_%s", name); if (t && !IS_ERR(t)) { struct ipt_getinfo info; @@ -1152,7 +1152,7 @@ static int get_info(void __user *user, int *len, int compat) } static int -get_entries(struct ipt_get_entries __user *uptr, int *len) +get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len) { int ret; struct ipt_get_entries get; @@ -1170,7 +1170,7 @@ get_entries(struct ipt_get_entries __user *uptr, int *len) return -EINVAL; } - t = xt_find_table_lock(AF_INET, get.name); + t = xt_find_table_lock(net, AF_INET, get.name); if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", private->number); @@ -1191,7 +1191,7 @@ get_entries(struct ipt_get_entries __user *uptr, int *len) } static int -__do_replace(const char *name, unsigned int valid_hooks, +__do_replace(struct net *net, const char *name, unsigned int valid_hooks, struct xt_table_info *newinfo, unsigned int num_counters, void __user *counters_ptr) { @@ -1208,7 +1208,7 @@ __do_replace(const char *name, unsigned int valid_hooks, goto out; } - t = try_then_request_module(xt_find_table_lock(AF_INET, name), + t = try_then_request_module(xt_find_table_lock(net, AF_INET, name), "iptable_%s", name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1261,7 +1261,7 @@ __do_replace(const char *name, unsigned int valid_hooks, } static int -do_replace(void __user *user, unsigned int len) +do_replace(struct net *net, void __user *user, unsigned int len) { int ret; struct ipt_replace tmp; @@ -1295,7 +1295,7 @@ do_replace(void __user *user, unsigned int len) duprintf("ip_tables: Translated table\n"); - ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo, + ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, tmp.num_counters, tmp.counters); if (ret) goto free_newinfo_untrans; @@ -1331,7 +1331,7 @@ add_counter_to_entry(struct ipt_entry *e, } static int -do_add_counters(void __user *user, unsigned int len, int compat) +do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) { unsigned int i; struct xt_counters_info tmp; @@ -1383,7 +1383,7 @@ do_add_counters(void __user *user, unsigned int len, int compat) goto free; } - t = xt_find_table_lock(AF_INET, name); + t = xt_find_table_lock(net, AF_INET, name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1429,7 +1429,7 @@ struct compat_ipt_replace { static int compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, - compat_uint_t *size, struct xt_counters *counters, + unsigned int *size, struct xt_counters *counters, unsigned int *i) { struct ipt_entry_target *t; @@ -1476,7 +1476,7 @@ compat_find_calc_match(struct ipt_entry_match *m, const char *name, const struct ipt_ip *ip, unsigned int hookmask, - int *size, int *i) + int *size, unsigned int *i) { struct xt_match *match; @@ -1534,7 +1534,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, struct ipt_entry_target *t; struct xt_target *target; unsigned int entry_offset; - int ret, off, h, j; + unsigned int j; + int ret, off, h; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 @@ -1647,7 +1648,8 @@ static int compat_check_entry(struct ipt_entry *e, const char *name, unsigned int *i) { - int j, ret; + unsigned int j; + int ret; j = 0; ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, @@ -1789,7 +1791,7 @@ out_unlock: } static int -compat_do_replace(void __user *user, unsigned int len) +compat_do_replace(struct net *net, void __user *user, unsigned int len) { int ret; struct compat_ipt_replace tmp; @@ -1826,7 +1828,7 @@ compat_do_replace(void __user *user, unsigned int len) duprintf("compat_do_replace: Translated table\n"); - ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo, + ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, tmp.num_counters, compat_ptr(tmp.counters)); if (ret) goto free_newinfo_untrans; @@ -1850,11 +1852,11 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, switch (cmd) { case IPT_SO_SET_REPLACE: - ret = compat_do_replace(user, len); + ret = compat_do_replace(sk->sk_net, user, len); break; case IPT_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 1); + ret = do_add_counters(sk->sk_net, user, len, 1); break; default: @@ -1903,7 +1905,8 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, } static int -compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len) +compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr, + int *len) { int ret; struct compat_ipt_get_entries get; @@ -1924,7 +1927,7 @@ compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len) } xt_compat_lock(AF_INET); - t = xt_find_table_lock(AF_INET, get.name); + t = xt_find_table_lock(net, AF_INET, get.name); if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; struct xt_table_info info; @@ -1960,10 +1963,10 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) switch (cmd) { case IPT_SO_GET_INFO: - ret = get_info(user, len, 1); + ret = get_info(sk->sk_net, user, len, 1); break; case IPT_SO_GET_ENTRIES: - ret = compat_get_entries(user, len); + ret = compat_get_entries(sk->sk_net, user, len); break; default: ret = do_ipt_get_ctl(sk, cmd, user, len); @@ -1982,11 +1985,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) switch (cmd) { case IPT_SO_SET_REPLACE: - ret = do_replace(user, len); + ret = do_replace(sk->sk_net, user, len); break; case IPT_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 0); + ret = do_add_counters(sk->sk_net, user, len, 0); break; default: @@ -2007,11 +2010,11 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) switch (cmd) { case IPT_SO_GET_INFO: - ret = get_info(user, len, 0); + ret = get_info(sk->sk_net, user, len, 0); break; case IPT_SO_GET_ENTRIES: - ret = get_entries(user, len); + ret = get_entries(sk->sk_net, user, len); break; case IPT_SO_GET_REVISION_MATCH: @@ -2048,17 +2051,21 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return ret; } -int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) +struct xt_table *ipt_register_table(struct net *net, struct xt_table *table, + const struct ipt_replace *repl) { int ret; struct xt_table_info *newinfo; struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; + struct xt_table *new_table; newinfo = xt_alloc_table_info(repl->size); - if (!newinfo) - return -ENOMEM; + if (!newinfo) { + ret = -ENOMEM; + goto out; + } /* choose the copy on our node/cpu, but dont care about preemption */ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; @@ -2069,30 +2076,36 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) repl->num_entries, repl->hook_entry, repl->underflow); - if (ret != 0) { - xt_free_table_info(newinfo); - return ret; - } + if (ret != 0) + goto out_free; - ret = xt_register_table(table, &bootstrap, newinfo); - if (ret != 0) { - xt_free_table_info(newinfo); - return ret; + new_table = xt_register_table(net, table, &bootstrap, newinfo); + if (IS_ERR(new_table)) { + ret = PTR_ERR(new_table); + goto out_free; } - return 0; + return new_table; + +out_free: + xt_free_table_info(newinfo); +out: + return ERR_PTR(ret); } void ipt_unregister_table(struct xt_table *table) { struct xt_table_info *private; void *loc_cpu_entry; + struct module *table_owner = table->me; private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + if (private->number > private->initial_entries) + module_put(table_owner); xt_free_table_info(private); } @@ -2200,11 +2213,26 @@ static struct xt_match icmp_matchstruct __read_mostly = { .family = AF_INET, }; +static int __net_init ip_tables_net_init(struct net *net) +{ + return xt_proto_init(net, AF_INET); +} + +static void __net_exit ip_tables_net_exit(struct net *net) +{ + xt_proto_fini(net, AF_INET); +} + +static struct pernet_operations ip_tables_net_ops = { + .init = ip_tables_net_init, + .exit = ip_tables_net_exit, +}; + static int __init ip_tables_init(void) { int ret; - ret = xt_proto_init(AF_INET); + ret = register_pernet_subsys(&ip_tables_net_ops); if (ret < 0) goto err1; @@ -2234,7 +2262,7 @@ err4: err3: xt_unregister_target(&ipt_standard_target); err2: - xt_proto_fini(AF_INET); + unregister_pernet_subsys(&ip_tables_net_ops); err1: return ret; } @@ -2247,7 +2275,7 @@ static void __exit ip_tables_fini(void) xt_unregister_target(&ipt_error_target); xt_unregister_target(&ipt_standard_target); - xt_proto_fini(AF_INET); + unregister_pernet_subsys(&ip_tables_net_ops); } EXPORT_SYMBOL(ipt_register_table); diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 1b31f7d..c6cf84c 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -76,13 +76,6 @@ clusterip_config_put(struct clusterip_config *c) kfree(c); } -/* increase the count of entries(rules) using/referencing this config */ -static inline void -clusterip_config_entry_get(struct clusterip_config *c) -{ - atomic_inc(&c->entries); -} - /* decrease the count of entries using/referencing this config. If last * entry(rule) is removed, remove the config from lists, but don't free it * yet, since proc-files could still be holding references */ diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index e3154a9..68cbe3c 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -212,11 +212,11 @@ recent_mt(const struct sk_buff *skb, const struct net_device *in, recent_entry_remove(t, e); ret = !ret; } else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) { - unsigned long t = jiffies - info->seconds * HZ; + unsigned long time = jiffies - info->seconds * HZ; unsigned int i, hits = 0; for (i = 0; i < e->nstamps; i++) { - if (info->seconds && time_after(t, e->stamps[i])) + if (info->seconds && time_after(time, e->stamps[i])) continue; if (++hits >= info->hit_count) { ret = !ret; @@ -320,6 +320,7 @@ struct recent_iter_state { }; static void *recent_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(recent_lock) { struct recent_iter_state *st = seq->private; const struct recent_table *t = st->table; @@ -352,6 +353,7 @@ static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void recent_seq_stop(struct seq_file *s, void *v) + __releases(recent_lock) { spin_unlock_bh(&recent_lock); } diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 29bb4f9..69f3d7e 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -28,7 +28,7 @@ static struct struct ipt_replace repl; struct ipt_standard entries[3]; struct ipt_error term; -} initial_table __initdata = { +} initial_table __net_initdata = { .repl = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, @@ -69,7 +69,7 @@ ipt_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ipt_do_table(skb, hook, in, out, &packet_filter); + return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter); } static unsigned int @@ -88,7 +88,7 @@ ipt_local_out_hook(unsigned int hook, return NF_ACCEPT; } - return ipt_do_table(skb, hook, in, out, &packet_filter); + return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter); } static struct nf_hook_ops ipt_ops[] __read_mostly = { @@ -119,6 +119,26 @@ static struct nf_hook_ops ipt_ops[] __read_mostly = { static int forward = NF_ACCEPT; module_param(forward, bool, 0000); +static int __net_init iptable_filter_net_init(struct net *net) +{ + /* Register table */ + net->ipv4.iptable_filter = + ipt_register_table(net, &packet_filter, &initial_table.repl); + if (IS_ERR(net->ipv4.iptable_filter)) + return PTR_ERR(net->ipv4.iptable_filter); + return 0; +} + +static void __net_exit iptable_filter_net_exit(struct net *net) +{ + ipt_unregister_table(net->ipv4.iptable_filter); +} + +static struct pernet_operations iptable_filter_net_ops = { + .init = iptable_filter_net_init, + .exit = iptable_filter_net_exit, +}; + static int __init iptable_filter_init(void) { int ret; @@ -131,8 +151,7 @@ static int __init iptable_filter_init(void) /* Entry 1 is the FORWARD hook */ initial_table.entries[1].target.verdict = -forward - 1; - /* Register table */ - ret = ipt_register_table(&packet_filter, &initial_table.repl); + ret = register_pernet_subsys(&iptable_filter_net_ops); if (ret < 0) return ret; @@ -144,14 +163,14 @@ static int __init iptable_filter_init(void) return ret; cleanup_table: - ipt_unregister_table(&packet_filter); + unregister_pernet_subsys(&iptable_filter_net_ops); return ret; } static void __exit iptable_filter_fini(void) { nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); - ipt_unregister_table(&packet_filter); + unregister_pernet_subsys(&iptable_filter_net_ops); } module_init(iptable_filter_init); diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 5c4be20..c55a210 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -33,7 +33,7 @@ static struct struct ipt_replace repl; struct ipt_standard entries[5]; struct ipt_error term; -} initial_table __initdata = { +} initial_table __net_initdata = { .repl = { .name = "mangle", .valid_hooks = MANGLE_VALID_HOOKS, @@ -80,7 +80,7 @@ ipt_route_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ipt_do_table(skb, hook, in, out, &packet_mangler); + return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle); } static unsigned int @@ -112,7 +112,7 @@ ipt_local_hook(unsigned int hook, daddr = iph->daddr; tos = iph->tos; - ret = ipt_do_table(skb, hook, in, out, &packet_mangler); + ret = ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle); /* Reroute for ANY change. */ if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { iph = ip_hdr(skb); @@ -166,12 +166,31 @@ static struct nf_hook_ops ipt_ops[] __read_mostly = { }, }; +static int __net_init iptable_mangle_net_init(struct net *net) +{ + /* Register table */ + net->ipv4.iptable_mangle = + ipt_register_table(net, &packet_mangler, &initial_table.repl); + if (IS_ERR(net->ipv4.iptable_mangle)) + return PTR_ERR(net->ipv4.iptable_mangle); + return 0; +} + +static void __net_exit iptable_mangle_net_exit(struct net *net) +{ + ipt_unregister_table(net->ipv4.iptable_mangle); +} + +static struct pernet_operations iptable_mangle_net_ops = { + .init = iptable_mangle_net_init, + .exit = iptable_mangle_net_exit, +}; + static int __init iptable_mangle_init(void) { int ret; - /* Register table */ - ret = ipt_register_table(&packet_mangler, &initial_table.repl); + ret = register_pernet_subsys(&iptable_mangle_net_ops); if (ret < 0) return ret; @@ -183,14 +202,14 @@ static int __init iptable_mangle_init(void) return ret; cleanup_table: - ipt_unregister_table(&packet_mangler); + unregister_pernet_subsys(&iptable_mangle_net_ops); return ret; } static void __exit iptable_mangle_fini(void) { nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); - ipt_unregister_table(&packet_mangler); + unregister_pernet_subsys(&iptable_mangle_net_ops); } module_init(iptable_mangle_init); diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index dc34aa2..e41fe8c 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -14,7 +14,7 @@ static struct struct ipt_replace repl; struct ipt_standard entries[2]; struct ipt_error term; -} initial_table __initdata = { +} initial_table __net_initdata = { .repl = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, @@ -52,7 +52,7 @@ ipt_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ipt_do_table(skb, hook, in, out, &packet_raw); + return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw); } static unsigned int @@ -70,7 +70,7 @@ ipt_local_hook(unsigned int hook, "packet.\n"); return NF_ACCEPT; } - return ipt_do_table(skb, hook, in, out, &packet_raw); + return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw); } /* 'raw' is the very first table. */ @@ -91,12 +91,31 @@ static struct nf_hook_ops ipt_ops[] __read_mostly = { }, }; +static int __net_init iptable_raw_net_init(struct net *net) +{ + /* Register table */ + net->ipv4.iptable_raw = + ipt_register_table(net, &packet_raw, &initial_table.repl); + if (IS_ERR(net->ipv4.iptable_raw)) + return PTR_ERR(net->ipv4.iptable_raw); + return 0; +} + +static void __net_exit iptable_raw_net_exit(struct net *net) +{ + ipt_unregister_table(net->ipv4.iptable_raw); +} + +static struct pernet_operations iptable_raw_net_ops = { + .init = iptable_raw_net_init, + .exit = iptable_raw_net_exit, +}; + static int __init iptable_raw_init(void) { int ret; - /* Register table */ - ret = ipt_register_table(&packet_raw, &initial_table.repl); + ret = register_pernet_subsys(&iptable_raw_net_ops); if (ret < 0) return ret; @@ -108,14 +127,14 @@ static int __init iptable_raw_init(void) return ret; cleanup_table: - ipt_unregister_table(&packet_raw); + unregister_pernet_subsys(&iptable_raw_net_ops); return ret; } static void __exit iptable_raw_fini(void) { nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); - ipt_unregister_table(&packet_raw); + unregister_pernet_subsys(&iptable_raw_net_ops); } module_init(iptable_raw_init); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index ac3d61d..a65b845 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -27,7 +27,8 @@ static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { - __be32 _addrs[2], *ap; + const __be32 *ap; + __be32 _addrs[2]; ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr), sizeof(u_int32_t) * 2, _addrs); if (ap == NULL) @@ -76,7 +77,8 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, unsigned int *dataoff, u_int8_t *protonum) { - struct iphdr _iph, *iph; + const struct iphdr *iph; + struct iphdr _iph; iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); if (iph == NULL) @@ -111,8 +113,8 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, { struct nf_conn *ct; enum ip_conntrack_info ctinfo; - struct nf_conn_help *help; - struct nf_conntrack_helper *helper; + const struct nf_conn_help *help; + const struct nf_conntrack_helper *helper; /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(skb, &ctinfo); @@ -299,8 +301,8 @@ static ctl_table ip_ct_sysctl_table[] = { static int getorigdst(struct sock *sk, int optval, void __user *user, int *len) { - struct inet_sock *inet = inet_sk(sk); - struct nf_conntrack_tuple_hash *h; + const struct inet_sock *inet = inet_sk(sk); + const struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; NF_CT_TUPLE_U_BLANK(&tuple); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 543c02b..089252e 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -39,12 +39,14 @@ struct ct_iter_state { static struct hlist_node *ct_get_first(struct seq_file *seq) { struct ct_iter_state *st = seq->private; + struct hlist_node *n; for (st->bucket = 0; st->bucket < nf_conntrack_htable_size; st->bucket++) { - if (!hlist_empty(&nf_conntrack_hash[st->bucket])) - return nf_conntrack_hash[st->bucket].first; + n = rcu_dereference(nf_conntrack_hash[st->bucket].first); + if (n) + return n; } return NULL; } @@ -54,11 +56,11 @@ static struct hlist_node *ct_get_next(struct seq_file *seq, { struct ct_iter_state *st = seq->private; - head = head->next; + head = rcu_dereference(head->next); while (head == NULL) { if (++st->bucket >= nf_conntrack_htable_size) return NULL; - head = nf_conntrack_hash[st->bucket].first; + head = rcu_dereference(nf_conntrack_hash[st->bucket].first); } return head; } @@ -74,8 +76,9 @@ static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) } static void *ct_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) { - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); return ct_get_idx(seq, *pos); } @@ -86,16 +89,17 @@ static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) } static void ct_seq_stop(struct seq_file *s, void *v) + __releases(RCU) { - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); } static int ct_seq_show(struct seq_file *s, void *v) { const struct nf_conntrack_tuple_hash *hash = v; const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); - struct nf_conntrack_l3proto *l3proto; - struct nf_conntrack_l4proto *l4proto; + const struct nf_conntrack_l3proto *l3proto; + const struct nf_conntrack_l4proto *l4proto; NF_CT_ASSERT(ct); @@ -191,10 +195,12 @@ struct ct_expect_iter_state { static struct hlist_node *ct_expect_get_first(struct seq_file *seq) { struct ct_expect_iter_state *st = seq->private; + struct hlist_node *n; for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { - if (!hlist_empty(&nf_ct_expect_hash[st->bucket])) - return nf_ct_expect_hash[st->bucket].first; + n = rcu_dereference(nf_ct_expect_hash[st->bucket].first); + if (n) + return n; } return NULL; } @@ -204,11 +210,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq, { struct ct_expect_iter_state *st = seq->private; - head = head->next; + head = rcu_dereference(head->next); while (head == NULL) { if (++st->bucket >= nf_ct_expect_hsize) return NULL; - head = nf_ct_expect_hash[st->bucket].first; + head = rcu_dereference(nf_ct_expect_hash[st->bucket].first); } return head; } @@ -224,8 +230,9 @@ static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos) } static void *exp_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) { - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); return ct_expect_get_idx(seq, *pos); } @@ -236,14 +243,15 @@ static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void exp_seq_stop(struct seq_file *seq, void *v) + __releases(RCU) { - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); } static int exp_seq_show(struct seq_file *s, void *v) { struct nf_conntrack_expect *exp; - struct hlist_node *n = v; + const struct hlist_node *n = v; exp = hlist_entry(n, struct nf_conntrack_expect, hnode); @@ -324,7 +332,7 @@ static void ct_cpu_seq_stop(struct seq_file *seq, void *v) static int ct_cpu_seq_show(struct seq_file *seq, void *v) { unsigned int nr_conntracks = atomic_read(&nf_conntrack_count); - struct ip_conntrack_stat *st = v; + const struct ip_conntrack_stat *st = v; if (v == SEQ_START_TOKEN) { seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n"); diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 4004a04..6873fdd 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -26,7 +26,8 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { - struct icmphdr _hdr, *hp; + const struct icmphdr *hp; + struct icmphdr _hdr; hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); if (hp == NULL) @@ -100,7 +101,7 @@ static int icmp_packet(struct nf_conn *ct, } /* Called when a new connection for this protocol found. */ -static int icmp_new(struct nf_conn *conntrack, +static int icmp_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { static const u_int8_t valid_new[] = { @@ -110,15 +111,15 @@ static int icmp_new(struct nf_conn *conntrack, [ICMP_ADDRESS] = 1 }; - if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) - || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { + if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) + || !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) { /* Can't create a new ICMP `conn' with this. */ pr_debug("icmp: can't create new conn with type %u\n", - conntrack->tuplehash[0].tuple.dst.u.icmp.type); - NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); + ct->tuplehash[0].tuple.dst.u.icmp.type); + NF_CT_DUMP_TUPLE(&ct->tuplehash[0].tuple); return 0; } - atomic_set(&conntrack->proto.icmp.count, 0); + atomic_set(&ct->proto.icmp.count, 0); return 1; } @@ -129,8 +130,8 @@ icmp_error_message(struct sk_buff *skb, unsigned int hooknum) { struct nf_conntrack_tuple innertuple, origtuple; - struct nf_conntrack_l4proto *innerproto; - struct nf_conntrack_tuple_hash *h; + const struct nf_conntrack_l4proto *innerproto; + const struct nf_conntrack_tuple_hash *h; NF_CT_ASSERT(skb->nfct == NULL); @@ -176,7 +177,8 @@ static int icmp_error(struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum) { - struct icmphdr _ih, *icmph; + const struct icmphdr *icmph; + struct icmphdr _ih; /* Not enough header? */ icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih); diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index e53ae1e..dd07362 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -31,7 +31,7 @@ #include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l4proto.h> -static DEFINE_RWLOCK(nf_nat_lock); +static DEFINE_SPINLOCK(nf_nat_lock); static struct nf_conntrack_l3proto *l3proto __read_mostly; @@ -154,8 +154,8 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple, struct nf_conn *ct; struct hlist_node *n; - read_lock_bh(&nf_nat_lock); - hlist_for_each_entry(nat, n, &bysource[h], bysource) { + rcu_read_lock(); + hlist_for_each_entry_rcu(nat, n, &bysource[h], bysource) { ct = nat->ct; if (same_src(ct, tuple)) { /* Copy source part from reply tuple. */ @@ -164,12 +164,12 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple, result->dst = tuple->dst; if (in_range(result, range)) { - read_unlock_bh(&nf_nat_lock); + rcu_read_unlock(); return 1; } } } - read_unlock_bh(&nf_nat_lock); + rcu_read_unlock(); return 0; } @@ -330,12 +330,12 @@ nf_nat_setup_info(struct nf_conn *ct, unsigned int srchash; srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - write_lock_bh(&nf_nat_lock); + spin_lock_bh(&nf_nat_lock); /* nf_conntrack_alter_reply might re-allocate exntension aera */ nat = nfct_nat(ct); nat->ct = ct; - hlist_add_head(&nat->bysource, &bysource[srchash]); - write_unlock_bh(&nf_nat_lock); + hlist_add_head_rcu(&nat->bysource, &bysource[srchash]); + spin_unlock_bh(&nf_nat_lock); } /* It's done. */ @@ -521,14 +521,14 @@ int nf_nat_protocol_register(const struct nf_nat_protocol *proto) { int ret = 0; - write_lock_bh(&nf_nat_lock); + spin_lock_bh(&nf_nat_lock); if (nf_nat_protos[proto->protonum] != &nf_nat_unknown_protocol) { ret = -EBUSY; goto out; } rcu_assign_pointer(nf_nat_protos[proto->protonum], proto); out: - write_unlock_bh(&nf_nat_lock); + spin_unlock_bh(&nf_nat_lock); return ret; } EXPORT_SYMBOL(nf_nat_protocol_register); @@ -536,10 +536,10 @@ EXPORT_SYMBOL(nf_nat_protocol_register); /* Noone stores the protocol anywhere; simply delete it. */ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) { - write_lock_bh(&nf_nat_lock); + spin_lock_bh(&nf_nat_lock); rcu_assign_pointer(nf_nat_protos[proto->protonum], &nf_nat_unknown_protocol); - write_unlock_bh(&nf_nat_lock); + spin_unlock_bh(&nf_nat_lock); synchronize_rcu(); } EXPORT_SYMBOL(nf_nat_protocol_unregister); @@ -594,10 +594,10 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *ct) NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK); - write_lock_bh(&nf_nat_lock); - hlist_del(&nat->bysource); + spin_lock_bh(&nf_nat_lock); + hlist_del_rcu(&nat->bysource); nat->ct = NULL; - write_unlock_bh(&nf_nat_lock); + spin_unlock_bh(&nf_nat_lock); } static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) @@ -609,10 +609,10 @@ static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) if (!ct || !(ct->status & IPS_NAT_DONE_MASK)) return; - write_lock_bh(&nf_nat_lock); + spin_lock_bh(&nf_nat_lock); hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); new_nat->ct = ct; - write_unlock_bh(&nf_nat_lock); + spin_unlock_bh(&nf_nat_lock); } static struct nf_ct_ext_type nat_extend __read_mostly = { @@ -646,17 +646,13 @@ static int __init nf_nat_init(void) } /* Sew in builtin protocols. */ - write_lock_bh(&nf_nat_lock); + spin_lock_bh(&nf_nat_lock); for (i = 0; i < MAX_IP_NAT_PROTO; i++) rcu_assign_pointer(nf_nat_protos[i], &nf_nat_unknown_protocol); rcu_assign_pointer(nf_nat_protos[IPPROTO_TCP], &nf_nat_protocol_tcp); rcu_assign_pointer(nf_nat_protos[IPPROTO_UDP], &nf_nat_protocol_udp); rcu_assign_pointer(nf_nat_protos[IPPROTO_ICMP], &nf_nat_protocol_icmp); - write_unlock_bh(&nf_nat_lock); - - for (i = 0; i < nf_nat_htable_size; i++) { - INIT_HLIST_HEAD(&bysource[i]); - } + spin_unlock_bh(&nf_nat_lock); /* Initialize fake conntrack so that NAT will skip it */ nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK; diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index a121989..ee47bf2 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -32,7 +32,8 @@ static int set_addr(struct sk_buff *skb, __be32 ip; __be16 port; } __attribute__ ((__packed__)) buf; - struct tcphdr _tcph, *th; + const struct tcphdr *th; + struct tcphdr _tcph; buf.ip = ip; buf.port = port; @@ -99,7 +100,7 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, unsigned char **data, TransportAddress *taddr, int count) { - struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); int i; __be16 port; diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 4c02328..ca57f47 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -44,8 +44,7 @@ adjust_tcp_sequence(u32 seq, struct nf_nat_seq *this_way, *other_way; struct nf_conn_nat *nat = nfct_nat(ct); - pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n", - ntohl(seq), seq); + pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n", seq, seq); dir = CTINFO2DIR(ctinfo); diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index e63b944..3a1e6d6 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c @@ -40,11 +40,11 @@ MODULE_ALIAS("ip_nat_pptp"); static void pptp_nat_expected(struct nf_conn *ct, struct nf_conntrack_expect *exp) { - struct nf_conn *master = ct->master; + const struct nf_conn *master = ct->master; struct nf_conntrack_expect *other_exp; struct nf_conntrack_tuple t; - struct nf_ct_pptp_master *ct_pptp_info; - struct nf_nat_pptp *nat_pptp_info; + const struct nf_ct_pptp_master *ct_pptp_info; + const struct nf_nat_pptp *nat_pptp_info; struct nf_nat_range range; ct_pptp_info = &nfct_help(master)->help.ct_pptp_info; @@ -186,7 +186,7 @@ static void pptp_exp_gre(struct nf_conntrack_expect *expect_orig, struct nf_conntrack_expect *expect_reply) { - struct nf_conn *ct = expect_orig->master; + const struct nf_conn *ct = expect_orig->master; struct nf_ct_pptp_master *ct_pptp_info; struct nf_nat_pptp *nat_pptp_info; @@ -217,7 +217,7 @@ pptp_inbound_pkt(struct sk_buff *skb, struct PptpControlHeader *ctlh, union pptp_ctrl_union *pptpReq) { - struct nf_nat_pptp *nat_pptp_info; + const struct nf_nat_pptp *nat_pptp_info; u_int16_t msg; __be16 new_pcid; unsigned int pcid_off; diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index 9fa272e..a1e4da1 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c @@ -59,7 +59,7 @@ static int gre_unique_tuple(struct nf_conntrack_tuple *tuple, const struct nf_nat_range *range, enum nf_nat_manip_type maniptype, - const struct nf_conn *conntrack) + const struct nf_conn *ct) { static u_int16_t key; __be16 *keyptr; @@ -67,7 +67,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, /* If there is no master conntrack we are not PPTP, do not change tuples */ - if (!conntrack->master) + if (!ct->master) return 0; if (maniptype == IP_NAT_MANIP_SRC) @@ -76,7 +76,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, keyptr = &tuple->dst.u.gre.key; if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { - pr_debug("%p: NATing GRE PPTP\n", conntrack); + pr_debug("%p: NATing GRE PPTP\n", ct); min = 1; range_size = 0xffff; } else { @@ -88,11 +88,11 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, for (i = 0; i < range_size; i++, key++) { *keyptr = htons(min + key % range_size); - if (!nf_nat_used_tuple(tuple, conntrack)) + if (!nf_nat_used_tuple(tuple, ct)) return 1; } - pr_debug("%p: no NAT mapping\n", conntrack); + pr_debug("%p: no NAT mapping\n", ct); return 0; } @@ -104,7 +104,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, { struct gre_hdr *greh; struct gre_hdr_pptp *pgreh; - struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); + const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); unsigned int hdroff = iphdroff + iph->ihl * 4; /* pgreh includes two optional 32bit fields which are not required @@ -148,12 +148,12 @@ static const struct nf_nat_protocol gre = { #endif }; -int __init nf_nat_proto_gre_init(void) +static int __init nf_nat_proto_gre_init(void) { return nf_nat_protocol_register(&gre); } -void __exit nf_nat_proto_gre_fini(void) +static void __exit nf_nat_proto_gre_fini(void) { nf_nat_protocol_unregister(&gre); } diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c index a0e44c9..03a0296 100644 --- a/net/ipv4/netfilter/nf_nat_proto_icmp.c +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c @@ -57,7 +57,7 @@ icmp_manip_pkt(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, enum nf_nat_manip_type maniptype) { - struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); + const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); struct icmphdr *hdr; unsigned int hdroff = iphdroff + iph->ihl*4; diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index da23e9fb..ffd5d15 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c @@ -93,7 +93,7 @@ tcp_manip_pkt(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, enum nf_nat_manip_type maniptype) { - struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); + const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); struct tcphdr *hdr; unsigned int hdroff = iphdroff + iph->ihl*4; __be32 oldip, newip; diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index 10df4db..4b8f499 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c @@ -91,7 +91,7 @@ udp_manip_pkt(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, enum nf_nat_manip_type maniptype) { - struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); + const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); struct udphdr *hdr; unsigned int hdroff = iphdroff + iph->ihl*4; __be32 oldip, newip; diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 5191822..f8fda57 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -58,13 +58,14 @@ static struct .term = IPT_ERROR_INIT, /* ERROR */ }; -static struct xt_table nat_table = { +static struct xt_table __nat_table = { .name = "nat", .valid_hooks = NAT_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, .af = AF_INET, }; +static struct xt_table *nat_table; /* Source NAT */ static unsigned int ipt_snat_target(struct sk_buff *skb, @@ -214,7 +215,7 @@ int nf_nat_rule_find(struct sk_buff *skb, { int ret; - ret = ipt_do_table(skb, hooknum, in, out, &nat_table); + ret = ipt_do_table(skb, hooknum, in, out, nat_table); if (ret == NF_ACCEPT) { if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) @@ -248,9 +249,10 @@ int __init nf_nat_rule_init(void) { int ret; - ret = ipt_register_table(&nat_table, &nat_initial_table.repl); - if (ret != 0) - return ret; + nat_table = ipt_register_table(&init_net, &__nat_table, + &nat_initial_table.repl); + if (IS_ERR(nat_table)) + return PTR_ERR(nat_table); ret = xt_register_target(&ipt_snat_reg); if (ret != 0) goto unregister_table; @@ -264,7 +266,7 @@ int __init nf_nat_rule_init(void) unregister_snat: xt_unregister_target(&ipt_snat_reg); unregister_table: - ipt_unregister_table(&nat_table); + ipt_unregister_table(nat_table); return ret; } @@ -273,5 +275,5 @@ void nf_nat_rule_cleanup(void) { xt_unregister_target(&ipt_dnat_reg); xt_unregister_target(&ipt_snat_reg); - ipt_unregister_table(&nat_table); + ipt_unregister_table(nat_table); } diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 606a170..b4c8d49 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -35,9 +35,9 @@ struct addr_map { } addr[IP_CT_DIR_MAX]; }; -static void addr_map_init(struct nf_conn *ct, struct addr_map *map) +static void addr_map_init(const struct nf_conn *ct, struct addr_map *map) { - struct nf_conntrack_tuple *t; + const struct nf_conntrack_tuple *t; enum ip_conntrack_dir dir; unsigned int n; diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 07f2a49..540ce6a 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -260,7 +260,7 @@ static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc) { unsigned char ch; - if (eoc == 0) { + if (eoc == NULL) { if (!asn1_octet_decode(ctx, &ch)) return 0; diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c index 1360a94..b096e81 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/ipv4/netfilter/nf_nat_tftp.c @@ -24,7 +24,7 @@ static unsigned int help(struct sk_buff *skb, enum ip_conntrack_info ctinfo, struct nf_conntrack_expect *exp) { - struct nf_conn *ct = exp->master; + const struct nf_conn *ct = exp->master; exp->saved_proto.udp.port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 85c0869..a3002fe 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -352,6 +352,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, skb_reserve(skb, hh_len); skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; skb->dst = dst_clone(&rt->u.dst); skb_reset_network_header(skb); @@ -544,6 +545,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, { struct flowi fl = { .oif = ipc.oif, + .mark = sk->sk_mark, .nl_u = { .ip4_u = { .daddr = daddr, .saddr = saddr, @@ -860,8 +862,7 @@ static struct sock *raw_get_first(struct seq_file *seq) struct hlist_node *node; sk_for_each(sk, node, &state->h->ht[state->bucket]) - if (sk->sk_net == state->p.net && - sk->sk_family == state->family) + if (sk->sk_net == state->p.net) goto found; } sk = NULL; @@ -877,8 +878,7 @@ static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk) sk = sk_next(sk); try_again: ; - } while (sk && sk->sk_net != state->p.net && - sk->sk_family != state->family); + } while (sk && sk->sk_net != state->p.net); if (!sk && ++state->bucket < RAW_HTABLE_SIZE) { sk = sk_head(&state->h->ht[state->bucket]); @@ -927,7 +927,7 @@ void raw_seq_stop(struct seq_file *seq, void *v) } EXPORT_SYMBOL_GPL(raw_seq_stop); -static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i) +static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) { struct inet_sock *inet = inet_sk(sp); __be32 dest = inet->daddr, @@ -935,33 +935,23 @@ static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i) __u16 destp = 0, srcp = inet->num; - sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" + seq_printf(seq, "%4d: %08X:%04X %08X:%04X" " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d", i, src, srcp, dest, destp, sp->sk_state, atomic_read(&sp->sk_wmem_alloc), atomic_read(&sp->sk_rmem_alloc), 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); - return tmpbuf; } -#define TMPSZ 128 - static int raw_seq_show(struct seq_file *seq, void *v) { - char tmpbuf[TMPSZ+1]; - if (v == SEQ_START_TOKEN) - seq_printf(seq, "%-*s\n", TMPSZ-1, - " sl local_address rem_address st tx_queue " - "rx_queue tr tm->when retrnsmt uid timeout " - "inode drops"); - else { - struct raw_iter_state *state = raw_seq_private(seq); - - seq_printf(seq, "%-*s\n", TMPSZ-1, - get_raw_sock(v, tmpbuf, state->bucket)); - } + seq_printf(seq, " sl local_address rem_address st tx_queue " + "rx_queue tr tm->when retrnsmt uid timeout " + "inode drops\n"); + else + raw_sock_seq_show(seq, v, raw_seq_private(seq)->bucket); return 0; } @@ -972,27 +962,25 @@ static const struct seq_operations raw_seq_ops = { .show = raw_seq_show, }; -int raw_seq_open(struct inode *ino, struct file *file, struct raw_hashinfo *h, - unsigned short family) +int raw_seq_open(struct inode *ino, struct file *file, + struct raw_hashinfo *h, const struct seq_operations *ops) { int err; struct raw_iter_state *i; - err = seq_open_net(ino, file, &raw_seq_ops, - sizeof(struct raw_iter_state)); + err = seq_open_net(ino, file, ops, sizeof(struct raw_iter_state)); if (err < 0) return err; i = raw_seq_private((struct seq_file *)file->private_data); i->h = h; - i->family = family; return 0; } EXPORT_SYMBOL_GPL(raw_seq_open); static int raw_v4_seq_open(struct inode *inode, struct file *file) { - return raw_seq_open(inode, file, &raw_v4_hashinfo, PF_INET); + return raw_seq_open(inode, file, &raw_v4_hashinfo, &raw_seq_ops); } static const struct file_operations raw_seq_fops = { diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 896c768..8842ecb9b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -117,8 +117,6 @@ #define RT_GC_TIMEOUT (300*HZ) -static int ip_rt_min_delay = 2 * HZ; -static int ip_rt_max_delay = 10 * HZ; static int ip_rt_max_size; static int ip_rt_gc_timeout = RT_GC_TIMEOUT; static int ip_rt_gc_interval = 60 * HZ; @@ -133,12 +131,9 @@ static int ip_rt_mtu_expires = 10 * 60 * HZ; static int ip_rt_min_pmtu = 512 + 20 + 20; static int ip_rt_min_advmss = 256; static int ip_rt_secret_interval = 10 * 60 * HZ; -static int ip_rt_flush_expected; -static unsigned long rt_deadline; #define RTprint(a...) printk(KERN_DEBUG a) -static struct timer_list rt_flush_timer; static void rt_worker_func(struct work_struct *work); static DECLARE_DELAYED_WORK(expires_work, rt_worker_func); static struct timer_list rt_secret_timer; @@ -169,6 +164,7 @@ static struct dst_ops ipv4_dst_ops = { .update_pmtu = ip_rt_update_pmtu, .local_out = ip_local_out, .entry_size = sizeof(struct rtable), + .entries = ATOMIC_INIT(0), }; #define ECN_OR_COST(class) TC_PRIO_##class @@ -259,19 +255,16 @@ static inline void rt_hash_lock_init(void) static struct rt_hash_bucket *rt_hash_table; static unsigned rt_hash_mask; static unsigned int rt_hash_log; -static unsigned int rt_hash_rnd; +static atomic_t rt_genid; static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); #define RT_CACHE_STAT_INC(field) \ (__raw_get_cpu_var(rt_cache_stat).field++) -static int rt_intern_hash(unsigned hash, struct rtable *rth, - struct rtable **res); - static unsigned int rt_hash_code(u32 daddr, u32 saddr) { - return (jhash_2words(daddr, saddr, rt_hash_rnd) - & rt_hash_mask); + return jhash_2words(daddr, saddr, atomic_read(&rt_genid)) + & rt_hash_mask; } #define rt_hash(daddr, saddr, idx) \ @@ -281,27 +274,28 @@ static unsigned int rt_hash_code(u32 daddr, u32 saddr) #ifdef CONFIG_PROC_FS struct rt_cache_iter_state { int bucket; + int genid; }; -static struct rtable *rt_cache_get_first(struct seq_file *seq) +static struct rtable *rt_cache_get_first(struct rt_cache_iter_state *st) { struct rtable *r = NULL; - struct rt_cache_iter_state *st = seq->private; for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) { rcu_read_lock_bh(); - r = rt_hash_table[st->bucket].chain; - if (r) - break; + r = rcu_dereference(rt_hash_table[st->bucket].chain); + while (r) { + if (r->rt_genid == st->genid) + return r; + r = rcu_dereference(r->u.dst.rt_next); + } rcu_read_unlock_bh(); } - return rcu_dereference(r); + return r; } -static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r) +static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, struct rtable *r) { - struct rt_cache_iter_state *st = seq->private; - r = r->u.dst.rt_next; while (!r) { rcu_read_unlock_bh(); @@ -313,29 +307,38 @@ static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r) return rcu_dereference(r); } -static struct rtable *rt_cache_get_idx(struct seq_file *seq, loff_t pos) +static struct rtable *rt_cache_get_idx(struct rt_cache_iter_state *st, loff_t pos) { - struct rtable *r = rt_cache_get_first(seq); + struct rtable *r = rt_cache_get_first(st); if (r) - while (pos && (r = rt_cache_get_next(seq, r))) + while (pos && (r = rt_cache_get_next(st, r))) { + if (r->rt_genid != st->genid) + continue; --pos; + } return pos ? NULL : r; } static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) { - return *pos ? rt_cache_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; + struct rt_cache_iter_state *st = seq->private; + + if (*pos) + return rt_cache_get_idx(st, *pos - 1); + st->genid = atomic_read(&rt_genid); + return SEQ_START_TOKEN; } static void *rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct rtable *r = NULL; + struct rtable *r; + struct rt_cache_iter_state *st = seq->private; if (v == SEQ_START_TOKEN) - r = rt_cache_get_first(seq); + r = rt_cache_get_first(st); else - r = rt_cache_get_next(seq, v); + r = rt_cache_get_next(st, v); ++*pos; return r; } @@ -708,6 +711,11 @@ static void rt_check_expire(void) continue; spin_lock_bh(rt_hash_lock_addr(i)); while ((rth = *rthp) != NULL) { + if (rth->rt_genid != atomic_read(&rt_genid)) { + *rthp = rth->u.dst.rt_next; + rt_free(rth); + continue; + } if (rth->u.dst.expires) { /* Entry is expired even if it is in use */ if (time_before_eq(jiffies, rth->u.dst.expires)) { @@ -732,83 +740,45 @@ static void rt_check_expire(void) /* * rt_worker_func() is run in process context. - * If a whole flush was scheduled, it is done. - * Else, we call rt_check_expire() to scan part of the hash table + * we call rt_check_expire() to scan part of the hash table */ static void rt_worker_func(struct work_struct *work) { - if (ip_rt_flush_expected) { - ip_rt_flush_expected = 0; - rt_do_flush(1); - } else - rt_check_expire(); + rt_check_expire(); schedule_delayed_work(&expires_work, ip_rt_gc_interval); } -/* This can run from both BH and non-BH contexts, the latter - * in the case of a forced flush event. +/* + * Pertubation of rt_genid by a small quantity [1..256] + * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() + * many times (2^24) without giving recent rt_genid. + * Jenkins hash is strong enough that litle changes of rt_genid are OK. */ -static void rt_run_flush(unsigned long process_context) +static void rt_cache_invalidate(void) { - rt_deadline = 0; - - get_random_bytes(&rt_hash_rnd, 4); + unsigned char shuffle; - rt_do_flush(process_context); + get_random_bytes(&shuffle, sizeof(shuffle)); + atomic_add(shuffle + 1U, &rt_genid); } -static DEFINE_SPINLOCK(rt_flush_lock); - +/* + * delay < 0 : invalidate cache (fast : entries will be deleted later) + * delay >= 0 : invalidate & flush cache (can be long) + */ void rt_cache_flush(int delay) { - unsigned long now = jiffies; - int user_mode = !in_softirq(); - - if (delay < 0) - delay = ip_rt_min_delay; - - spin_lock_bh(&rt_flush_lock); - - if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) { - long tmo = (long)(rt_deadline - now); - - /* If flush timer is already running - and flush request is not immediate (delay > 0): - - if deadline is not achieved, prolongate timer to "delay", - otherwise fire it at deadline time. - */ - - if (user_mode && tmo < ip_rt_max_delay-ip_rt_min_delay) - tmo = 0; - - if (delay > tmo) - delay = tmo; - } - - if (delay <= 0) { - spin_unlock_bh(&rt_flush_lock); - rt_run_flush(user_mode); - return; - } - - if (rt_deadline == 0) - rt_deadline = now + ip_rt_max_delay; - - mod_timer(&rt_flush_timer, now+delay); - spin_unlock_bh(&rt_flush_lock); + rt_cache_invalidate(); + if (delay >= 0) + rt_do_flush(!in_softirq()); } /* - * We change rt_hash_rnd and ask next rt_worker_func() invocation - * to perform a flush in process context + * We change rt_genid and let gc do the cleanup */ static void rt_secret_rebuild(unsigned long dummy) { - get_random_bytes(&rt_hash_rnd, 4); - ip_rt_flush_expected = 1; - cancel_delayed_work(&expires_work); - schedule_delayed_work(&expires_work, HZ/10); + rt_cache_invalidate(); mod_timer(&rt_secret_timer, jiffies + ip_rt_secret_interval); } @@ -885,7 +855,8 @@ static int rt_garbage_collect(struct dst_ops *ops) rthp = &rt_hash_table[k].chain; spin_lock_bh(rt_hash_lock_addr(k)); while ((rth = *rthp) != NULL) { - if (!rt_may_expire(rth, tmo, expire)) { + if (rth->rt_genid == atomic_read(&rt_genid) && + !rt_may_expire(rth, tmo, expire)) { tmo >>= 1; rthp = &rth->u.dst.rt_next; continue; @@ -966,6 +937,11 @@ restart: spin_lock_bh(rt_hash_lock_addr(hash)); while ((rth = *rthp) != NULL) { + if (rth->rt_genid != atomic_read(&rt_genid)) { + *rthp = rth->u.dst.rt_next; + rt_free(rth); + continue; + } if (compare_keys(&rth->fl, &rt->fl) && compare_netns(rth, rt)) { /* Put it first */ *rthp = rth->u.dst.rt_next; @@ -1131,17 +1107,19 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) static void rt_del(unsigned hash, struct rtable *rt) { - struct rtable **rthp; + struct rtable **rthp, *aux; + rthp = &rt_hash_table[hash].chain; spin_lock_bh(rt_hash_lock_addr(hash)); ip_rt_put(rt); - for (rthp = &rt_hash_table[hash].chain; *rthp; - rthp = &(*rthp)->u.dst.rt_next) - if (*rthp == rt) { - *rthp = rt->u.dst.rt_next; - rt_free(rt); - break; + while ((aux = *rthp) != NULL) { + if (aux == rt || (aux->rt_genid != atomic_read(&rt_genid))) { + *rthp = aux->u.dst.rt_next; + rt_free(aux); + continue; } + rthp = &aux->u.dst.rt_next; + } spin_unlock_bh(rt_hash_lock_addr(hash)); } @@ -1186,7 +1164,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, if (rth->fl.fl4_dst != daddr || rth->fl.fl4_src != skeys[i] || rth->fl.oif != ikeys[k] || - rth->fl.iif != 0) { + rth->fl.iif != 0 || + rth->rt_genid != atomic_read(&rt_genid)) { rthp = &rth->u.dst.rt_next; continue; } @@ -1224,7 +1203,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, rt->u.dst.neighbour = NULL; rt->u.dst.hh = NULL; rt->u.dst.xfrm = NULL; - + rt->rt_genid = atomic_read(&rt_genid); rt->rt_flags |= RTCF_REDIRECTED; /* Gateway is different ... */ @@ -1445,7 +1424,8 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, rth->rt_src == iph->saddr && rth->fl.iif == 0 && !(dst_metric_locked(&rth->u.dst, RTAX_MTU)) && - rth->u.dst.dev->nd_net == net) { + rth->u.dst.dev->nd_net == net && + rth->rt_genid == atomic_read(&rt_genid)) { unsigned short mtu = new_mtu; if (new_mtu < 68 || new_mtu >= old_mtu) { @@ -1680,8 +1660,9 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.oif = 0; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; - rth->rt_type = RTN_MULTICAST; + rth->rt_genid = atomic_read(&rt_genid); rth->rt_flags = RTCF_MULTICAST; + rth->rt_type = RTN_MULTICAST; if (our) { rth->u.dst.input= ip_local_deliver; rth->rt_flags |= RTCF_LOCAL; @@ -1820,6 +1801,7 @@ static inline int __mkroute_input(struct sk_buff *skb, rth->u.dst.input = ip_forward; rth->u.dst.output = ip_output; + rth->rt_genid = atomic_read(&rt_genid); rt_set_nexthop(rth, res, itag); @@ -1980,6 +1962,7 @@ local_input: goto e_nobufs; rth->u.dst.output= ip_rt_bug; + rth->rt_genid = atomic_read(&rt_genid); atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; @@ -2071,7 +2054,8 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.oif == 0 && rth->fl.mark == skb->mark && rth->fl.fl4_tos == tos && - rth->u.dst.dev->nd_net == net) { + rth->u.dst.dev->nd_net == net && + rth->rt_genid == atomic_read(&rt_genid)) { dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(in_hit); rcu_read_unlock(); @@ -2199,6 +2183,7 @@ static inline int __mkroute_output(struct rtable **result, rth->rt_spec_dst= fl->fl4_src; rth->u.dst.output=ip_output; + rth->rt_genid = atomic_read(&rt_genid); RT_CACHE_STAT_INC(out_slow_tot); @@ -2471,7 +2456,8 @@ int __ip_route_output_key(struct net *net, struct rtable **rp, rth->fl.mark == flp->mark && !((rth->fl.fl4_tos ^ flp->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK)) && - rth->u.dst.dev->nd_net == net) { + rth->u.dst.dev->nd_net == net && + rth->rt_genid == atomic_read(&rt_genid)) { dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); @@ -2498,6 +2484,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { .check = ipv4_dst_check, .update_pmtu = ipv4_rt_blackhole_update_pmtu, .entry_size = sizeof(struct rtable), + .entries = ATOMIC_INIT(0), }; @@ -2525,6 +2512,7 @@ static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp, struct sock rt->idev = ort->idev; if (rt->idev) in_dev_hold(rt->idev); + rt->rt_genid = atomic_read(&rt_genid); rt->rt_flags = ort->rt_flags; rt->rt_type = ort->rt_type; rt->rt_dst = ort->rt_dst; @@ -2779,6 +2767,8 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) rt = rcu_dereference(rt->u.dst.rt_next), idx++) { if (idx < s_idx) continue; + if (rt->rt_genid != atomic_read(&rt_genid)) + continue; skb->dst = dst_clone(&rt->u.dst); if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWROUTE, @@ -2848,24 +2838,6 @@ ctl_table ipv4_route_table[] = { .strategy = &ipv4_sysctl_rtcache_flush_strategy, }, { - .ctl_name = NET_IPV4_ROUTE_MIN_DELAY, - .procname = "min_delay", - .data = &ip_rt_min_delay, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies, - }, - { - .ctl_name = NET_IPV4_ROUTE_MAX_DELAY, - .procname = "max_delay", - .data = &ip_rt_max_delay, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies, - }, - { .ctl_name = NET_IPV4_ROUTE_GC_THRESH, .procname = "gc_thresh", .data = &ipv4_dst_ops.gc_thresh, @@ -3023,8 +2995,8 @@ int __init ip_rt_init(void) { int rc = 0; - rt_hash_rnd = (int) ((num_physpages ^ (num_physpages>>8)) ^ - (jiffies ^ (jiffies >> 7))); + atomic_set(&rt_genid, (int) ((num_physpages ^ (num_physpages>>8)) ^ + (jiffies ^ (jiffies >> 7)))); #ifdef CONFIG_NET_CLS_ROUTE ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct)); @@ -3057,7 +3029,6 @@ int __init ip_rt_init(void) devinet_init(); ip_fib_init(); - setup_timer(&rt_flush_timer, rt_run_flush, 0); setup_timer(&rt_secret_timer, rt_secret_rebuild, 0); /* All the timers, started at system startup tend diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 82cdf23..88286f3 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -185,7 +185,7 @@ static int strategy_allowed_congestion_control(ctl_table *table, int __user *nam tcp_get_available_congestion_control(tbl.data, tbl.maxlen); ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen); - if (ret == 0 && newval && newlen) + if (ret == 1 && newval && newlen) ret = tcp_set_allowed_congestion_control(tbl.data); kfree(tbl.data); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fa2c85c..19c449f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2153,7 +2153,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int fast_rexmit) tp->lost_skb_hint = skb; tp->lost_cnt_hint = cnt; - if (tcp_is_fack(tp) || + if (tcp_is_fack(tp) || tcp_is_reno(tp) || (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) cnt += tcp_skb_pcount(skb); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9aea88b..77c1939 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -369,8 +369,8 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) return; } - sk = inet_lookup(&tcp_hashinfo, iph->daddr, th->dest, iph->saddr, - th->source, inet_iif(skb)); + sk = inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->daddr, th->dest, + iph->saddr, th->source, inet_iif(skb)); if (!sk) { ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); return; @@ -1503,8 +1503,8 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) if (req) return tcp_check_req(sk, skb, req, prev); - nsk = inet_lookup_established(&tcp_hashinfo, iph->saddr, th->source, - iph->daddr, th->dest, inet_iif(skb)); + nsk = inet_lookup_established(sk->sk_net, &tcp_hashinfo, iph->saddr, + th->source, iph->daddr, th->dest, inet_iif(skb)); if (nsk) { if (nsk->sk_state != TCP_TIME_WAIT) { @@ -1661,8 +1661,8 @@ int tcp_v4_rcv(struct sk_buff *skb) TCP_SKB_CB(skb)->flags = iph->tos; TCP_SKB_CB(skb)->sacked = 0; - sk = __inet_lookup(&tcp_hashinfo, iph->saddr, th->source, - iph->daddr, th->dest, inet_iif(skb)); + sk = __inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->saddr, + th->source, iph->daddr, th->dest, inet_iif(skb)); if (!sk) goto no_tcp_socket; @@ -1735,7 +1735,8 @@ do_time_wait: } switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { case TCP_TW_SYN: { - struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo, + struct sock *sk2 = inet_lookup_listener(skb->dev->nd_net, + &tcp_hashinfo, iph->daddr, th->dest, inet_iif(skb)); if (sk2) { diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 89f0188..ed750f9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2564,5 +2564,4 @@ EXPORT_SYMBOL(tcp_connect); EXPORT_SYMBOL(tcp_make_synack); EXPORT_SYMBOL(tcp_simple_retransmit); EXPORT_SYMBOL(tcp_sync_mss); -EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor); EXPORT_SYMBOL(tcp_mtup_init); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2fb8d73..7ea1b67 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -130,14 +130,14 @@ EXPORT_SYMBOL(sysctl_udp_wmem_min); atomic_t udp_memory_allocated; EXPORT_SYMBOL(udp_memory_allocated); -static inline int __udp_lib_lport_inuse(__u16 num, +static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, const struct hlist_head udptable[]) { struct sock *sk; struct hlist_node *node; sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) - if (sk->sk_hash == num) + if (sk->sk_net == net && sk->sk_hash == num) return 1; return 0; } @@ -159,6 +159,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, struct hlist_head *head; struct sock *sk2; int error = 1; + struct net *net = sk->sk_net; write_lock_bh(&udp_hash_lock); @@ -198,7 +199,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, /* 2nd pass: find hole in shortest hash chain */ rover = best; for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) { - if (! __udp_lib_lport_inuse(rover, udptable)) + if (! __udp_lib_lport_inuse(net, rover, udptable)) goto gotit; rover += UDP_HTABLE_SIZE; if (rover > high) @@ -218,6 +219,7 @@ gotit: sk_for_each(sk2, node, head) if (sk2->sk_hash == snum && sk2 != sk && + sk2->sk_net == net && (!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) && @@ -261,9 +263,9 @@ static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM */ -static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, - __be32 daddr, __be16 dport, - int dif, struct hlist_head udptable[]) +static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, + __be16 sport, __be32 daddr, __be16 dport, + int dif, struct hlist_head udptable[]) { struct sock *sk, *result = NULL; struct hlist_node *node; @@ -274,7 +276,8 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { struct inet_sock *inet = inet_sk(sk); - if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) { + if (sk->sk_net == net && sk->sk_hash == hnum && + !ipv6_only_sock(sk)) { int score = (sk->sk_family == PF_INET ? 1 : 0); if (inet->rcv_saddr) { if (inet->rcv_saddr != daddr) @@ -361,8 +364,8 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[]) int harderr; int err; - sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, - skb->dev->ifindex, udptable ); + sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest, + iph->saddr, uh->source, skb->dev->ifindex, udptable); if (sk == NULL) { ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); return; /* No socket for error */ @@ -1185,8 +1188,8 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); - sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, - inet_iif(skb), udptable); + sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr, + uh->dest, inet_iif(skb), udptable); if (sk != NULL) { int ret = 0; diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 3783e3e..10ed704 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -247,6 +247,7 @@ static struct dst_ops xfrm4_dst_ops = { .local_out = __ip_local_out, .gc_thresh = 1024, .entry_size = sizeof(struct xfrm_dst), + .entries = ATOMIC_INIT(0), }; static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 3268451..41f5982 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -38,7 +38,7 @@ static void ipip_destroy(struct xfrm_state *x) { } -static struct xfrm_type ipip_type = { +static const struct xfrm_type ipip_type = { .description = "IPIP", .owner = THIS_MODULE, .proto = IPPROTO_IPIP, @@ -50,7 +50,7 @@ static struct xfrm_type ipip_type = { static int xfrm_tunnel_rcv(struct sk_buff *skb) { - return xfrm4_rcv_spi(skb, IPPROTO_IP, ip_hdr(skb)->saddr); + return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr); } static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index eb0b808..3ffb032 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -85,6 +85,7 @@ config INET6_ESP depends on IPV6 select XFRM select CRYPTO + select CRYPTO_AEAD select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_CBC diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index fb0d07a..379c8e0 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -515,7 +515,7 @@ static void ah6_destroy(struct xfrm_state *x) kfree(ahp); } -static struct xfrm_type ah6_type = +static const struct xfrm_type ah6_type = { .description = "AH6", .owner = THIS_MODULE, diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 5bd5292..8e0f142 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -24,33 +24,124 @@ * This file is derived from net/ipv4/esp.c */ +#include <crypto/aead.h> +#include <crypto/authenc.h> #include <linux/err.h> #include <linux/module.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/esp.h> #include <linux/scatterlist.h> -#include <linux/crypto.h> #include <linux/kernel.h> #include <linux/pfkeyv2.h> #include <linux/random.h> +#include <linux/slab.h> #include <linux/spinlock.h> #include <net/icmp.h> #include <net/ipv6.h> #include <net/protocol.h> #include <linux/icmpv6.h> +struct esp_skb_cb { + struct xfrm_skb_cb xfrm; + void *tmp; +}; + +#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) + +/* + * Allocate an AEAD request structure with extra space for SG and IV. + * + * For alignment considerations the IV is placed at the front, followed + * by the request and finally the SG list. + * + * TODO: Use spare space in skb for this where possible. + */ +static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags) +{ + unsigned int len; + + len = crypto_aead_ivsize(aead); + if (len) { + len += crypto_aead_alignmask(aead) & + ~(crypto_tfm_ctx_alignment() - 1); + len = ALIGN(len, crypto_tfm_ctx_alignment()); + } + + len += sizeof(struct aead_givcrypt_request) + crypto_aead_reqsize(aead); + len = ALIGN(len, __alignof__(struct scatterlist)); + + len += sizeof(struct scatterlist) * nfrags; + + return kmalloc(len, GFP_ATOMIC); +} + +static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp) +{ + return crypto_aead_ivsize(aead) ? + PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp; +} + +static inline struct aead_givcrypt_request *esp_tmp_givreq( + struct crypto_aead *aead, u8 *iv) +{ + struct aead_givcrypt_request *req; + + req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead), + crypto_tfm_ctx_alignment()); + aead_givcrypt_set_tfm(req, aead); + return req; +} + +static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv) +{ + struct aead_request *req; + + req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead), + crypto_tfm_ctx_alignment()); + aead_request_set_tfm(req, aead); + return req; +} + +static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead, + struct aead_request *req) +{ + return (void *)ALIGN((unsigned long)(req + 1) + + crypto_aead_reqsize(aead), + __alignof__(struct scatterlist)); +} + +static inline struct scatterlist *esp_givreq_sg( + struct crypto_aead *aead, struct aead_givcrypt_request *req) +{ + return (void *)ALIGN((unsigned long)(req + 1) + + crypto_aead_reqsize(aead), + __alignof__(struct scatterlist)); +} + +static void esp_output_done(struct crypto_async_request *base, int err) +{ + struct sk_buff *skb = base->data; + + kfree(ESP_SKB_CB(skb)->tmp); + xfrm_output_resume(skb, err); +} + static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) { int err; struct ip_esp_hdr *esph; - struct crypto_blkcipher *tfm; - struct blkcipher_desc desc; + struct crypto_aead *aead; + struct aead_givcrypt_request *req; + struct scatterlist *sg; + struct scatterlist *asg; struct sk_buff *trailer; + void *tmp; int blksize; int clen; int alen; int nfrags; + u8 *iv; u8 *tail; struct esp_data *esp = x->data; @@ -60,18 +151,26 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) /* Round to block size */ clen = skb->len; - alen = esp->auth.icv_trunc_len; - tfm = esp->conf.tfm; - desc.tfm = tfm; - desc.flags = 0; - blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); + aead = esp->aead; + alen = crypto_aead_authsize(aead); + + blksize = ALIGN(crypto_aead_blocksize(aead), 4); clen = ALIGN(clen + 2, blksize); - if (esp->conf.padlen) - clen = ALIGN(clen, esp->conf.padlen); + if (esp->padlen) + clen = ALIGN(clen, esp->padlen); - if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) { + if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0) goto error; - } + nfrags = err; + + tmp = esp_alloc_tmp(aead, nfrags + 1); + if (!tmp) + goto error; + + iv = esp_tmp_iv(aead, tmp); + req = esp_tmp_givreq(aead, iv); + asg = esp_givreq_sg(aead, req); + sg = asg + 1; /* Fill padding... */ tail = skb_tail_pointer(trailer); @@ -81,86 +180,113 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) tail[i] = i + 1; } while (0); tail[clen-skb->len - 2] = (clen - skb->len) - 2; - pskb_put(skb, trailer, clen - skb->len); + tail[clen - skb->len - 1] = *skb_mac_header(skb); + pskb_put(skb, trailer, clen - skb->len + alen); skb_push(skb, -skb_network_offset(skb)); esph = ip_esp_hdr(skb); - *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb); *skb_mac_header(skb) = IPPROTO_ESP; esph->spi = x->id.spi; esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq); - spin_lock_bh(&x->lock); + sg_init_table(sg, nfrags); + skb_to_sgvec(skb, sg, + esph->enc_data + crypto_aead_ivsize(aead) - skb->data, + clen + alen); + sg_init_one(asg, esph, sizeof(*esph)); - if (esp->conf.ivlen) { - if (unlikely(!esp->conf.ivinitted)) { - get_random_bytes(esp->conf.ivec, esp->conf.ivlen); - esp->conf.ivinitted = 1; - } - crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); - } + aead_givcrypt_set_callback(req, 0, esp_output_done, skb); + aead_givcrypt_set_crypt(req, sg, sg, clen, iv); + aead_givcrypt_set_assoc(req, asg, sizeof(*esph)); + aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq); - do { - struct scatterlist *sg = &esp->sgbuf[0]; + ESP_SKB_CB(skb)->tmp = tmp; + err = crypto_aead_givencrypt(req); + if (err == -EINPROGRESS) + goto error; - if (unlikely(nfrags > ESP_NUM_FAST_SG)) { - sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); - if (!sg) - goto unlock; - } - sg_init_table(sg, nfrags); - skb_to_sgvec(skb, sg, - esph->enc_data + - esp->conf.ivlen - - skb->data, clen); - err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); - if (unlikely(sg != &esp->sgbuf[0])) - kfree(sg); - } while (0); + if (err == -EBUSY) + err = NET_XMIT_DROP; + + kfree(tmp); + +error: + return err; +} + +static int esp_input_done2(struct sk_buff *skb, int err) +{ + struct xfrm_state *x = xfrm_input_state(skb); + struct esp_data *esp = x->data; + struct crypto_aead *aead = esp->aead; + int alen = crypto_aead_authsize(aead); + int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead); + int elen = skb->len - hlen; + int hdr_len = skb_network_header_len(skb); + int padlen; + u8 nexthdr[2]; + + kfree(ESP_SKB_CB(skb)->tmp); if (unlikely(err)) - goto unlock; + goto out; - if (esp->conf.ivlen) { - memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen); - crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen); - } + if (skb_copy_bits(skb, skb->len - alen - 2, nexthdr, 2)) + BUG(); - if (esp->auth.icv_full_len) { - err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data, - sizeof(*esph) + esp->conf.ivlen + clen); - memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen); + err = -EINVAL; + padlen = nexthdr[0]; + if (padlen + 2 + alen >= elen) { + LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage " + "padlen=%d, elen=%d\n", padlen + 2, elen - alen); + goto out; } -unlock: - spin_unlock_bh(&x->lock); + /* ... check padding bits here. Silly. :-) */ -error: + pskb_trim(skb, skb->len - alen - padlen - 2); + __skb_pull(skb, hlen); + skb_set_transport_header(skb, -hdr_len); + + err = nexthdr[1]; + + /* RFC4303: Drop dummy packets without any error */ + if (err == IPPROTO_NONE) + err = -EINVAL; + +out: return err; } +static void esp_input_done(struct crypto_async_request *base, int err) +{ + struct sk_buff *skb = base->data; + + xfrm_input_resume(skb, esp_input_done2(skb, err)); +} + static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) { - struct ipv6hdr *iph; struct ip_esp_hdr *esph; struct esp_data *esp = x->data; - struct crypto_blkcipher *tfm = esp->conf.tfm; - struct blkcipher_desc desc = { .tfm = tfm }; + struct crypto_aead *aead = esp->aead; + struct aead_request *req; struct sk_buff *trailer; - int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); - int alen = esp->auth.icv_trunc_len; - int elen = skb->len - sizeof(*esph) - esp->conf.ivlen - alen; - int hdr_len = skb_network_header_len(skb); + int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead); int nfrags; int ret = 0; + void *tmp; + u8 *iv; + struct scatterlist *sg; + struct scatterlist *asg; if (!pskb_may_pull(skb, sizeof(*esph))) { ret = -EINVAL; goto out; } - if (elen <= 0 || (elen & (blksize-1))) { + if (elen <= 0) { ret = -EINVAL; goto out; } @@ -170,86 +296,38 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) goto out; } - skb->ip_summed = CHECKSUM_NONE; - - spin_lock(&x->lock); - - /* If integrity check is required, do this. */ - if (esp->auth.icv_full_len) { - u8 sum[alen]; - - ret = esp_mac_digest(esp, skb, 0, skb->len - alen); - if (ret) - goto unlock; + ret = -ENOMEM; + tmp = esp_alloc_tmp(aead, nfrags + 1); + if (!tmp) + goto out; - if (skb_copy_bits(skb, skb->len - alen, sum, alen)) - BUG(); + ESP_SKB_CB(skb)->tmp = tmp; + iv = esp_tmp_iv(aead, tmp); + req = esp_tmp_req(aead, iv); + asg = esp_req_sg(aead, req); + sg = asg + 1; - if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { - ret = -EBADMSG; - goto unlock; - } - } + skb->ip_summed = CHECKSUM_NONE; esph = (struct ip_esp_hdr *)skb->data; - iph = ipv6_hdr(skb); /* Get ivec. This can be wrong, check against another impls. */ - if (esp->conf.ivlen) - crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen); - - { - struct scatterlist *sg = &esp->sgbuf[0]; - - if (unlikely(nfrags > ESP_NUM_FAST_SG)) { - sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); - if (!sg) { - ret = -ENOMEM; - goto unlock; - } - } - sg_init_table(sg, nfrags); - skb_to_sgvec(skb, sg, - sizeof(*esph) + esp->conf.ivlen, - elen); - ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen); - if (unlikely(sg != &esp->sgbuf[0])) - kfree(sg); - } + iv = esph->enc_data; -unlock: - spin_unlock(&x->lock); + sg_init_table(sg, nfrags); + skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen); + sg_init_one(asg, esph, sizeof(*esph)); - if (unlikely(ret)) - goto out; - - { - u8 nexthdr[2]; - u8 padlen; - - if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) - BUG(); - - padlen = nexthdr[0]; - if (padlen+2 >= elen) { - LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen); - ret = -EINVAL; - goto out; - } - /* ... check padding bits here. Silly. :-) */ + aead_request_set_callback(req, 0, esp_input_done, skb); + aead_request_set_crypt(req, sg, sg, elen, iv); + aead_request_set_assoc(req, asg, sizeof(*esph)); - /* RFC4303: Drop dummy packets without any error */ - if (nexthdr[1] == IPPROTO_NONE) { - ret = -EINVAL; - goto out; - } + ret = crypto_aead_decrypt(req); + if (ret == -EINPROGRESS) + goto out; - pskb_trim(skb, skb->len - alen - padlen - 2); - ret = nexthdr[1]; - } + ret = esp_input_done2(skb, ret); - __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen); - skb_set_transport_header(skb, -hdr_len); out: return ret; } @@ -257,11 +335,11 @@ out: static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) { struct esp_data *esp = x->data; - u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); - u32 align = max_t(u32, blksize, esp->conf.padlen); + u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4); + u32 align = max_t(u32, blksize, esp->padlen); u32 rem; - mtu -= x->props.header_len + esp->auth.icv_trunc_len; + mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); rem = mtu & (align - 1); mtu &= ~(align - 1); @@ -300,81 +378,146 @@ static void esp6_destroy(struct xfrm_state *x) if (!esp) return; - crypto_free_blkcipher(esp->conf.tfm); - esp->conf.tfm = NULL; - kfree(esp->conf.ivec); - esp->conf.ivec = NULL; - crypto_free_hash(esp->auth.tfm); - esp->auth.tfm = NULL; - kfree(esp->auth.work_icv); - esp->auth.work_icv = NULL; + crypto_free_aead(esp->aead); kfree(esp); } -static int esp6_init_state(struct xfrm_state *x) +static int esp_init_aead(struct xfrm_state *x) +{ + struct esp_data *esp = x->data; + struct crypto_aead *aead; + int err; + + aead = crypto_alloc_aead(x->aead->alg_name, 0, 0); + err = PTR_ERR(aead); + if (IS_ERR(aead)) + goto error; + + esp->aead = aead; + + err = crypto_aead_setkey(aead, x->aead->alg_key, + (x->aead->alg_key_len + 7) / 8); + if (err) + goto error; + + err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8); + if (err) + goto error; + +error: + return err; +} + +static int esp_init_authenc(struct xfrm_state *x) { - struct esp_data *esp = NULL; - struct crypto_blkcipher *tfm; + struct esp_data *esp = x->data; + struct crypto_aead *aead; + struct crypto_authenc_key_param *param; + struct rtattr *rta; + char *key; + char *p; + char authenc_name[CRYPTO_MAX_ALG_NAME]; + unsigned int keylen; + int err; + err = -EINVAL; if (x->ealg == NULL) goto error; - if (x->encap) + err = -ENAMETOOLONG; + if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", + x->aalg ? x->aalg->alg_name : "digest_null", + x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) goto error; - esp = kzalloc(sizeof(*esp), GFP_KERNEL); - if (esp == NULL) - return -ENOMEM; + aead = crypto_alloc_aead(authenc_name, 0, 0); + err = PTR_ERR(aead); + if (IS_ERR(aead)) + goto error; + + esp->aead = aead; + + keylen = (x->aalg ? (x->aalg->alg_key_len + 7) / 8 : 0) + + (x->ealg->alg_key_len + 7) / 8 + RTA_SPACE(sizeof(*param)); + err = -ENOMEM; + key = kmalloc(keylen, GFP_KERNEL); + if (!key) + goto error; + + p = key; + rta = (void *)p; + rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM; + rta->rta_len = RTA_LENGTH(sizeof(*param)); + param = RTA_DATA(rta); + p += RTA_SPACE(sizeof(*param)); if (x->aalg) { struct xfrm_algo_desc *aalg_desc; - struct crypto_hash *hash; - - hash = crypto_alloc_hash(x->aalg->alg_name, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(hash)) - goto error; - esp->auth.tfm = hash; - if (crypto_hash_setkey(hash, x->aalg->alg_key, - (x->aalg->alg_key_len + 7) / 8)) - goto error; + memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8); + p += (x->aalg->alg_key_len + 7) / 8; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); + err = -EINVAL; if (aalg_desc->uinfo.auth.icv_fullbits/8 != - crypto_hash_digestsize(hash)) { + crypto_aead_authsize(aead)) { NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", x->aalg->alg_name, - crypto_hash_digestsize(hash), + crypto_aead_authsize(aead), aalg_desc->uinfo.auth.icv_fullbits/8); - goto error; + goto free_key; } - esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; - esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; - - esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL); - if (!esp->auth.work_icv) - goto error; - } - tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - goto error; - esp->conf.tfm = tfm; - esp->conf.ivlen = crypto_blkcipher_ivsize(tfm); - esp->conf.padlen = 0; - if (esp->conf.ivlen) { - esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); - if (unlikely(esp->conf.ivec == NULL)) - goto error; - esp->conf.ivinitted = 0; + err = crypto_aead_setauthsize( + aead, aalg_desc->uinfo.auth.icv_truncbits / 8); + if (err) + goto free_key; } - if (crypto_blkcipher_setkey(tfm, x->ealg->alg_key, - (x->ealg->alg_key_len + 7) / 8)) + + param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); + memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8); + + err = crypto_aead_setkey(aead, key, keylen); + +free_key: + kfree(key); + +error: + return err; +} + +static int esp6_init_state(struct xfrm_state *x) +{ + struct esp_data *esp; + struct crypto_aead *aead; + u32 align; + int err; + + if (x->encap) + return -EINVAL; + + esp = kzalloc(sizeof(*esp), GFP_KERNEL); + if (esp == NULL) + return -ENOMEM; + + x->data = esp; + + if (x->aead) + err = esp_init_aead(x); + else + err = esp_init_authenc(x); + + if (err) goto error; - x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; + + aead = esp->aead; + + esp->padlen = 0; + + x->props.header_len = sizeof(struct ip_esp_hdr) + + crypto_aead_ivsize(aead); switch (x->props.mode) { case XFRM_MODE_BEET: case XFRM_MODE_TRANSPORT: @@ -385,17 +528,17 @@ static int esp6_init_state(struct xfrm_state *x) default: goto error; } - x->data = esp; - return 0; + + align = ALIGN(crypto_aead_blocksize(aead), 4); + if (esp->padlen) + align = max_t(u32, align, esp->padlen); + x->props.trailer_len = align + 1 + crypto_aead_authsize(esp->aead); error: - x->data = esp; - esp6_destroy(x); - x->data = NULL; - return -EINVAL; + return err; } -static struct xfrm_type esp6_type = +static const struct xfrm_type esp6_type = { .description = "ESP6", .owner = THIS_MODULE, diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index a66a7d8..d325a99 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -54,7 +54,8 @@ EXPORT_SYMBOL(__inet6_hash); * * The sockhash lock must be held as a reader here. */ -struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, +struct sock *__inet6_lookup_established(struct net *net, + struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, @@ -75,22 +76,13 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, read_lock(lock); sk_for_each(sk, node, &head->chain) { /* For IPV6 do the cheaper port and family tests first. */ - if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif)) + if (INET6_MATCH(sk, net, hash, saddr, daddr, ports, dif)) goto hit; /* You sunk my battleship! */ } /* Must check for a TIME_WAIT'er before going to listener hash. */ sk_for_each(sk, node, &head->twchain) { - const struct inet_timewait_sock *tw = inet_twsk(sk); - - if(*((__portpair *)&(tw->tw_dport)) == ports && - sk->sk_family == PF_INET6) { - const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); - - if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) && - ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) && - (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif)) - goto hit; - } + if (INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) + goto hit; } read_unlock(lock); return NULL; @@ -102,9 +94,9 @@ hit: } EXPORT_SYMBOL(__inet6_lookup_established); -struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, - const struct in6_addr *daddr, - const unsigned short hnum, const int dif) +struct sock *inet6_lookup_listener(struct net *net, + struct inet_hashinfo *hashinfo, const struct in6_addr *daddr, + const unsigned short hnum, const int dif) { struct sock *sk; const struct hlist_node *node; @@ -113,7 +105,8 @@ struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, read_lock(&hashinfo->lhash_lock); sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { - if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) { + if (sk->sk_net == net && inet_sk(sk)->num == hnum && + sk->sk_family == PF_INET6) { const struct ipv6_pinfo *np = inet6_sk(sk); score = 1; @@ -145,7 +138,7 @@ struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, EXPORT_SYMBOL_GPL(inet6_lookup_listener); -struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, +struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const __be16 dport, const int dif) @@ -153,7 +146,7 @@ struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, struct sock *sk; local_bh_disable(); - sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); + sk = __inet6_lookup(net, hashinfo, saddr, sport, daddr, ntohs(dport), dif); local_bh_enable(); return sk; @@ -179,21 +172,16 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; + struct net *net = sk->sk_net; prefetch(head->chain.first); write_lock(lock); /* Check TIME-WAIT sockets first. */ sk_for_each(sk2, node, &head->twchain) { - const struct inet6_timewait_sock *tw6 = inet6_twsk(sk2); - tw = inet_twsk(sk2); - if(*((__portpair *)&(tw->tw_dport)) == ports && - sk2->sk_family == PF_INET6 && - ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) && - ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) && - (!sk2->sk_bound_dev_if || sk2->sk_bound_dev_if == dif)) { + if (INET6_TW_MATCH(sk2, net, hash, saddr, daddr, ports, dif)) { if (twsk_unique(sk, sk2, twp)) goto unique; else @@ -204,7 +192,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, /* And established part... */ sk_for_each(sk2, node, &head->chain) { - if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif)) + if (INET6_MATCH(sk2, net, hash, saddr, daddr, ports, dif)) goto not_unique; } @@ -248,97 +236,8 @@ static inline u32 inet6_sk_port_offset(const struct sock *sk) int inet6_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk) { - struct inet_hashinfo *hinfo = death_row->hashinfo; - const unsigned short snum = inet_sk(sk)->num; - struct inet_bind_hashbucket *head; - struct inet_bind_bucket *tb; - int ret; - - if (snum == 0) { - int i, port, low, high, remaining; - static u32 hint; - const u32 offset = hint + inet6_sk_port_offset(sk); - struct hlist_node *node; - struct inet_timewait_sock *tw = NULL; - - inet_get_local_port_range(&low, &high); - remaining = (high - low) + 1; - - local_bh_disable(); - for (i = 1; i <= remaining; i++) { - port = low + (i + offset) % remaining; - head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; - spin_lock(&head->lock); - - /* Does not bother with rcv_saddr checks, - * because the established check is already - * unique enough. - */ - inet_bind_bucket_for_each(tb, node, &head->chain) { - if (tb->port == port) { - BUG_TRAP(!hlist_empty(&tb->owners)); - if (tb->fastreuse >= 0) - goto next_port; - if (!__inet6_check_established(death_row, - sk, port, - &tw)) - goto ok; - goto next_port; - } - } - - tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, - head, port); - if (!tb) { - spin_unlock(&head->lock); - break; - } - tb->fastreuse = -1; - goto ok; - - next_port: - spin_unlock(&head->lock); - } - local_bh_enable(); - - return -EADDRNOTAVAIL; - -ok: - hint += i; - - /* Head lock still held and bh's disabled */ - inet_bind_hash(sk, tb, port); - if (sk_unhashed(sk)) { - inet_sk(sk)->sport = htons(port); - __inet6_hash(hinfo, sk); - } - spin_unlock(&head->lock); - - if (tw) { - inet_twsk_deschedule(tw, death_row); - inet_twsk_put(tw); - } - - ret = 0; - goto out; - } - - head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)]; - tb = inet_csk(sk)->icsk_bind_hash; - spin_lock_bh(&head->lock); - - if (sk_head(&tb->owners) == sk && sk->sk_bind_node.next == NULL) { - __inet6_hash(hinfo, sk); - spin_unlock_bh(&head->lock); - return 0; - } else { - spin_unlock(&head->lock); - /* No definite answer... Walk to established hash table */ - ret = __inet6_check_established(death_row, sk, snum, NULL); -out: - local_bh_enable(); - return ret; - } + return __inet_hash_connect(death_row, sk, + __inet6_check_established, __inet6_hash); } EXPORT_SYMBOL_GPL(inet6_hash_connect); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 15c4f6c..9ac6ca2 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -257,6 +257,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ipv6_addr_copy(&hdr->daddr, first_hop); skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; mtu = dst_mtu(dst); if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { @@ -636,6 +637,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (skb_shinfo(skb)->frag_list) { int first_len = skb_pagelen(skb); + int truesizes = 0; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -658,7 +660,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) sock_hold(skb->sk); frag->sk = skb->sk; frag->destructor = sock_wfree; - skb->truesize -= frag->truesize; + truesizes += frag->truesize; } } @@ -689,6 +691,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) first_len = skb_pagelen(skb); skb->data_len = first_len - skb_headlen(skb); + skb->truesize -= truesizes; skb->len = first_len; ipv6_hdr(skb)->payload_len = htons(first_len - sizeof(struct ipv6hdr)); @@ -1437,6 +1440,7 @@ int ip6_push_pending_frames(struct sock *sk) ipv6_addr_copy(&hdr->daddr, final_dst); skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; skb->dst = dst_clone(&rt->u.dst); IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index b276d04..b900395 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -64,6 +64,7 @@ static LIST_HEAD(ipcomp6_tfms_list); static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) { + int nexthdr; int err = -ENOMEM; struct ip_comp_hdr *ipch; int plen, dlen; @@ -79,6 +80,8 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) /* Remove ipcomp header and decompress original payload */ ipch = (void *)skb->data; + nexthdr = ipch->nexthdr; + skb->transport_header = skb->network_header + sizeof(*ipch); __skb_pull(skb, sizeof(*ipch)); @@ -108,7 +111,7 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) skb->truesize += dlen - plen; __skb_put(skb, dlen - plen); skb_copy_to_linear_data(skb, scratch, dlen); - err = ipch->nexthdr; + err = nexthdr; out_put_cpu: put_cpu(); @@ -450,7 +453,7 @@ error: goto out; } -static struct xfrm_type ipcomp6_type = +static const struct xfrm_type ipcomp6_type = { .description = "IPCOMP6", .owner = THIS_MODULE, diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 49d3966..cd8a5bd 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -330,7 +330,7 @@ static void mip6_destopt_destroy(struct xfrm_state *x) { } -static struct xfrm_type mip6_destopt_type = +static const struct xfrm_type mip6_destopt_type = { .description = "MIP6DESTOPT", .owner = THIS_MODULE, @@ -462,7 +462,7 @@ static void mip6_rthdr_destroy(struct xfrm_state *x) { } -static struct xfrm_type mip6_rthdr_type = +static const struct xfrm_type mip6_rthdr_type = { .description = "MIP6RT", .owner = THIS_MODULE, diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 56b4ea6..e869916 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -515,6 +515,7 @@ static struct notifier_block ipq_nl_notifier = { .notifier_call = ipq_rcv_nl_event, }; +#ifdef CONFIG_SYSCTL static struct ctl_table_header *ipq_sysctl_header; static ctl_table ipq_table[] = { @@ -528,7 +529,9 @@ static ctl_table ipq_table[] = { }, { .ctl_name = 0 } }; +#endif +#ifdef CONFIG_PROC_FS static int ip6_queue_show(struct seq_file *m, void *v) { read_lock_bh(&queue_lock); @@ -565,6 +568,7 @@ static const struct file_operations ip6_queue_proc_fops = { .release = single_release, .owner = THIS_MODULE, }; +#endif static const struct nf_queue_handler nfqh = { .name = "ip6_queue", @@ -574,7 +578,7 @@ static const struct nf_queue_handler nfqh = { static int __init ip6_queue_init(void) { int status = -ENOMEM; - struct proc_dir_entry *proc; + struct proc_dir_entry *proc __maybe_unused; netlink_register_notifier(&ipq_nl_notifier); ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0, @@ -584,6 +588,7 @@ static int __init ip6_queue_init(void) goto cleanup_netlink_notifier; } +#ifdef CONFIG_PROC_FS proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); if (proc) { proc->owner = THIS_MODULE; @@ -592,10 +597,11 @@ static int __init ip6_queue_init(void) printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); goto cleanup_ipqnl; } - +#endif register_netdevice_notifier(&ipq_dev_notifier); +#ifdef CONFIG_SYSCTL ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table); - +#endif status = nf_register_queue_handler(PF_INET6, &nfqh); if (status < 0) { printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); @@ -604,11 +610,13 @@ static int __init ip6_queue_init(void) return status; cleanup_sysctl: +#ifdef CONFIG_SYSCTL unregister_sysctl_table(ipq_sysctl_header); +#endif unregister_netdevice_notifier(&ipq_dev_notifier); proc_net_remove(&init_net, IPQ_PROC_FS_NAME); -cleanup_ipqnl: +cleanup_ipqnl: __maybe_unused netlink_kernel_release(ipqnl); mutex_lock(&ipqnl_mutex); mutex_unlock(&ipqnl_mutex); @@ -624,7 +632,9 @@ static void __exit ip6_queue_fini(void) synchronize_net(); ipq_flush(NULL, 0); +#ifdef CONFIG_SYSCTL unregister_sysctl_table(ipq_sysctl_header); +#endif unregister_netdevice_notifier(&ipq_dev_notifier); proc_net_remove(&init_net, IPQ_PROC_FS_NAME); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index dd7860f..bf9bb6e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -320,7 +320,7 @@ static void trace_packet(struct sk_buff *skb, unsigned int hook, const struct net_device *in, const struct net_device *out, - char *tablename, + const char *tablename, struct xt_table_info *private, struct ip6t_entry *e) { @@ -1118,7 +1118,7 @@ static int compat_table_info(const struct xt_table_info *info, } #endif -static int get_info(void __user *user, int *len, int compat) +static int get_info(struct net *net, void __user *user, int *len, int compat) { char name[IP6T_TABLE_MAXNAMELEN]; struct xt_table *t; @@ -1138,7 +1138,7 @@ static int get_info(void __user *user, int *len, int compat) if (compat) xt_compat_lock(AF_INET6); #endif - t = try_then_request_module(xt_find_table_lock(AF_INET6, name), + t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name), "ip6table_%s", name); if (t && !IS_ERR(t)) { struct ip6t_getinfo info; @@ -1178,7 +1178,7 @@ static int get_info(void __user *user, int *len, int compat) } static int -get_entries(struct ip6t_get_entries __user *uptr, int *len) +get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len) { int ret; struct ip6t_get_entries get; @@ -1196,7 +1196,7 @@ get_entries(struct ip6t_get_entries __user *uptr, int *len) return -EINVAL; } - t = xt_find_table_lock(AF_INET6, get.name); + t = xt_find_table_lock(net, AF_INET6, get.name); if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", private->number); @@ -1217,7 +1217,7 @@ get_entries(struct ip6t_get_entries __user *uptr, int *len) } static int -__do_replace(const char *name, unsigned int valid_hooks, +__do_replace(struct net *net, const char *name, unsigned int valid_hooks, struct xt_table_info *newinfo, unsigned int num_counters, void __user *counters_ptr) { @@ -1235,7 +1235,7 @@ __do_replace(const char *name, unsigned int valid_hooks, goto out; } - t = try_then_request_module(xt_find_table_lock(AF_INET6, name), + t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name), "ip6table_%s", name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1288,7 +1288,7 @@ __do_replace(const char *name, unsigned int valid_hooks, } static int -do_replace(void __user *user, unsigned int len) +do_replace(struct net *net, void __user *user, unsigned int len) { int ret; struct ip6t_replace tmp; @@ -1322,7 +1322,7 @@ do_replace(void __user *user, unsigned int len) duprintf("ip_tables: Translated table\n"); - ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo, + ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, tmp.num_counters, tmp.counters); if (ret) goto free_newinfo_untrans; @@ -1358,7 +1358,8 @@ add_counter_to_entry(struct ip6t_entry *e, } static int -do_add_counters(void __user *user, unsigned int len, int compat) +do_add_counters(struct net *net, void __user *user, unsigned int len, + int compat) { unsigned int i; struct xt_counters_info tmp; @@ -1410,7 +1411,7 @@ do_add_counters(void __user *user, unsigned int len, int compat) goto free; } - t = xt_find_table_lock(AF_INET6, name); + t = xt_find_table_lock(net, AF_INET6, name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1456,7 +1457,7 @@ struct compat_ip6t_replace { static int compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, - compat_uint_t *size, struct xt_counters *counters, + unsigned int *size, struct xt_counters *counters, unsigned int *i) { struct ip6t_entry_target *t; @@ -1503,7 +1504,7 @@ compat_find_calc_match(struct ip6t_entry_match *m, const char *name, const struct ip6t_ip6 *ipv6, unsigned int hookmask, - int *size, int *i) + int *size, unsigned int *i) { struct xt_match *match; @@ -1561,7 +1562,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, struct ip6t_entry_target *t; struct xt_target *target; unsigned int entry_offset; - int ret, off, h, j; + unsigned int j; + int ret, off, h; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 @@ -1673,7 +1675,8 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, static int compat_check_entry(struct ip6t_entry *e, const char *name, unsigned int *i) { - int j, ret; + unsigned int j; + int ret; j = 0; ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, @@ -1815,7 +1818,7 @@ out_unlock: } static int -compat_do_replace(void __user *user, unsigned int len) +compat_do_replace(struct net *net, void __user *user, unsigned int len) { int ret; struct compat_ip6t_replace tmp; @@ -1852,7 +1855,7 @@ compat_do_replace(void __user *user, unsigned int len) duprintf("compat_do_replace: Translated table\n"); - ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo, + ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, tmp.num_counters, compat_ptr(tmp.counters)); if (ret) goto free_newinfo_untrans; @@ -1876,11 +1879,11 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, switch (cmd) { case IP6T_SO_SET_REPLACE: - ret = compat_do_replace(user, len); + ret = compat_do_replace(sk->sk_net, user, len); break; case IP6T_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 1); + ret = do_add_counters(sk->sk_net, user, len, 1); break; default: @@ -1929,7 +1932,8 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, } static int -compat_get_entries(struct compat_ip6t_get_entries __user *uptr, int *len) +compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr, + int *len) { int ret; struct compat_ip6t_get_entries get; @@ -1950,7 +1954,7 @@ compat_get_entries(struct compat_ip6t_get_entries __user *uptr, int *len) } xt_compat_lock(AF_INET6); - t = xt_find_table_lock(AF_INET6, get.name); + t = xt_find_table_lock(net, AF_INET6, get.name); if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; struct xt_table_info info; @@ -1986,10 +1990,10 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) switch (cmd) { case IP6T_SO_GET_INFO: - ret = get_info(user, len, 1); + ret = get_info(sk->sk_net, user, len, 1); break; case IP6T_SO_GET_ENTRIES: - ret = compat_get_entries(user, len); + ret = compat_get_entries(sk->sk_net, user, len); break; default: ret = do_ip6t_get_ctl(sk, cmd, user, len); @@ -2008,11 +2012,11 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) switch (cmd) { case IP6T_SO_SET_REPLACE: - ret = do_replace(user, len); + ret = do_replace(sk->sk_net, user, len); break; case IP6T_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 0); + ret = do_add_counters(sk->sk_net, user, len, 0); break; default: @@ -2033,11 +2037,11 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) switch (cmd) { case IP6T_SO_GET_INFO: - ret = get_info(user, len, 0); + ret = get_info(sk->sk_net, user, len, 0); break; case IP6T_SO_GET_ENTRIES: - ret = get_entries(user, len); + ret = get_entries(sk->sk_net, user, len); break; case IP6T_SO_GET_REVISION_MATCH: @@ -2074,17 +2078,21 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return ret; } -int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) +struct xt_table *ip6t_register_table(struct net *net, struct xt_table *table, + const struct ip6t_replace *repl) { int ret; struct xt_table_info *newinfo; struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; + struct xt_table *new_table; newinfo = xt_alloc_table_info(repl->size); - if (!newinfo) - return -ENOMEM; + if (!newinfo) { + ret = -ENOMEM; + goto out; + } /* choose the copy on our node/cpu, but dont care about preemption */ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; @@ -2095,30 +2103,35 @@ int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) repl->num_entries, repl->hook_entry, repl->underflow); - if (ret != 0) { - xt_free_table_info(newinfo); - return ret; - } + if (ret != 0) + goto out_free; - ret = xt_register_table(table, &bootstrap, newinfo); - if (ret != 0) { - xt_free_table_info(newinfo); - return ret; + new_table = xt_register_table(net, table, &bootstrap, newinfo); + if (IS_ERR(new_table)) { + ret = PTR_ERR(new_table); + goto out_free; } + return new_table; - return 0; +out_free: + xt_free_table_info(newinfo); +out: + return ERR_PTR(ret); } void ip6t_unregister_table(struct xt_table *table) { struct xt_table_info *private; void *loc_cpu_entry; + struct module *table_owner = table->me; private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + if (private->number > private->initial_entries) + module_put(table_owner); xt_free_table_info(private); } @@ -2225,11 +2238,26 @@ static struct xt_match icmp6_matchstruct __read_mostly = { .family = AF_INET6, }; +static int __net_init ip6_tables_net_init(struct net *net) +{ + return xt_proto_init(net, AF_INET6); +} + +static void __net_exit ip6_tables_net_exit(struct net *net) +{ + xt_proto_fini(net, AF_INET6); +} + +static struct pernet_operations ip6_tables_net_ops = { + .init = ip6_tables_net_init, + .exit = ip6_tables_net_exit, +}; + static int __init ip6_tables_init(void) { int ret; - ret = xt_proto_init(AF_INET6); + ret = register_pernet_subsys(&ip6_tables_net_ops); if (ret < 0) goto err1; @@ -2259,7 +2287,7 @@ err4: err3: xt_unregister_target(&ip6t_standard_target); err2: - xt_proto_fini(AF_INET6); + unregister_pernet_subsys(&ip6_tables_net_ops); err1: return ret; } @@ -2271,7 +2299,8 @@ static void __exit ip6_tables_fini(void) xt_unregister_match(&icmp6_matchstruct); xt_unregister_target(&ip6t_error_target); xt_unregister_target(&ip6t_standard_target); - xt_proto_fini(AF_INET6); + + unregister_pernet_subsys(&ip6_tables_net_ops); } /* diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 87d38d0..2d9cd09 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -26,7 +26,7 @@ static struct struct ip6t_replace repl; struct ip6t_standard entries[3]; struct ip6t_error term; -} initial_table __initdata = { +} initial_table __net_initdata = { .repl = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, @@ -67,7 +67,7 @@ ip6t_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(skb, hook, in, out, &packet_filter); + return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_filter); } static unsigned int @@ -87,7 +87,7 @@ ip6t_local_out_hook(unsigned int hook, } #endif - return ip6t_do_table(skb, hook, in, out, &packet_filter); + return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_filter); } static struct nf_hook_ops ip6t_ops[] __read_mostly = { @@ -118,6 +118,26 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { static int forward = NF_ACCEPT; module_param(forward, bool, 0000); +static int __net_init ip6table_filter_net_init(struct net *net) +{ + /* Register table */ + net->ipv6.ip6table_filter = + ip6t_register_table(net, &packet_filter, &initial_table.repl); + if (IS_ERR(net->ipv6.ip6table_filter)) + return PTR_ERR(net->ipv6.ip6table_filter); + return 0; +} + +static void __net_exit ip6table_filter_net_exit(struct net *net) +{ + ip6t_unregister_table(net->ipv6.ip6table_filter); +} + +static struct pernet_operations ip6table_filter_net_ops = { + .init = ip6table_filter_net_init, + .exit = ip6table_filter_net_exit, +}; + static int __init ip6table_filter_init(void) { int ret; @@ -130,8 +150,7 @@ static int __init ip6table_filter_init(void) /* Entry 1 is the FORWARD hook */ initial_table.entries[1].target.verdict = -forward - 1; - /* Register table */ - ret = ip6t_register_table(&packet_filter, &initial_table.repl); + ret = register_pernet_subsys(&ip6table_filter_net_ops); if (ret < 0) return ret; @@ -143,14 +162,14 @@ static int __init ip6table_filter_init(void) return ret; cleanup_table: - ip6t_unregister_table(&packet_filter); + unregister_pernet_subsys(&ip6table_filter_net_ops); return ret; } static void __exit ip6table_filter_fini(void) { nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); - ip6t_unregister_table(&packet_filter); + unregister_pernet_subsys(&ip6table_filter_net_ops); } module_init(ip6table_filter_init); diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index d608260..035343a 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -26,7 +26,7 @@ static struct struct ip6t_replace repl; struct ip6t_standard entries[5]; struct ip6t_error term; -} initial_table __initdata = { +} initial_table __net_initdata = { .repl = { .name = "mangle", .valid_hooks = MANGLE_VALID_HOOKS, @@ -73,7 +73,7 @@ ip6t_route_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(skb, hook, in, out, &packet_mangler); + return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_mangle); } static unsigned int @@ -108,7 +108,7 @@ ip6t_local_hook(unsigned int hook, /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u_int32_t *)ipv6_hdr(skb)); - ret = ip6t_do_table(skb, hook, in, out, &packet_mangler); + ret = ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_mangle); if (ret != NF_DROP && ret != NF_STOLEN && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) @@ -158,12 +158,31 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { }, }; +static int __net_init ip6table_mangle_net_init(struct net *net) +{ + /* Register table */ + net->ipv6.ip6table_mangle = + ip6t_register_table(net, &packet_mangler, &initial_table.repl); + if (IS_ERR(net->ipv6.ip6table_mangle)) + return PTR_ERR(net->ipv6.ip6table_mangle); + return 0; +} + +static void __net_exit ip6table_mangle_net_exit(struct net *net) +{ + ip6t_unregister_table(net->ipv6.ip6table_mangle); +} + +static struct pernet_operations ip6table_mangle_net_ops = { + .init = ip6table_mangle_net_init, + .exit = ip6table_mangle_net_exit, +}; + static int __init ip6table_mangle_init(void) { int ret; - /* Register table */ - ret = ip6t_register_table(&packet_mangler, &initial_table.repl); + ret = register_pernet_subsys(&ip6table_mangle_net_ops); if (ret < 0) return ret; @@ -175,14 +194,14 @@ static int __init ip6table_mangle_init(void) return ret; cleanup_table: - ip6t_unregister_table(&packet_mangler); + unregister_pernet_subsys(&ip6table_mangle_net_ops); return ret; } static void __exit ip6table_mangle_fini(void) { nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); - ip6t_unregister_table(&packet_mangler); + unregister_pernet_subsys(&ip6table_mangle_net_ops); } module_init(ip6table_mangle_init); diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index eccbaaa..5cd8420 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -13,7 +13,7 @@ static struct struct ip6t_replace repl; struct ip6t_standard entries[2]; struct ip6t_error term; -} initial_table __initdata = { +} initial_table __net_initdata = { .repl = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, @@ -51,7 +51,7 @@ ip6t_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(skb, hook, in, out, &packet_raw); + return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_raw); } static struct nf_hook_ops ip6t_ops[] __read_mostly = { @@ -71,12 +71,31 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { }, }; +static int __net_init ip6table_raw_net_init(struct net *net) +{ + /* Register table */ + net->ipv6.ip6table_raw = + ip6t_register_table(net, &packet_raw, &initial_table.repl); + if (IS_ERR(net->ipv6.ip6table_raw)) + return PTR_ERR(net->ipv6.ip6table_raw); + return 0; +} + +static void __net_exit ip6table_raw_net_exit(struct net *net) +{ + ip6t_unregister_table(net->ipv6.ip6table_raw); +} + +static struct pernet_operations ip6table_raw_net_ops = { + .init = ip6table_raw_net_init, + .exit = ip6table_raw_net_exit, +}; + static int __init ip6table_raw_init(void) { int ret; - /* Register table */ - ret = ip6t_register_table(&packet_raw, &initial_table.repl); + ret = register_pernet_subsys(&ip6table_raw_net_ops); if (ret < 0) return ret; @@ -88,14 +107,14 @@ static int __init ip6table_raw_init(void) return ret; cleanup_table: - ip6t_unregister_table(&packet_raw); + unregister_pernet_subsys(&ip6table_raw_net_ops); return ret; } static void __exit ip6table_raw_fini(void) { nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); - ip6t_unregister_table(&packet_raw); + unregister_pernet_subsys(&ip6table_raw_net_ops); } module_init(ip6table_raw_init); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 2d7b024..3717bdf 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -30,7 +30,8 @@ static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { - u_int32_t _addrs[8], *ap; + const u_int32_t *ap; + u_int32_t _addrs[8]; ap = skb_header_pointer(skb, nhoff + offsetof(struct ipv6hdr, saddr), sizeof(_addrs), _addrs); @@ -146,8 +147,8 @@ static unsigned int ipv6_confirm(unsigned int hooknum, int (*okfn)(struct sk_buff *)) { struct nf_conn *ct; - struct nf_conn_help *help; - struct nf_conntrack_helper *helper; + const struct nf_conn_help *help; + const struct nf_conntrack_helper *helper; enum ip_conntrack_info ctinfo; unsigned int ret, protoff; unsigned int extoff = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index da924c6..0897d0f 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -32,7 +32,8 @@ static int icmpv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { - struct icmp6hdr _hdr, *hp; + const struct icmp6hdr *hp; + struct icmp6hdr _hdr; hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); if (hp == NULL) @@ -45,7 +46,7 @@ static int icmpv6_pkt_to_tuple(const struct sk_buff *skb, } /* Add 1; spaces filled with 0. */ -static u_int8_t invmap[] = { +static const u_int8_t invmap[] = { [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1, [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1, [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1, @@ -101,24 +102,24 @@ static int icmpv6_packet(struct nf_conn *ct, } /* Called when a new connection for this protocol found. */ -static int icmpv6_new(struct nf_conn *conntrack, +static int icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { - static u_int8_t valid_new[] = { + static const u_int8_t valid_new[] = { [ICMPV6_ECHO_REQUEST - 128] = 1, [ICMPV6_NI_QUERY - 128] = 1 }; - int type = conntrack->tuplehash[0].tuple.dst.u.icmp.type - 128; + int type = ct->tuplehash[0].tuple.dst.u.icmp.type - 128; if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) { /* Can't create a new ICMPv6 `conn' with this. */ pr_debug("icmpv6: can't create new conn with type %u\n", type + 128); - NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); + NF_CT_DUMP_TUPLE(&ct->tuplehash[0].tuple); return 0; } - atomic_set(&conntrack->proto.icmp.count, 0); + atomic_set(&ct->proto.icmp.count, 0); return 1; } @@ -129,8 +130,8 @@ icmpv6_error_message(struct sk_buff *skb, unsigned int hooknum) { struct nf_conntrack_tuple intuple, origtuple; - struct nf_conntrack_tuple_hash *h; - struct nf_conntrack_l4proto *inproto; + const struct nf_conntrack_tuple_hash *h; + const struct nf_conntrack_l4proto *inproto; NF_CT_ASSERT(skb->nfct == NULL); @@ -176,7 +177,8 @@ static int icmpv6_error(struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum) { - struct icmp6hdr _ih, *icmp6h; + const struct icmp6hdr *icmp6h; + struct icmp6hdr _ih; icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); if (icmp6h == NULL) { diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 022da6c..2a0d698 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -39,6 +39,7 @@ #include <net/rawv6.h> #include <net/ndisc.h> #include <net/addrconf.h> +#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #include <linux/sysctl.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv6.h> @@ -680,21 +681,6 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, nf_conntrack_put_reasm(skb); } -int nf_ct_frag6_kfree_frags(struct sk_buff *skb) -{ - struct sk_buff *s, *s2; - - for (s = NFCT_FRAG6_CB(skb)->orig; s; s = s2) { - - s2 = s->next; - kfree_skb(s); - } - - kfree_skb(skb); - - return 0; -} - int nf_ct_frag6_init(void) { nf_frags.hashfn = nf_hashfn; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4d88055..8897ccf 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -641,6 +641,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, skb_reserve(skb, hh_len); skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; skb->dst = dst_clone(&rt->u.dst); skb_put(skb, length); @@ -767,6 +768,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, */ memset(&fl, 0, sizeof(fl)); + fl.mark = sk->sk_mark; + if (sin6) { if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; @@ -1259,7 +1262,7 @@ static const struct seq_operations raw6_seq_ops = { static int raw6_seq_open(struct inode *inode, struct file *file) { - return raw_seq_open(inode, file, &raw_v6_hashinfo, PF_INET6); + return raw_seq_open(inode, file, &raw_v6_hashinfo, &raw6_seq_ops); } static const struct file_operations raw6_seq_fops = { diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 4004c5f..513f72e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -107,6 +107,7 @@ static struct dst_ops ip6_dst_ops = { .update_pmtu = ip6_rt_update_pmtu, .local_out = ip6_local_out, .entry_size = sizeof(struct rt6_info), + .entries = ATOMIC_INIT(0), }; static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) @@ -120,6 +121,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { .check = ip6_dst_check, .update_pmtu = ip6_rt_blackhole_update_pmtu, .entry_size = sizeof(struct rt6_info), + .entries = ATOMIC_INIT(0), }; struct rt6_info ip6_null_entry = { @@ -1907,7 +1909,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) */ if (rt->rt6i_dev == arg->dev && !dst_metric_locked(&rt->u.dst, RTAX_MTU) && - (dst_mtu(&rt->u.dst) > arg->mtu || + (dst_mtu(&rt->u.dst) >= arg->mtu || (dst_mtu(&rt->u.dst) < arg->mtu && dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; @@ -1960,6 +1962,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; cfg->fc_nlinfo.nlh = nlh; + cfg->fc_nlinfo.nl_net = skb->sk->sk_net; if (tb[RTA_GATEWAY]) { nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 00c0839..59d0029 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -330,8 +330,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct tcp_sock *tp; __u32 seq; - sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr, - th->source, skb->dev->ifindex); + sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr, + th->dest, &hdr->saddr, th->source, skb->dev->ifindex); if (sk == NULL) { ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); @@ -1208,9 +1208,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) if (req) return tcp_check_req(sk, skb, req, prev); - nsk = __inet6_lookup_established(&tcp_hashinfo, &ipv6_hdr(skb)->saddr, - th->source, &ipv6_hdr(skb)->daddr, - ntohs(th->dest), inet6_iif(skb)); + nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo, + &ipv6_hdr(skb)->saddr, th->source, + &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); if (nsk) { if (nsk->sk_state != TCP_TIME_WAIT) { @@ -1710,9 +1710,10 @@ static int tcp_v6_rcv(struct sk_buff *skb) TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); TCP_SKB_CB(skb)->sacked = 0; - sk = __inet6_lookup(&tcp_hashinfo, &ipv6_hdr(skb)->saddr, th->source, - &ipv6_hdr(skb)->daddr, ntohs(th->dest), - inet6_iif(skb)); + sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, + &ipv6_hdr(skb)->saddr, th->source, + &ipv6_hdr(skb)->daddr, ntohs(th->dest), + inet6_iif(skb)); if (!sk) goto no_tcp_socket; @@ -1792,7 +1793,7 @@ do_time_wait: { struct sock *sk2; - sk2 = inet6_lookup_listener(&tcp_hashinfo, + sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo, &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); if (sk2 != NULL) { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index bd4b9df..53739de 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -56,7 +56,8 @@ static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) 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 net *net, + struct in6_addr *saddr, __be16 sport, struct in6_addr *daddr, __be16 dport, int dif, struct hlist_head udptable[]) { @@ -69,7 +70,8 @@ static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { struct inet_sock *inet = inet_sk(sk); - if (sk->sk_hash == hnum && sk->sk_family == PF_INET6) { + if (sk->sk_net == net && sk->sk_hash == hnum && + sk->sk_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); int score = 0; if (inet->dport) { @@ -233,7 +235,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct sock *sk; int err; - sk = __udp6_lib_lookup(daddr, uh->dest, + sk = __udp6_lib_lookup(skb->dev->nd_net, daddr, uh->dest, saddr, uh->source, inet6_iif(skb), udptable); if (sk == NULL) return; @@ -478,7 +480,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], * check socket cache ... must talk to Alan about his plans * for sock caches... i'll skip this for now. */ - sk = __udp6_lib_lookup(saddr, uh->source, + sk = __udp6_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr, uh->dest, inet6_iif(skb), udptable); if (sk == NULL) { diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index c25a6b5..7d20199 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -272,6 +272,7 @@ static struct dst_ops xfrm6_dst_ops = { .local_out = __ip6_local_out, .gc_thresh = 1024, .entry_size = sizeof(struct xfrm_dst), + .entries = ATOMIC_INIT(0), }; static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index fae90ff..639fe8a 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -319,7 +319,7 @@ static void xfrm6_tunnel_destroy(struct xfrm_state *x) xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); } -static struct xfrm_type xfrm6_tunnel_type = { +static const struct xfrm_type xfrm6_tunnel_type = { .description = "IP6IP6", .owner = THIS_MODULE, .proto = IPPROTO_IPV6, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 89e1e30..d44c872 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -340,9 +340,42 @@ static u32 ieee80211_rx_load_stats(struct ieee80211_local *local, return load; } +static ieee80211_txrx_result +ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx) +{ + int hdrlen; + + /* + * Drivers are required to align the payload data in a way that + * guarantees that the contained IP header is aligned to a four- + * byte boundary. In the case of regular frames, this simply means + * aligning the payload to a four-byte boundary (because either + * the IP header is directly contained, or IV/RFC1042 headers that + * have a length divisible by four are in front of it. + * + * With A-MSDU frames, however, the payload data address must + * yield two modulo four because there are 14-byte 802.3 headers + * within the A-MSDU frames that push the IP header further back + * to a multiple of four again. Thankfully, the specs were sane + * enough this time around to require padding each A-MSDU subframe + * to a length that is a multiple of four. + * + * Padding like atheros hardware adds which is inbetween the 802.11 + * header and the payload is not supported, the driver is required + * to move the 802.11 header further back in that case. + */ + hdrlen = ieee80211_get_hdrlen(rx->fc); + if (rx->flags & IEEE80211_TXRXD_RX_AMSDU) + hdrlen += ETH_HLEN; + WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); + + return TXRX_CONTINUE; +} + ieee80211_rx_handler ieee80211_rx_pre_handlers[] = { ieee80211_rx_h_parse_qos, + ieee80211_rx_h_verify_ip_alignment, NULL }; @@ -1679,7 +1712,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *prev = NULL; struct sk_buff *skb_new; u8 *bssid; - int hdrlen; hdr = (struct ieee80211_hdr *) skb->data; memset(&rx, 0, sizeof(rx)); @@ -1691,18 +1723,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, rx.fc = le16_to_cpu(hdr->frame_control); type = rx.fc & IEEE80211_FCTL_FTYPE; - /* - * Drivers are required to align the payload data to a four-byte - * boundary, so the last two bits of the address where it starts - * may not be set. The header is required to be directly before - * the payload data, padding like atheros hardware adds which is - * inbetween the 802.11 header and the payload is not supported, - * the driver is required to move the 802.11 header further back - * in that case. - */ - hdrlen = ieee80211_get_hdrlen(rx.fc); - WARN_ON_ONCE(((unsigned long)(skb->data + hdrlen)) & 3); - if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) local->dot11ReceivedFragmentCount++; @@ -1952,7 +1972,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, goto end_reorder; /* null data frames are excluded */ - if (unlikely(fc & IEEE80211_STYPE_QOS_NULLFUNC)) + if (unlikely(fc & IEEE80211_STYPE_NULLFUNC)) goto end_reorder; /* new un-ordered ampdu frame - process it */ diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 078fff0..327e847 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -40,7 +40,7 @@ #define NF_CONNTRACK_VERSION "0.5.0" -DEFINE_RWLOCK(nf_conntrack_lock); +DEFINE_SPINLOCK(nf_conntrack_lock); EXPORT_SYMBOL_GPL(nf_conntrack_lock); /* nf_conntrack_standalone needs this */ @@ -73,15 +73,19 @@ static unsigned int nf_conntrack_hash_rnd; static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, unsigned int size, unsigned int rnd) { - unsigned int a, b; - - a = jhash2(tuple->src.u3.all, ARRAY_SIZE(tuple->src.u3.all), - (tuple->src.l3num << 16) | tuple->dst.protonum); - b = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all), - ((__force __u16)tuple->src.u.all << 16) | - (__force __u16)tuple->dst.u.all); - - return ((u64)jhash_2words(a, b, rnd) * size) >> 32; + unsigned int n; + u_int32_t h; + + /* The direction must be ignored, so we hash everything up to the + * destination ports (which is a multiple of 4) and treat the last + * three bytes manually. + */ + n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32); + h = jhash2((u32 *)tuple, n, + rnd ^ (((__force __u16)tuple->dst.u.all << 16) | + tuple->dst.protonum)); + + return ((u64)h * size) >> 32; } static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple) @@ -166,8 +170,8 @@ static void clean_from_lists(struct nf_conn *ct) { pr_debug("clean_from_lists(%p)\n", ct); - hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); - hlist_del(&ct->tuplehash[IP_CT_DIR_REPLY].hnode); + hlist_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); + hlist_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnode); /* Destroy all pending expectations */ nf_ct_remove_expectations(ct); @@ -199,7 +203,7 @@ destroy_conntrack(struct nf_conntrack *nfct) rcu_read_unlock(); - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); /* Expectations will have been removed in clean_from_lists, * except TFTP can create an expectation on the first packet, * before connection is in the list, so we need to clean here, @@ -213,7 +217,7 @@ destroy_conntrack(struct nf_conntrack *nfct) } NF_CT_STAT_INC(delete); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); if (ct->master) nf_ct_put(ct->master); @@ -236,26 +240,24 @@ static void death_by_timeout(unsigned long ul_conntrack) rcu_read_unlock(); } - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); /* Inside lock so preempt is disabled on module removal path. * Otherwise we can get spurious warnings. */ NF_CT_STAT_INC(delete_list); clean_from_lists(ct); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); nf_ct_put(ct); } struct nf_conntrack_tuple_hash * -__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack) +__nf_conntrack_find(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; struct hlist_node *n; unsigned int hash = hash_conntrack(tuple); - hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) { - if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && - nf_ct_tuple_equal(tuple, &h->tuple)) { + hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) { + if (nf_ct_tuple_equal(tuple, &h->tuple)) { NF_CT_STAT_INC(found); return h; } @@ -271,12 +273,16 @@ struct nf_conntrack_tuple_hash * nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; + struct nf_conn *ct; - read_lock_bh(&nf_conntrack_lock); - h = __nf_conntrack_find(tuple, NULL); - if (h) - atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); - read_unlock_bh(&nf_conntrack_lock); + rcu_read_lock(); + h = __nf_conntrack_find(tuple); + if (h) { + ct = nf_ct_tuplehash_to_ctrack(h); + if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) + h = NULL; + } + rcu_read_unlock(); return h; } @@ -286,10 +292,10 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct, unsigned int hash, unsigned int repl_hash) { - hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, - &nf_conntrack_hash[hash]); - hlist_add_head(&ct->tuplehash[IP_CT_DIR_REPLY].hnode, - &nf_conntrack_hash[repl_hash]); + hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, + &nf_conntrack_hash[hash]); + hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnode, + &nf_conntrack_hash[repl_hash]); } void nf_conntrack_hash_insert(struct nf_conn *ct) @@ -299,9 +305,9 @@ void nf_conntrack_hash_insert(struct nf_conn *ct) hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); __nf_conntrack_hash_insert(ct, hash, repl_hash); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); } EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert); @@ -338,7 +344,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); pr_debug("Confirming conntrack %p\n", ct); - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); /* See if there's one in the list already, including reverse: NAT could have grabbed it without realizing, since we're @@ -364,7 +370,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) atomic_inc(&ct->ct_general.use); set_bit(IPS_CONFIRMED_BIT, &ct->status); NF_CT_STAT_INC(insert); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); help = nfct_help(ct); if (help && help->helper) nf_conntrack_event_cache(IPCT_HELPER, skb); @@ -379,7 +385,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) out: NF_CT_STAT_INC(insert_failed); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); return NF_DROP; } EXPORT_SYMBOL_GPL(__nf_conntrack_confirm); @@ -391,12 +397,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack) { struct nf_conntrack_tuple_hash *h; + struct hlist_node *n; + unsigned int hash = hash_conntrack(tuple); - read_lock_bh(&nf_conntrack_lock); - h = __nf_conntrack_find(tuple, ignored_conntrack); - read_unlock_bh(&nf_conntrack_lock); + rcu_read_lock(); + hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) { + if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && + nf_ct_tuple_equal(tuple, &h->tuple)) { + NF_CT_STAT_INC(found); + rcu_read_unlock(); + return 1; + } + NF_CT_STAT_INC(searched); + } + rcu_read_unlock(); - return h != NULL; + return 0; } EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); @@ -404,7 +420,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); /* There's a small race here where we may free a just-assured connection. Too bad: we're in trouble anyway. */ -static int early_drop(unsigned int hash) +static noinline int early_drop(unsigned int hash) { /* Use oldest entry, which is roughly LRU */ struct nf_conntrack_tuple_hash *h; @@ -413,21 +429,23 @@ static int early_drop(unsigned int hash) unsigned int i, cnt = 0; int dropped = 0; - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); for (i = 0; i < nf_conntrack_htable_size; i++) { - hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) { + hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], + hnode) { tmp = nf_ct_tuplehash_to_ctrack(h); if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) ct = tmp; cnt++; } + + if (ct && unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) + ct = NULL; if (ct || cnt >= NF_CT_EVICTION_RANGE) break; hash = (hash + 1) % nf_conntrack_htable_size; } - if (ct) - atomic_inc(&ct->ct_general.use); - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); if (!ct) return dropped; @@ -444,7 +462,7 @@ static int early_drop(unsigned int hash) struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, const struct nf_conntrack_tuple *repl) { - struct nf_conn *conntrack = NULL; + struct nf_conn *ct = NULL; if (unlikely(!nf_conntrack_hash_rnd_initted)) { get_random_bytes(&nf_conntrack_hash_rnd, 4); @@ -454,8 +472,8 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, /* We don't want any race condition at early drop stage */ atomic_inc(&nf_conntrack_count); - if (nf_conntrack_max - && atomic_read(&nf_conntrack_count) > nf_conntrack_max) { + if (nf_conntrack_max && + unlikely(atomic_read(&nf_conntrack_count) > nf_conntrack_max)) { unsigned int hash = hash_conntrack(orig); if (!early_drop(hash)) { atomic_dec(&nf_conntrack_count); @@ -467,30 +485,37 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, } } - conntrack = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC); - if (conntrack == NULL) { + ct = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC); + if (ct == NULL) { pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); atomic_dec(&nf_conntrack_count); return ERR_PTR(-ENOMEM); } - atomic_set(&conntrack->ct_general.use, 1); - conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; - conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; + atomic_set(&ct->ct_general.use, 1); + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; + ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; /* Don't set timer yet: wait for confirmation */ - setup_timer(&conntrack->timeout, death_by_timeout, - (unsigned long)conntrack); + setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); + INIT_RCU_HEAD(&ct->rcu); - return conntrack; + return ct; } EXPORT_SYMBOL_GPL(nf_conntrack_alloc); -void nf_conntrack_free(struct nf_conn *conntrack) +static void nf_conntrack_free_rcu(struct rcu_head *head) { - nf_ct_ext_free(conntrack); - kmem_cache_free(nf_conntrack_cachep, conntrack); + struct nf_conn *ct = container_of(head, struct nf_conn, rcu); + + nf_ct_ext_free(ct); + kmem_cache_free(nf_conntrack_cachep, ct); atomic_dec(&nf_conntrack_count); } + +void nf_conntrack_free(struct nf_conn *ct) +{ + call_rcu(&ct->rcu, nf_conntrack_free_rcu); +} EXPORT_SYMBOL_GPL(nf_conntrack_free); /* Allocate a new conntrack: we return -ENOMEM if classification @@ -502,7 +527,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, struct sk_buff *skb, unsigned int dataoff) { - struct nf_conn *conntrack; + struct nf_conn *ct; struct nf_conn_help *help; struct nf_conntrack_tuple repl_tuple; struct nf_conntrack_expect *exp; @@ -512,46 +537,46 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, return NULL; } - conntrack = nf_conntrack_alloc(tuple, &repl_tuple); - if (conntrack == NULL || IS_ERR(conntrack)) { + ct = nf_conntrack_alloc(tuple, &repl_tuple); + if (ct == NULL || IS_ERR(ct)) { pr_debug("Can't allocate conntrack.\n"); - return (struct nf_conntrack_tuple_hash *)conntrack; + return (struct nf_conntrack_tuple_hash *)ct; } - if (!l4proto->new(conntrack, skb, dataoff)) { - nf_conntrack_free(conntrack); + if (!l4proto->new(ct, skb, dataoff)) { + nf_conntrack_free(ct); pr_debug("init conntrack: can't track with proto module\n"); return NULL; } - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); exp = nf_ct_find_expectation(tuple); if (exp) { pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", - conntrack, exp); + ct, exp); /* Welcome, Mr. Bond. We've been expecting you... */ - __set_bit(IPS_EXPECTED_BIT, &conntrack->status); - conntrack->master = exp->master; + __set_bit(IPS_EXPECTED_BIT, &ct->status); + ct->master = exp->master; if (exp->helper) { - help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC); + help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); if (help) rcu_assign_pointer(help->helper, exp->helper); } #ifdef CONFIG_NF_CONNTRACK_MARK - conntrack->mark = exp->master->mark; + ct->mark = exp->master->mark; #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK - conntrack->secmark = exp->master->secmark; + ct->secmark = exp->master->secmark; #endif - nf_conntrack_get(&conntrack->master->ct_general); + nf_conntrack_get(&ct->master->ct_general); NF_CT_STAT_INC(expect_new); } else { struct nf_conntrack_helper *helper; helper = __nf_ct_helper_find(&repl_tuple); if (helper) { - help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC); + help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); if (help) rcu_assign_pointer(help->helper, helper); } @@ -559,18 +584,17 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, } /* Overload tuple linked list to put us in unconfirmed list. */ - hlist_add_head(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].hnode, - &unconfirmed); + hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, &unconfirmed); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); if (exp) { if (exp->expectfn) - exp->expectfn(conntrack, exp); + exp->expectfn(ct, exp); nf_ct_expect_put(exp); } - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL]; + return &ct->tuplehash[IP_CT_DIR_ORIGINAL]; } /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */ @@ -729,7 +753,6 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, struct nf_conn_help *help = nfct_help(ct); struct nf_conntrack_helper *helper; - write_lock_bh(&nf_conntrack_lock); /* Should be unconfirmed, so not in hash table yet */ NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); @@ -738,8 +761,9 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; if (ct->master || (help && help->expecting != 0)) - goto out; + return; + rcu_read_lock(); helper = __nf_ct_helper_find(newreply); if (helper == NULL) { if (help) @@ -757,7 +781,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, rcu_assign_pointer(help->helper, helper); out: - write_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); @@ -773,13 +797,11 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); NF_CT_ASSERT(skb); - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); /* Only update if this is not a fixed timeout */ - if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { - write_unlock_bh(&nf_conntrack_lock); - return; - } + if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) + goto acct; /* If not in hash table, timer will not be active yet */ if (!nf_ct_is_confirmed(ct)) { @@ -799,6 +821,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, } } +acct: #ifdef CONFIG_NF_CT_ACCT if (do_acct) { ct->counters[CTINFO2DIR(ctinfo)].packets++; @@ -811,7 +834,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, } #endif - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); /* must be unlocked when calling event cache */ if (event) @@ -879,14 +902,6 @@ static void nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb) nf_conntrack_get(nskb->nfct); } -static inline int -do_iter(const struct nf_conntrack_tuple_hash *i, - int (*iter)(struct nf_conn *i, void *data), - void *data) -{ - return iter(nf_ct_tuplehash_to_ctrack(i), data); -} - /* Bring out ya dead! */ static struct nf_conn * get_next_corpse(int (*iter)(struct nf_conn *i, void *data), @@ -896,7 +911,7 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), struct nf_conn *ct; struct hlist_node *n; - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { hlist_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnode) { ct = nf_ct_tuplehash_to_ctrack(h); @@ -909,11 +924,11 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), if (iter(ct, data)) set_bit(IPS_DYING_BIT, &ct->status); } - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); return NULL; found: atomic_inc(&ct->ct_general.use); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); return ct; } @@ -939,7 +954,7 @@ static int kill_all(struct nf_conn *i, void *data) return 1; } -void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, int size) +void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, unsigned int size) { if (vmalloced) vfree(hash); @@ -988,7 +1003,7 @@ void nf_conntrack_cleanup(void) nf_conntrack_expect_fini(); } -struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced) +struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) { struct hlist_head *hash; unsigned int size, i; @@ -1015,8 +1030,8 @@ EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable); int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) { - int i, bucket, hashsize, vmalloced; - int old_vmalloced, old_size; + int i, bucket, vmalloced, old_vmalloced; + unsigned int hashsize, old_size; int rnd; struct hlist_head *hash, *old_hash; struct nf_conntrack_tuple_hash *h; @@ -1025,7 +1040,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) if (!nf_conntrack_htable_size) return param_set_uint(val, kp); - hashsize = simple_strtol(val, NULL, 0); + hashsize = simple_strtoul(val, NULL, 0); if (!hashsize) return -EINVAL; @@ -1037,12 +1052,17 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) * use a newrandom seed */ get_random_bytes(&rnd, 4); - write_lock_bh(&nf_conntrack_lock); + /* Lookups in the old hash might happen in parallel, which means we + * might get false negatives during connection lookup. New connections + * created because of a false negative won't make it into the hash + * though since that required taking the lock. + */ + spin_lock_bh(&nf_conntrack_lock); for (i = 0; i < nf_conntrack_htable_size; i++) { while (!hlist_empty(&nf_conntrack_hash[i])) { h = hlist_entry(nf_conntrack_hash[i].first, struct nf_conntrack_tuple_hash, hnode); - hlist_del(&h->hnode); + hlist_del_rcu(&h->hnode); bucket = __hash_conntrack(&h->tuple, hashsize, rnd); hlist_add_head(&h->hnode, &hash[bucket]); } @@ -1055,7 +1075,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) nf_conntrack_vmalloc = vmalloced; nf_conntrack_hash = hash; nf_conntrack_hash_rnd = rnd; - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); nf_ct_free_hashtable(old_hash, old_vmalloced, old_size); return 0; diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index e0cd9d0..e06bf00 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -50,7 +50,7 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) NF_CT_ASSERT(master_help); NF_CT_ASSERT(!timer_pending(&exp->timeout)); - hlist_del(&exp->hnode); + hlist_del_rcu(&exp->hnode); nf_ct_expect_count--; hlist_del(&exp->lnode); @@ -65,9 +65,9 @@ static void nf_ct_expectation_timed_out(unsigned long ul_expect) { struct nf_conntrack_expect *exp = (void *)ul_expect; - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); nf_ct_unlink_expect(exp); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); nf_ct_expect_put(exp); } @@ -97,7 +97,7 @@ __nf_ct_expect_find(const struct nf_conntrack_tuple *tuple) return NULL; h = nf_ct_expect_dst_hash(tuple); - hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) { + hlist_for_each_entry_rcu(i, n, &nf_ct_expect_hash[h], hnode) { if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) return i; } @@ -111,11 +111,11 @@ nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i; - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); i = __nf_ct_expect_find(tuple); - if (i) - atomic_inc(&i->use); - read_unlock_bh(&nf_conntrack_lock); + if (i && !atomic_inc_not_zero(&i->use)) + i = NULL; + rcu_read_unlock(); return i; } @@ -201,12 +201,12 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, /* Generally a bad idea to call this: could have matched already. */ void nf_ct_unexpect_related(struct nf_conntrack_expect *exp) { - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); if (del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_ct_expect_put(exp); } - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); } EXPORT_SYMBOL_GPL(nf_ct_unexpect_related); @@ -223,6 +223,7 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me) new->master = me; atomic_set(&new->use, 1); + INIT_RCU_HEAD(&new->rcu); return new; } EXPORT_SYMBOL_GPL(nf_ct_expect_alloc); @@ -278,10 +279,18 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family, } EXPORT_SYMBOL_GPL(nf_ct_expect_init); +static void nf_ct_expect_free_rcu(struct rcu_head *head) +{ + struct nf_conntrack_expect *exp; + + exp = container_of(head, struct nf_conntrack_expect, rcu); + kmem_cache_free(nf_ct_expect_cachep, exp); +} + void nf_ct_expect_put(struct nf_conntrack_expect *exp) { if (atomic_dec_and_test(&exp->use)) - kmem_cache_free(nf_ct_expect_cachep, exp); + call_rcu(&exp->rcu, nf_ct_expect_free_rcu); } EXPORT_SYMBOL_GPL(nf_ct_expect_put); @@ -295,7 +304,7 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) hlist_add_head(&exp->lnode, &master_help->expectations); master_help->expecting++; - hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]); + hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]); nf_ct_expect_count++; setup_timer(&exp->timeout, nf_ct_expectation_timed_out, @@ -346,7 +355,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect) NF_CT_ASSERT(master_help); - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); if (!master_help->helper) { ret = -ESHUTDOWN; goto out; @@ -381,7 +390,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect) nf_ct_expect_event(IPEXP_NEW, expect); ret = 0; out: - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); return ret; } EXPORT_SYMBOL_GPL(nf_ct_expect_related); @@ -394,10 +403,12 @@ struct ct_expect_iter_state { static struct hlist_node *ct_expect_get_first(struct seq_file *seq) { struct ct_expect_iter_state *st = seq->private; + struct hlist_node *n; for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { - if (!hlist_empty(&nf_ct_expect_hash[st->bucket])) - return nf_ct_expect_hash[st->bucket].first; + n = rcu_dereference(nf_ct_expect_hash[st->bucket].first); + if (n) + return n; } return NULL; } @@ -407,11 +418,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq, { struct ct_expect_iter_state *st = seq->private; - head = head->next; + head = rcu_dereference(head->next); while (head == NULL) { if (++st->bucket >= nf_ct_expect_hsize) return NULL; - head = nf_ct_expect_hash[st->bucket].first; + head = rcu_dereference(nf_ct_expect_hash[st->bucket].first); } return head; } @@ -427,8 +438,9 @@ static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos) } static void *exp_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) { - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); return ct_expect_get_idx(seq, *pos); } @@ -439,8 +451,9 @@ static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void exp_seq_stop(struct seq_file *seq, void *v) + __releases(RCU) { - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); } static int exp_seq_show(struct seq_file *s, void *v) diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c index ff66fba..8678823 100644 --- a/net/netfilter/nf_conntrack_h323_asn1.c +++ b/net/netfilter/nf_conntrack_h323_asn1.c @@ -87,7 +87,7 @@ typedef struct field_t { unsigned char ub; unsigned short attr; unsigned short offset; - struct field_t *fields; + const struct field_t *fields; } field_t; /* Bit Stream */ @@ -96,7 +96,7 @@ typedef struct { unsigned char *beg; unsigned char *end; unsigned char *cur; - unsigned bit; + unsigned int bit; } bitstr_t; /* Tool Functions */ @@ -104,29 +104,29 @@ typedef struct { #define INC_BITS(bs,b) if(((bs)->bit+=(b))>7){(bs)->cur+=(bs)->bit>>3;(bs)->bit&=7;} #define BYTE_ALIGN(bs) if((bs)->bit){(bs)->cur++;(bs)->bit=0;} #define CHECK_BOUND(bs,n) if((bs)->cur+(n)>(bs)->end)return(H323_ERROR_BOUND) -static unsigned get_len(bitstr_t * bs); -static unsigned get_bit(bitstr_t * bs); -static unsigned get_bits(bitstr_t * bs, unsigned b); -static unsigned get_bitmap(bitstr_t * bs, unsigned b); -static unsigned get_uint(bitstr_t * bs, int b); +static unsigned int get_len(bitstr_t *bs); +static unsigned int get_bit(bitstr_t *bs); +static unsigned int get_bits(bitstr_t *bs, unsigned int b); +static unsigned int get_bitmap(bitstr_t *bs, unsigned int b); +static unsigned int get_uint(bitstr_t *bs, int b); /* Decoder Functions */ -static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_int(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_nul(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_bool(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_oid(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_int(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_enum(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_bitstr(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_numstr(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_octstr(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_bmpstr(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_seq(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_seqof(bitstr_t *bs, const struct field_t *f, char *base, int level); +static int decode_choice(bitstr_t *bs, const struct field_t *f, char *base, int level); /* Decoder Functions Vector */ -typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int); -static decoder_t Decoders[] = { +typedef int (*decoder_t)(bitstr_t *, const struct field_t *, char *, int); +static const decoder_t Decoders[] = { decode_nul, decode_bool, decode_oid, @@ -150,9 +150,9 @@ static decoder_t Decoders[] = { * Functions ****************************************************************************/ /* Assume bs is aligned && v < 16384 */ -unsigned get_len(bitstr_t * bs) +static unsigned int get_len(bitstr_t *bs) { - unsigned v; + unsigned int v; v = *bs->cur++; @@ -166,9 +166,9 @@ unsigned get_len(bitstr_t * bs) } /****************************************************************************/ -unsigned get_bit(bitstr_t * bs) +static unsigned int get_bit(bitstr_t *bs) { - unsigned b = (*bs->cur) & (0x80 >> bs->bit); + unsigned int b = (*bs->cur) & (0x80 >> bs->bit); INC_BIT(bs); @@ -177,9 +177,9 @@ unsigned get_bit(bitstr_t * bs) /****************************************************************************/ /* Assume b <= 8 */ -unsigned get_bits(bitstr_t * bs, unsigned b) +static unsigned int get_bits(bitstr_t *bs, unsigned int b) { - unsigned v, l; + unsigned int v, l; v = (*bs->cur) & (0xffU >> bs->bit); l = b + bs->bit; @@ -203,9 +203,9 @@ unsigned get_bits(bitstr_t * bs, unsigned b) /****************************************************************************/ /* Assume b <= 32 */ -unsigned get_bitmap(bitstr_t * bs, unsigned b) +static unsigned int get_bitmap(bitstr_t *bs, unsigned int b) { - unsigned v, l, shift, bytes; + unsigned int v, l, shift, bytes; if (!b) return 0; @@ -213,18 +213,18 @@ unsigned get_bitmap(bitstr_t * bs, unsigned b) l = bs->bit + b; if (l < 8) { - v = (unsigned) (*bs->cur) << (bs->bit + 24); + v = (unsigned int)(*bs->cur) << (bs->bit + 24); bs->bit = l; } else if (l == 8) { - v = (unsigned) (*bs->cur++) << (bs->bit + 24); + v = (unsigned int)(*bs->cur++) << (bs->bit + 24); bs->bit = 0; } else { for (bytes = l >> 3, shift = 24, v = 0; bytes; bytes--, shift -= 8) - v |= (unsigned) (*bs->cur++) << shift; + v |= (unsigned int)(*bs->cur++) << shift; if (l < 32) { - v |= (unsigned) (*bs->cur) << shift; + v |= (unsigned int)(*bs->cur) << shift; v <<= bs->bit; } else if (l > 32) { v <<= bs->bit; @@ -242,9 +242,9 @@ unsigned get_bitmap(bitstr_t * bs, unsigned b) /**************************************************************************** * Assume bs is aligned and sizeof(unsigned int) == 4 ****************************************************************************/ -unsigned get_uint(bitstr_t * bs, int b) +static unsigned int get_uint(bitstr_t *bs, int b) { - unsigned v = 0; + unsigned int v = 0; switch (b) { case 4: @@ -264,7 +264,8 @@ unsigned get_uint(bitstr_t * bs, int b) } /****************************************************************************/ -int decode_nul(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_nul(bitstr_t *bs, const struct field_t *f, + char *base, int level) { PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -272,7 +273,8 @@ int decode_nul(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_bool(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_bool(bitstr_t *bs, const struct field_t *f, + char *base, int level) { PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -283,7 +285,8 @@ int decode_bool(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_oid(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_oid(bitstr_t *bs, const struct field_t *f, + char *base, int level) { int len; @@ -299,9 +302,10 @@ int decode_oid(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_int(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_int(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned len; + unsigned int len; PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); @@ -318,9 +322,9 @@ int decode_int(bitstr_t * bs, field_t * f, char *base, int level) len = get_bits(bs, 2) + 1; BYTE_ALIGN(bs); if (base && (f->attr & DECODE)) { /* timeToLive */ - unsigned v = get_uint(bs, len) + f->lb; + unsigned int v = get_uint(bs, len) + f->lb; PRINT(" = %u", v); - *((unsigned *) (base + f->offset)) = v; + *((unsigned int *)(base + f->offset)) = v; } bs->cur += len; break; @@ -342,7 +346,8 @@ int decode_int(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_enum(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_enum(bitstr_t *bs, const struct field_t *f, + char *base, int level) { PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -357,9 +362,10 @@ int decode_enum(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_bitstr(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned len; + unsigned int len; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -390,9 +396,10 @@ int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_numstr(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned len; + unsigned int len; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -407,9 +414,10 @@ int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_octstr(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned len; + unsigned int len; PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); @@ -424,7 +432,7 @@ int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level) bs->cur[0], bs->cur[1], bs->cur[2], bs->cur[3], bs->cur[4] * 256 + bs->cur[5])); - *((unsigned *) (base + f->offset)) = + *((unsigned int *)(base + f->offset)) = bs->cur - bs->buf; } } @@ -455,9 +463,10 @@ int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_bmpstr(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned len; + unsigned int len; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -480,11 +489,12 @@ int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_seq(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len; + unsigned int ext, bmp, i, opt, len = 0, bmp2, bmp2_len; int err; - field_t *son; + const struct field_t *son; unsigned char *beg = NULL; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -498,7 +508,7 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) /* Get fields bitmap */ bmp = get_bitmap(bs, f->sz); if (base) - *(unsigned *) base = bmp; + *(unsigned int *)base = bmp; /* Decode the root components */ for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) { @@ -550,7 +560,7 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) bmp2 = get_bitmap(bs, bmp2_len); bmp |= bmp2 >> f->sz; if (base) - *(unsigned *) base = bmp; + *(unsigned int *)base = bmp; BYTE_ALIGN(bs); /* Decode the extension components */ @@ -596,11 +606,12 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_seqof(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned count, effective_count = 0, i, len = 0; + unsigned int count, effective_count = 0, i, len = 0; int err; - field_t *son; + const struct field_t *son; unsigned char *beg = NULL; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -636,8 +647,8 @@ int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level) /* Write Count */ if (base) { effective_count = count > f->ub ? f->ub : count; - *(unsigned *) base = effective_count; - base += sizeof(unsigned); + *(unsigned int *)base = effective_count; + base += sizeof(unsigned int); } /* Decode nested field */ @@ -685,11 +696,12 @@ int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level) /****************************************************************************/ -int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) +static int decode_choice(bitstr_t *bs, const struct field_t *f, + char *base, int level) { - unsigned type, ext, len = 0; + unsigned int type, ext, len = 0; int err; - field_t *son; + const struct field_t *son; unsigned char *beg = NULL; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); @@ -710,7 +722,7 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) /* Write Type */ if (base) - *(unsigned *) base = type; + *(unsigned int *)base = type; /* Check Range */ if (type >= f->ub) { /* Newer version? */ @@ -754,9 +766,9 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) } /****************************************************************************/ -int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras) +int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage *ras) { - static field_t ras_message = { + static const struct field_t ras_message = { FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT, 0, _RasMessage }; @@ -771,9 +783,9 @@ int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras) /****************************************************************************/ static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg, - size_t sz, H323_UserInformation * uuie) + size_t sz, H323_UserInformation *uuie) { - static field_t h323_userinformation = { + static const struct field_t h323_userinformation = { FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT, 0, _H323_UserInformation }; @@ -792,7 +804,7 @@ int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, MultimediaSystemControlMessage * mscm) { - static field_t multimediasystemcontrolmessage = { + static const struct field_t multimediasystemcontrolmessage = { FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4, DECODE | EXT, 0, _MultimediaSystemControlMessage }; @@ -807,7 +819,7 @@ int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, } /****************************************************************************/ -int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931) +int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931) { unsigned char *p = buf; int len; diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 872c1aa..6213787 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -114,7 +114,8 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, { struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); - struct tcphdr _tcph, *th; + const struct tcphdr *th; + struct tcphdr _tcph; int tcpdatalen; int tcpdataoff; unsigned char *tpkt; @@ -212,11 +213,11 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, } /****************************************************************************/ -static int get_h245_addr(struct nf_conn *ct, unsigned char *data, +static int get_h245_addr(struct nf_conn *ct, const unsigned char *data, H245_TransportAddress *taddr, union nf_inet_addr *addr, __be16 *port) { - unsigned char *p; + const unsigned char *p; int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; int len; @@ -625,7 +626,7 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data, TransportAddress *taddr, union nf_inet_addr *addr, __be16 *port) { - unsigned char *p; + const unsigned char *p; int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; int len; @@ -704,9 +705,8 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, /* If the calling party is on the same side of the forward-to party, * we don't need to track the second call */ -static int callforward_do_filter(union nf_inet_addr *src, - union nf_inet_addr *dst, - int family) +static int callforward_do_filter(const union nf_inet_addr *src, + const union nf_inet_addr *dst, int family) { const struct nf_afinfo *afinfo; struct flowi fl1, fl2; @@ -1185,7 +1185,8 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff, int *datalen) { - struct udphdr _uh, *uh; + const struct udphdr *uh; + struct udphdr _uh; int dataoff; uh = skb_header_pointer(skb, protoff, sizeof(_uh), &_uh); @@ -1415,7 +1416,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, nf_ct_refresh(ct, skb, info->timeout * HZ); /* Set expect timeout */ - read_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3, info->sig_port[!dir]); if (exp) { @@ -1425,7 +1426,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, NF_CT_DUMP_TUPLE(&exp->tuple); set_expect_timeout(exp, info->timeout); } - read_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); } return 0; @@ -1468,7 +1469,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, AdmissionRequest *arq) { - struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); __be16 port; union nf_inet_addr addr; diff --git a/net/netfilter/nf_conntrack_h323_types.c b/net/netfilter/nf_conntrack_h323_types.c index 3a21fdf..d880f35 100644 --- a/net/netfilter/nf_conntrack_h323_types.c +++ b/net/netfilter/nf_conntrack_h323_types.c @@ -5,22 +5,22 @@ * This source code is licensed under General Public License version 2. */ -static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */ +static const struct field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */ {FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE, offsetof(TransportAddress_ipAddress, ip), NULL}, {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */ +static const struct field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */ {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, }; -static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */ +static const struct field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */ {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */ +static const struct field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */ {FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0, @@ -29,37 +29,37 @@ static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */ _TransportAddress_ipSourceRoute_routing}, }; -static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */ +static const struct field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */ {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, {FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, }; -static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */ +static const struct field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */ {FNAME("ip") OCTSTR, FIXD, 16, 0, DECODE, offsetof(TransportAddress_ip6Address, ip), NULL}, {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _H221NonStandard[] = { /* SEQUENCE */ +static const struct field_t _H221NonStandard[] = { /* SEQUENCE */ {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _NonStandardIdentifier[] = { /* CHOICE */ +static const struct field_t _NonStandardIdentifier[] = { /* CHOICE */ {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard}, }; -static field_t _NonStandardParameter[] = { /* SEQUENCE */ +static const struct field_t _NonStandardParameter[] = { /* SEQUENCE */ {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0, _NonStandardIdentifier}, {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _TransportAddress[] = { /* CHOICE */ +static const struct field_t _TransportAddress[] = { /* CHOICE */ {FNAME("ipAddress") SEQ, 0, 2, 2, DECODE, offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress}, {FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0, @@ -75,7 +75,7 @@ static field_t _TransportAddress[] = { /* CHOICE */ _NonStandardParameter}, }; -static field_t _AliasAddress[] = { /* CHOICE */ +static const struct field_t _AliasAddress[] = { /* CHOICE */ {FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, {FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL}, {FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL}, @@ -85,78 +85,78 @@ static field_t _AliasAddress[] = { /* CHOICE */ {FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL}, }; -static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */ +static const struct field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _VendorIdentifier[] = { /* SEQUENCE */ +static const struct field_t _VendorIdentifier[] = { /* SEQUENCE */ {FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard}, {FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, {FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, }; -static field_t _GatekeeperInfo[] = { /* SEQUENCE */ +static const struct field_t _GatekeeperInfo[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, }; -static field_t _H310Caps[] = { /* SEQUENCE */ +static const struct field_t _H310Caps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _H320Caps[] = { /* SEQUENCE */ +static const struct field_t _H320Caps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _H321Caps[] = { /* SEQUENCE */ +static const struct field_t _H321Caps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _H322Caps[] = { /* SEQUENCE */ +static const struct field_t _H322Caps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _H323Caps[] = { /* SEQUENCE */ +static const struct field_t _H323Caps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _H324Caps[] = { /* SEQUENCE */ +static const struct field_t _H324Caps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _VoiceCaps[] = { /* SEQUENCE */ +static const struct field_t _VoiceCaps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _T120OnlyCaps[] = { /* SEQUENCE */ +static const struct field_t _T120OnlyCaps[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _SupportedProtocols[] = { /* CHOICE */ +static const struct field_t _SupportedProtocols[] = { /* CHOICE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, {FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps}, @@ -171,29 +171,29 @@ static field_t _SupportedProtocols[] = { /* CHOICE */ {FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL}, }; -static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */ +static const struct field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols}, }; -static field_t _GatewayInfo[] = { /* SEQUENCE */ +static const struct field_t _GatewayInfo[] = { /* SEQUENCE */ {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, _GatewayInfo_protocol}, {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, }; -static field_t _McuInfo[] = { /* SEQUENCE */ +static const struct field_t _McuInfo[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, }; -static field_t _TerminalInfo[] = { /* SEQUENCE */ +static const struct field_t _TerminalInfo[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, }; -static field_t _EndpointType[] = { /* SEQUENCE */ +static const struct field_t _EndpointType[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0, @@ -210,19 +210,19 @@ static field_t _EndpointType[] = { /* SEQUENCE */ 0, NULL}, }; -static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */ +static const struct field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */ +static const struct field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */ +static const struct field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */ {FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */ +static const struct field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */ {FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -231,12 +231,12 @@ static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */ 0, NULL}, }; -static field_t _Q954Details[] = { /* SEQUENCE */ +static const struct field_t _Q954Details[] = { /* SEQUENCE */ {FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _QseriesOptions[] = { /* SEQUENCE */ +static const struct field_t _QseriesOptions[] = { /* SEQUENCE */ {FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -247,32 +247,32 @@ static field_t _QseriesOptions[] = { /* SEQUENCE */ {FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details}, }; -static field_t _CallType[] = { /* CHOICE */ +static const struct field_t _CallType[] = { /* CHOICE */ {FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */ +static const struct field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */ {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */ +static const struct field_t _H245_NonStandardIdentifier[] = { /* CHOICE */ {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0, _H245_NonStandardIdentifier_h221NonStandard}, }; -static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */ +static const struct field_t _H245_NonStandardParameter[] = { /* SEQUENCE */ {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0, _H245_NonStandardIdentifier}, {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _H261VideoCapability[] = { /* SEQUENCE */ +static const struct field_t _H261VideoCapability[] = { /* SEQUENCE */ {FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, {FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0, @@ -282,7 +282,7 @@ static field_t _H261VideoCapability[] = { /* SEQUENCE */ {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _H262VideoCapability[] = { /* SEQUENCE */ +static const struct field_t _H262VideoCapability[] = { /* SEQUENCE */ {FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -304,7 +304,7 @@ static field_t _H262VideoCapability[] = { /* SEQUENCE */ {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _H263VideoCapability[] = { /* SEQUENCE */ +static const struct field_t _H263VideoCapability[] = { /* SEQUENCE */ {FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, {FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, {FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, @@ -330,7 +330,7 @@ static field_t _H263VideoCapability[] = { /* SEQUENCE */ {FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL}, }; -static field_t _IS11172VideoCapability[] = { /* SEQUENCE */ +static const struct field_t _IS11172VideoCapability[] = { /* SEQUENCE */ {FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, @@ -341,7 +341,7 @@ static field_t _IS11172VideoCapability[] = { /* SEQUENCE */ {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _VideoCapability[] = { /* CHOICE */ +static const struct field_t _VideoCapability[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, {FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0, @@ -355,12 +355,12 @@ static field_t _VideoCapability[] = { /* CHOICE */ {FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, }; -static field_t _AudioCapability_g7231[] = { /* SEQUENCE */ +static const struct field_t _AudioCapability_g7231[] = { /* SEQUENCE */ {FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL}, {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _IS11172AudioCapability[] = { /* SEQUENCE */ +static const struct field_t _IS11172AudioCapability[] = { /* SEQUENCE */ {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -372,7 +372,7 @@ static field_t _IS11172AudioCapability[] = { /* SEQUENCE */ {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, }; -static field_t _IS13818AudioCapability[] = { /* SEQUENCE */ +static const struct field_t _IS13818AudioCapability[] = { /* SEQUENCE */ {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -396,7 +396,7 @@ static field_t _IS13818AudioCapability[] = { /* SEQUENCE */ {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, }; -static field_t _AudioCapability[] = { /* CHOICE */ +static const struct field_t _AudioCapability[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, {FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, @@ -424,7 +424,7 @@ static field_t _AudioCapability[] = { /* CHOICE */ {FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL}, }; -static field_t _DataProtocolCapability[] = { /* CHOICE */ +static const struct field_t _DataProtocolCapability[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, {FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -442,7 +442,7 @@ static field_t _DataProtocolCapability[] = { /* CHOICE */ {FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */ +static const struct field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */ {FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -464,25 +464,25 @@ static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */ {FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _T84Profile[] = { /* CHOICE */ +static const struct field_t _T84Profile[] = { /* CHOICE */ {FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0, _T84Profile_t84Restricted}, }; -static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */ +static const struct field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */ {FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, _DataProtocolCapability}, {FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile}, }; -static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */ +static const struct field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */ {FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, _DataProtocolCapability}, {FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _DataApplicationCapability_application[] = { /* CHOICE */ +static const struct field_t _DataApplicationCapability_application[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, {FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT, @@ -509,20 +509,20 @@ static field_t _DataApplicationCapability_application[] = { /* CHOICE */ {FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, }; -static field_t _DataApplicationCapability[] = { /* SEQUENCE */ +static const struct field_t _DataApplicationCapability[] = { /* SEQUENCE */ {FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT, offsetof(DataApplicationCapability, application), _DataApplicationCapability_application}, {FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL}, }; -static field_t _EncryptionMode[] = { /* CHOICE */ +static const struct field_t _EncryptionMode[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, {FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _DataType[] = { /* CHOICE */ +static const struct field_t _DataType[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, {FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -538,7 +538,7 @@ static field_t _DataType[] = { /* CHOICE */ {FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, }; -static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */ +static const struct field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL}, {FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL}, {FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, @@ -546,12 +546,12 @@ static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL}, }; -static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */ +static const struct field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */ {FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL}, {FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL}, }; -static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */ +static const struct field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, {FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -565,53 +565,53 @@ static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE {FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL}, }; -static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */ +static const struct field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _H223LogicalChannelParameters_adaptationLayerType}, {FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _CRCLength[] = { /* CHOICE */ +static const struct field_t _CRCLength[] = { /* CHOICE */ {FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _V76HDLCParameters[] = { /* SEQUENCE */ +static const struct field_t _V76HDLCParameters[] = { /* SEQUENCE */ {FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength}, {FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */ +static const struct field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */ {FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */ +static const struct field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */ {FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */ +static const struct field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */ {FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL}, {FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0, _V76LogicalChannelParameters_mode_eRM_recovery}, }; -static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */ +static const struct field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */ {FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0, _V76LogicalChannelParameters_mode_eRM}, {FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _V75Parameters[] = { /* SEQUENCE */ +static const struct field_t _V75Parameters[] = { /* SEQUENCE */ {FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */ +static const struct field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0, _V76HDLCParameters}, {FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0, @@ -622,38 +622,38 @@ static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters}, }; -static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */ +static const struct field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, }; -static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */ +static const struct field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */ {FNAME("network") OCTSTR, FIXD, 4, 0, DECODE, offsetof(UnicastAddress_iPAddress, network), NULL}, {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */ +static const struct field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */ {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, {FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, }; -static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */ +static const struct field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */ {FNAME("network") OCTSTR, FIXD, 16, 0, DECODE, offsetof(UnicastAddress_iP6Address, network), NULL}, {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */ +static const struct field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */ {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */ +static const struct field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */ {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, }; -static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */ +static const struct field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */ {FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0, _UnicastAddress_iPSourceRouteAddress_routing}, {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, @@ -662,7 +662,7 @@ static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */ _UnicastAddress_iPSourceRouteAddress_route}, }; -static field_t _UnicastAddress[] = { /* CHOICE */ +static const struct field_t _UnicastAddress[] = { /* CHOICE */ {FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT, offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress}, {FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0, @@ -676,17 +676,17 @@ static field_t _UnicastAddress[] = { /* CHOICE */ {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, }; -static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */ +static const struct field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */ {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */ +static const struct field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */ {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _MulticastAddress[] = { /* CHOICE */ +static const struct field_t _MulticastAddress[] = { /* CHOICE */ {FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0, _MulticastAddress_iPAddress}, {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, @@ -695,14 +695,14 @@ static field_t _MulticastAddress[] = { /* CHOICE */ {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, }; -static field_t _H245_TransportAddress[] = { /* CHOICE */ +static const struct field_t _H245_TransportAddress[] = { /* CHOICE */ {FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT, offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress}, {FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0, _MulticastAddress}, }; -static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */ +static const struct field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, _H2250LogicalChannelParameters_nonStandard}, {FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL}, @@ -728,7 +728,7 @@ static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL}, }; -static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ +static const struct field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, _H222LogicalChannelParameters}, {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, @@ -742,7 +742,7 @@ static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexPara {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */ +static const struct field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT, offsetof(OpenLogicalChannel_forwardLogicalChannelParameters, @@ -756,7 +756,7 @@ static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQU {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, }; -static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ +static const struct field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, _H223LogicalChannelParameters}, {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0, @@ -767,7 +767,7 @@ static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexPara h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, }; -static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */ +static const struct field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType}, {FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT, offsetof(OpenLogicalChannel_reverseLogicalChannelParameters, @@ -778,23 +778,23 @@ static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQU {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, }; -static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */ +static const struct field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */ {FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _Q2931Address_address[] = { /* CHOICE */ +static const struct field_t _Q2931Address_address[] = { /* CHOICE */ {FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL}, {FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, }; -static field_t _Q2931Address[] = { /* SEQUENCE */ +static const struct field_t _Q2931Address[] = { /* SEQUENCE */ {FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0, _Q2931Address_address}, {FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL}, }; -static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */ +static const struct field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */ {FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address}, {FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, {FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT, @@ -802,7 +802,7 @@ static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */ _H245_TransportAddress}, }; -static field_t _NetworkAccessParameters[] = { /* SEQUENCE */ +static const struct field_t _NetworkAccessParameters[] = { /* SEQUENCE */ {FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _NetworkAccessParameters_distribution}, {FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT, @@ -814,7 +814,7 @@ static field_t _NetworkAccessParameters[] = { /* SEQUENCE */ NULL}, }; -static field_t _OpenLogicalChannel[] = { /* SEQUENCE */ +static const struct field_t _OpenLogicalChannel[] = { /* SEQUENCE */ {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT, offsetof(OpenLogicalChannel, forwardLogicalChannelParameters), @@ -829,13 +829,13 @@ static field_t _OpenLogicalChannel[] = { /* SEQUENCE */ {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, }; -static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */ +static const struct field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, sizeof(OpenLogicalChannel), _OpenLogicalChannel} , }; -static field_t _Setup_UUIE[] = { /* SEQUENCE */ +static const struct field_t _Setup_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, offsetof(Setup_UUIE, h245Address), _TransportAddress}, @@ -894,13 +894,13 @@ static field_t _Setup_UUIE[] = { /* SEQUENCE */ NULL}, }; -static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */ +static const struct field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, sizeof(OpenLogicalChannel), _OpenLogicalChannel} , }; -static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */ +static const struct field_t _CallProceeding_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, @@ -920,13 +920,13 @@ static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */ {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, }; -static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */ +static const struct field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, sizeof(OpenLogicalChannel), _OpenLogicalChannel} , }; -static field_t _Connect_UUIE[] = { /* SEQUENCE */ +static const struct field_t _Connect_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, offsetof(Connect_UUIE, h245Address), _TransportAddress}, @@ -954,13 +954,13 @@ static field_t _Connect_UUIE[] = { /* SEQUENCE */ {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, }; -static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */ +static const struct field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, sizeof(OpenLogicalChannel), _OpenLogicalChannel} , }; -static field_t _Alerting_UUIE[] = { /* SEQUENCE */ +static const struct field_t _Alerting_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, @@ -986,7 +986,7 @@ static field_t _Alerting_UUIE[] = { /* SEQUENCE */ {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, }; -static field_t _Information_UUIE[] = { /* SEQUENCE */ +static const struct field_t _Information_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, @@ -996,7 +996,7 @@ static field_t _Information_UUIE[] = { /* SEQUENCE */ {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, }; -static field_t _ReleaseCompleteReason[] = { /* CHOICE */ +static const struct field_t _ReleaseCompleteReason[] = { /* CHOICE */ {FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -1022,7 +1022,7 @@ static field_t _ReleaseCompleteReason[] = { /* CHOICE */ {FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */ +static const struct field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0, _ReleaseCompleteReason}, @@ -1039,11 +1039,11 @@ static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */ {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, }; -static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */ +static const struct field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _FacilityReason[] = { /* CHOICE */ +static const struct field_t _FacilityReason[] = { /* CHOICE */ {FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL}, @@ -1057,13 +1057,13 @@ static field_t _FacilityReason[] = { /* CHOICE */ {FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */ +static const struct field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, sizeof(OpenLogicalChannel), _OpenLogicalChannel} , }; -static field_t _Facility_UUIE[] = { /* SEQUENCE */ +static const struct field_t _Facility_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, offsetof(Facility_UUIE, alternativeAddress), _TransportAddress}, @@ -1094,17 +1094,17 @@ static field_t _Facility_UUIE[] = { /* SEQUENCE */ NULL}, }; -static field_t _CallIdentifier[] = { /* SEQUENCE */ +static const struct field_t _CallIdentifier[] = { /* SEQUENCE */ {FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, }; -static field_t _SecurityServiceMode[] = { /* CHOICE */ +static const struct field_t _SecurityServiceMode[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _SecurityCapabilities[] = { /* SEQUENCE */ +static const struct field_t _SecurityCapabilities[] = { /* SEQUENCE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0, @@ -1115,30 +1115,30 @@ static field_t _SecurityCapabilities[] = { /* SEQUENCE */ _SecurityServiceMode}, }; -static field_t _H245Security[] = { /* CHOICE */ +static const struct field_t _H245Security[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, {FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, {FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, }; -static field_t _DHset[] = { /* SEQUENCE */ +static const struct field_t _DHset[] = { /* SEQUENCE */ {FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, {FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, {FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, }; -static field_t _TypedCertificate[] = { /* SEQUENCE */ +static const struct field_t _TypedCertificate[] = { /* SEQUENCE */ {FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */ +static const struct field_t _H235_NonStandardParameter[] = { /* SEQUENCE */ {FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _ClearToken[] = { /* SEQUENCE */ +static const struct field_t _ClearToken[] = { /* SEQUENCE */ {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL}, {FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, @@ -1154,120 +1154,120 @@ static field_t _ClearToken[] = { /* SEQUENCE */ {FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, }; -static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */ +static const struct field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, }; -static field_t _Params[] = { /* SEQUENCE */ +static const struct field_t _Params[] = { /* SEQUENCE */ {FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL}, {FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, }; -static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */ {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */ {FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, _CryptoH323Token_cryptoEPPwdHash_token}, }; -static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */ {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */ {FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, _CryptoH323Token_cryptoGKPwdHash_token}, }; -static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */ {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */ {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */ {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */ {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */ +static const struct field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */ {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */ +static const struct field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */ {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */ +static const struct field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */ {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, _CryptoToken_cryptoEncryptedToken_token}, }; -static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */ +static const struct field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */ {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */ +static const struct field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */ {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("token") SEQ, 0, 4, 4, SKIP, 0, _CryptoToken_cryptoSignedToken_token}, }; -static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */ +static const struct field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */ {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */ +static const struct field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */ {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, _CryptoToken_cryptoHashedToken_token}, }; -static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */ +static const struct field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */ {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, }; -static field_t _CryptoToken[] = { /* CHOICE */ +static const struct field_t _CryptoToken[] = { /* CHOICE */ {FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0, _CryptoToken_cryptoEncryptedToken}, {FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0, @@ -1278,7 +1278,7 @@ static field_t _CryptoToken[] = { /* CHOICE */ _CryptoToken_cryptoPwdEncr}, }; -static field_t _CryptoH323Token[] = { /* CHOICE */ +static const struct field_t _CryptoH323Token[] = { /* CHOICE */ {FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0, _CryptoH323Token_cryptoEPPwdHash}, {FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0, @@ -1297,17 +1297,17 @@ static field_t _CryptoH323Token[] = { /* CHOICE */ _CryptoToken}, }; -static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */ +static const struct field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token}, }; -static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */ +static const struct field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, sizeof(OpenLogicalChannel), _OpenLogicalChannel} , }; -static field_t _Progress_UUIE[] = { /* SEQUENCE */ +static const struct field_t _Progress_UUIE[] = { /* SEQUENCE */ {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, @@ -1328,7 +1328,7 @@ static field_t _Progress_UUIE[] = { /* SEQUENCE */ {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, }; -static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */ +static const struct field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */ {FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT, offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE}, {FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT, @@ -1352,7 +1352,7 @@ static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */ {FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, }; -static field_t _RequestMessage[] = { /* CHOICE */ +static const struct field_t _RequestMessage[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, {FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, {FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL}, @@ -1372,7 +1372,7 @@ static field_t _RequestMessage[] = { /* CHOICE */ NULL}, }; -static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ +static const struct field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, _H222LogicalChannelParameters}, {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, @@ -1381,7 +1381,7 @@ static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexP h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, }; -static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */ +static const struct field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */ {FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, {FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT, @@ -1391,11 +1391,11 @@ static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* S {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, }; -static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */ +static const struct field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */ {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, }; -static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */ +static const struct field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */ {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, _H2250LogicalChannelAckParameters_nonStandard}, {FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL}, @@ -1410,14 +1410,14 @@ static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */ {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, }; -static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */ +static const struct field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */ {FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT, offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters, h2250LogicalChannelAckParameters), _H2250LogicalChannelAckParameters}, }; -static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */ +static const struct field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */ {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4, DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck, @@ -1433,7 +1433,7 @@ static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */ {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, }; -static field_t _ResponseMessage[] = { /* CHOICE */ +static const struct field_t _ResponseMessage[] = { /* CHOICE */ {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, {FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, @@ -1469,7 +1469,7 @@ static field_t _ResponseMessage[] = { /* CHOICE */ {FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL}, }; -static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */ +static const struct field_t _MultimediaSystemControlMessage[] = { /* CHOICE */ {FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT, offsetof(MultimediaSystemControlMessage, request), _RequestMessage}, {FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT, @@ -1479,14 +1479,14 @@ static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */ {FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL}, }; -static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */ +static const struct field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT, sizeof(MultimediaSystemControlMessage), _MultimediaSystemControlMessage} , }; -static field_t _H323_UU_PDU[] = { /* SEQUENCE */ +static const struct field_t _H323_UU_PDU[] = { /* SEQUENCE */ {FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT, offsetof(H323_UU_PDU, h323_message_body), _H323_UU_PDU_h323_message_body}, @@ -1507,13 +1507,13 @@ static field_t _H323_UU_PDU[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _H323_UserInformation[] = { /* SEQUENCE */ +static const struct field_t _H323_UserInformation[] = { /* SEQUENCE */ {FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT, offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU}, {FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL}, }; -static field_t _GatekeeperRequest[] = { /* SEQUENCE */ +static const struct field_t _GatekeeperRequest[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, @@ -1537,7 +1537,7 @@ static field_t _GatekeeperRequest[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _GatekeeperConfirm[] = { /* SEQUENCE */ +static const struct field_t _GatekeeperConfirm[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, @@ -1557,23 +1557,23 @@ static field_t _GatekeeperConfirm[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ +static const struct field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, sizeof(TransportAddress), _TransportAddress} , }; -static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */ +static const struct field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, sizeof(TransportAddress), _TransportAddress} , }; -static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */ +static const struct field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _RegistrationRequest[] = { /* SEQUENCE */ +static const struct field_t _RegistrationRequest[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, @@ -1621,17 +1621,17 @@ static field_t _RegistrationRequest[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */ +static const struct field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, sizeof(TransportAddress), _TransportAddress} , }; -static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */ +static const struct field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _RegistrationConfirm[] = { /* SEQUENCE */ +static const struct field_t _RegistrationConfirm[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, @@ -1667,13 +1667,13 @@ static field_t _RegistrationConfirm[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ +static const struct field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, sizeof(TransportAddress), _TransportAddress} , }; -static field_t _UnregistrationRequest[] = { /* SEQUENCE */ +static const struct field_t _UnregistrationRequest[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, offsetof(UnregistrationRequest, callSignalAddress), @@ -1694,24 +1694,24 @@ static field_t _UnregistrationRequest[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _CallModel[] = { /* CHOICE */ +static const struct field_t _CallModel[] = { /* CHOICE */ {FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL}, {FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, }; -static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */ +static const struct field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */ +static const struct field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */ +static const struct field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _AdmissionRequest[] = { /* SEQUENCE */ +static const struct field_t _AdmissionRequest[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType}, {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel}, @@ -1755,7 +1755,7 @@ static field_t _AdmissionRequest[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _AdmissionConfirm[] = { /* SEQUENCE */ +static const struct field_t _AdmissionConfirm[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL}, {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel}, @@ -1790,11 +1790,11 @@ static field_t _AdmissionConfirm[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */ +static const struct field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, }; -static field_t _LocationRequest[] = { /* SEQUENCE */ +static const struct field_t _LocationRequest[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0, @@ -1818,7 +1818,7 @@ static field_t _LocationRequest[] = { /* SEQUENCE */ {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, }; -static field_t _LocationConfirm[] = { /* SEQUENCE */ +static const struct field_t _LocationConfirm[] = { /* SEQUENCE */ {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, {FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT, offsetof(LocationConfirm, callSignalAddress), _TransportAddress}, @@ -1844,13 +1844,13 @@ static field_t _LocationConfirm[] = { /* SEQUENCE */ {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */ +static const struct field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */ {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, sizeof(TransportAddress), _TransportAddress} , }; -static field_t _InfoRequestResponse[] = { /* SEQUENCE */ +static const struct field_t _InfoRequestResponse[] = { /* SEQUENCE */ {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, _NonStandardParameter}, {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, @@ -1873,7 +1873,7 @@ static field_t _InfoRequestResponse[] = { /* SEQUENCE */ {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, }; -static field_t _RasMessage[] = { /* CHOICE */ +static const struct field_t _RasMessage[] = { /* CHOICE */ {FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT, offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest}, {FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT, diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 96aa637..b1fd21c 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -28,6 +28,7 @@ #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_extend.h> +static DEFINE_MUTEX(nf_ct_helper_mutex); static struct hlist_head *nf_ct_helper_hash __read_mostly; static unsigned int nf_ct_helper_hsize __read_mostly; static unsigned int nf_ct_helper_count __read_mostly; @@ -54,42 +55,13 @@ __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) return NULL; h = helper_hash(tuple); - hlist_for_each_entry(helper, n, &nf_ct_helper_hash[h], hnode) { + hlist_for_each_entry_rcu(helper, n, &nf_ct_helper_hash[h], hnode) { if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask)) return helper; } return NULL; } - -struct nf_conntrack_helper * -nf_ct_helper_find_get(const struct nf_conntrack_tuple *tuple) -{ - struct nf_conntrack_helper *helper; - - /* need nf_conntrack_lock to assure that helper exists until - * try_module_get() is called */ - read_lock_bh(&nf_conntrack_lock); - - helper = __nf_ct_helper_find(tuple); - if (helper) { - /* need to increase module usage count to assure helper will - * not go away while the caller is e.g. busy putting a - * conntrack in the hash that uses the helper */ - if (!try_module_get(helper->me)) - helper = NULL; - } - - read_unlock_bh(&nf_conntrack_lock); - - return helper; -} -EXPORT_SYMBOL_GPL(nf_ct_helper_find_get); - -void nf_ct_helper_put(struct nf_conntrack_helper *helper) -{ - module_put(helper->me); -} -EXPORT_SYMBOL_GPL(nf_ct_helper_put); +EXPORT_SYMBOL_GPL(__nf_ct_helper_find); struct nf_conntrack_helper * __nf_conntrack_helper_find_byname(const char *name) @@ -99,7 +71,7 @@ __nf_conntrack_helper_find_byname(const char *name) unsigned int i; for (i = 0; i < nf_ct_helper_hsize; i++) { - hlist_for_each_entry(h, n, &nf_ct_helper_hash[i], hnode) { + hlist_for_each_entry_rcu(h, n, &nf_ct_helper_hash[i], hnode) { if (!strcmp(h->name, name)) return h; } @@ -140,10 +112,10 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) BUG_ON(me->timeout == 0); - write_lock_bh(&nf_conntrack_lock); - hlist_add_head(&me->hnode, &nf_ct_helper_hash[h]); + mutex_lock(&nf_ct_helper_mutex); + hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); nf_ct_helper_count++; - write_unlock_bh(&nf_conntrack_lock); + mutex_unlock(&nf_ct_helper_mutex); return 0; } @@ -156,10 +128,17 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) struct hlist_node *n, *next; unsigned int i; - /* Need write lock here, to delete helper. */ - write_lock_bh(&nf_conntrack_lock); - hlist_del(&me->hnode); + mutex_lock(&nf_ct_helper_mutex); + hlist_del_rcu(&me->hnode); nf_ct_helper_count--; + mutex_unlock(&nf_ct_helper_mutex); + + /* Make sure every nothing is still using the helper unless its a + * connection in the hash. + */ + synchronize_rcu(); + + spin_lock_bh(&nf_conntrack_lock); /* Get rid of expectations */ for (i = 0; i < nf_ct_expect_hsize; i++) { @@ -181,10 +160,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) hlist_for_each_entry(h, n, &nf_conntrack_hash[i], hnode) unhelp(h, me); } - write_unlock_bh(&nf_conntrack_lock); - - /* Someone could be still looking at the helper in a bh. */ - synchronize_net(); + spin_unlock_bh(&nf_conntrack_lock); } EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index dfaed4b..c336b07 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -23,7 +23,7 @@ #define MAX_PORTS 8 static unsigned short ports[MAX_PORTS]; -static int ports_c; +static unsigned int ports_c; static unsigned int max_dcc_channels = 8; static unsigned int dcc_timeout __read_mostly = 300; /* This is slow, but it's simple. --RR */ diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 38141f1..4a1b42b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -491,11 +491,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, && ctnetlink_dump_helpinfo(skb, ct) < 0) goto nla_put_failure; -#ifdef CONFIG_NF_CONNTRACK_MARK - if ((events & IPCT_MARK || ct->mark) - && ctnetlink_dump_mark(skb, ct) < 0) - goto nla_put_failure; -#endif #ifdef CONFIG_NF_CONNTRACK_SECMARK if ((events & IPCT_SECMARK || ct->secmark) && ctnetlink_dump_secmark(skb, ct) < 0) @@ -516,6 +511,12 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, goto nla_put_failure; } +#ifdef CONFIG_NF_CONNTRACK_MARK + if ((events & IPCT_MARK || ct->mark) + && ctnetlink_dump_mark(skb, ct) < 0) + goto nla_put_failure; +#endif + nlh->nlmsg_len = skb->tail - b; nfnetlink_send(skb, 0, group, 0); return NOTIFY_DONE; @@ -545,12 +546,12 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); u_int8_t l3proto = nfmsg->nfgen_family; - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); last = (struct nf_conn *)cb->args[1]; for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { restart: - hlist_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]], - hnode) { + hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[cb->args[0]], + hnode) { if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = nf_ct_tuplehash_to_ctrack(h); @@ -568,7 +569,8 @@ restart: cb->nlh->nlmsg_seq, IPCTNL_MSG_CT_NEW, 1, ct) < 0) { - nf_conntrack_get(&ct->ct_general); + if (!atomic_inc_not_zero(&ct->ct_general.use)) + continue; cb->args[1] = (unsigned long)ct; goto out; } @@ -584,7 +586,7 @@ restart: } } out: - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); if (last) nf_ct_put(last); @@ -1167,11 +1169,12 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); #endif - helper = nf_ct_helper_find_get(rtuple); + rcu_read_lock(); + helper = __nf_ct_helper_find(rtuple); if (helper) { help = nf_ct_helper_ext_add(ct, GFP_KERNEL); if (help == NULL) { - nf_ct_helper_put(helper); + rcu_read_unlock(); err = -ENOMEM; goto err; } @@ -1187,9 +1190,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[], add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); - - if (helper) - nf_ct_helper_put(helper); + rcu_read_unlock(); return 0; @@ -1220,11 +1221,11 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, return err; } - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); if (cda[CTA_TUPLE_ORIG]) - h = __nf_conntrack_find(&otuple, NULL); + h = __nf_conntrack_find(&otuple); else if (cda[CTA_TUPLE_REPLY]) - h = __nf_conntrack_find(&rtuple, NULL); + h = __nf_conntrack_find(&rtuple); if (h == NULL) { struct nf_conntrack_tuple master; @@ -1237,9 +1238,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, CTA_TUPLE_MASTER, u3); if (err < 0) - return err; + goto out_unlock; - master_h = __nf_conntrack_find(&master, NULL); + master_h = __nf_conntrack_find(&master); if (master_h == NULL) { err = -ENOENT; goto out_unlock; @@ -1248,7 +1249,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, atomic_inc(&master_ct->ct_general.use); } - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) err = ctnetlink_create_conntrack(cda, @@ -1281,7 +1282,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, } out_unlock: - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); return err; } @@ -1472,7 +1473,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) struct hlist_node *n; u_int8_t l3proto = nfmsg->nfgen_family; - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); last = (struct nf_conntrack_expect *)cb->args[1]; for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) { restart: @@ -1489,7 +1490,8 @@ restart: cb->nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, 1, exp) < 0) { - atomic_inc(&exp->use); + if (!atomic_inc_not_zero(&exp->use)) + continue; cb->args[1] = (unsigned long)exp; goto out; } @@ -1500,7 +1502,7 @@ restart: } } out: - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); if (last) nf_ct_expect_put(last); @@ -1613,10 +1615,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, struct nf_conn_help *m_help; /* delete all expectations for this helper */ - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); h = __nf_conntrack_helper_find_byname(name); if (!h) { - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); return -EINVAL; } for (i = 0; i < nf_ct_expect_hsize; i++) { @@ -1631,10 +1633,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, } } } - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); } else { /* This basically means we have to flush everything*/ - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); for (i = 0; i < nf_ct_expect_hsize; i++) { hlist_for_each_entry_safe(exp, n, next, &nf_ct_expect_hash[i], @@ -1645,7 +1647,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, } } } - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); } return 0; @@ -1731,11 +1733,11 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - write_lock_bh(&nf_conntrack_lock); + spin_lock_bh(&nf_conntrack_lock); exp = __nf_ct_expect_find(&tuple); if (!exp) { - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) err = ctnetlink_create_expect(cda, u3); @@ -1745,7 +1747,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, err = -EEXIST; if (!(nlh->nlmsg_flags & NLM_F_EXCL)) err = ctnetlink_change_expect(exp, cda); - write_unlock_bh(&nf_conntrack_lock); + spin_unlock_bh(&nf_conntrack_lock); return err; } diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 099b6df..b5cb8e8 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); #ifdef DEBUG /* PptpControlMessageType names */ -const char *pptp_msg_name[] = { +const char *const pptp_msg_name[] = { "UNKNOWN_MESSAGE", "START_SESSION_REQUEST", "START_SESSION_REPLY", @@ -136,7 +136,7 @@ static void pptp_expectfn(struct nf_conn *ct, static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) { - struct nf_conntrack_tuple_hash *h; + const struct nf_conntrack_tuple_hash *h; struct nf_conntrack_expect *exp; struct nf_conn *sibling; @@ -168,7 +168,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) /* timeout GRE data connections */ static void pptp_destroy_siblings(struct nf_conn *ct) { - struct nf_conn_help *help = nfct_help(ct); + const struct nf_conn_help *help = nfct_help(ct); struct nf_conntrack_tuple t; nf_ct_gre_keymap_destroy(ct); @@ -497,9 +497,11 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, { int dir = CTINFO2DIR(ctinfo); - struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; - struct tcphdr _tcph, *tcph; - struct pptp_pkt_hdr _pptph, *pptph; + const struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; + const struct tcphdr *tcph; + struct tcphdr _tcph; + const struct pptp_pkt_hdr *pptph; + struct pptp_pkt_hdr _pptph; struct PptpControlHeader _ctlh, *ctlh; union pptp_ctrl_union _pptpReq, *pptpReq; unsigned int tcplen = skb->len - protoff; diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 22c5dcb..5545891 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -41,19 +41,19 @@ static int generic_print_tuple(struct seq_file *s, } /* Returns verdict for packet, or -1 for invalid. */ -static int packet(struct nf_conn *conntrack, +static int packet(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info ctinfo, int pf, unsigned int hooknum) { - nf_ct_refresh_acct(conntrack, ctinfo, skb, nf_ct_generic_timeout); + nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_generic_timeout); return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ -static int new(struct nf_conn *conntrack, const struct sk_buff *skb, +static int new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { return 1; diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 4a185f6..e10024a 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -161,9 +161,11 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { - struct gre_hdr_pptp _pgrehdr, *pgrehdr; + const struct gre_hdr_pptp *pgrehdr; + struct gre_hdr_pptp _pgrehdr; __be16 srckey; - struct gre_hdr _grehdr, *grehdr; + const struct gre_hdr *grehdr; + struct gre_hdr _grehdr; /* first only delinearize old RFC1701 GRE header */ grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr); diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 21d29e78..f9a0837 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -25,7 +25,7 @@ #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h> -/* Protects conntrack->proto.sctp */ +/* Protects ct->proto.sctp */ static DEFINE_RWLOCK(sctp_lock); /* FIXME: Examine ipfilter's timeouts and conntrack transitions more @@ -624,7 +624,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { #endif }; -int __init nf_conntrack_proto_sctp_init(void) +static int __init nf_conntrack_proto_sctp_init(void) { int ret; @@ -647,7 +647,7 @@ int __init nf_conntrack_proto_sctp_init(void) return ret; } -void __exit nf_conntrack_proto_sctp_fini(void) +static void __exit nf_conntrack_proto_sctp_fini(void) { nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 64c9b91..3e0ccca 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -26,7 +26,7 @@ #include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_log.h> -/* Protects conntrack->proto.tcp */ +/* Protects ct->proto.tcp */ static DEFINE_RWLOCK(tcp_lock); /* "Be conservative in what you do, @@ -46,7 +46,7 @@ static int nf_ct_tcp_max_retrans __read_mostly = 3; /* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR */ -static const char *tcp_conntrack_names[] = { +static const char *const tcp_conntrack_names[] = { "NONE", "SYN_SENT", "SYN_RECV", @@ -261,7 +261,8 @@ static int tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { - struct tcphdr _hdr, *hp; + const struct tcphdr *hp; + struct tcphdr _hdr; /* Actually only need first 8 bytes. */ hp = skb_header_pointer(skb, dataoff, 8, &_hdr); @@ -292,13 +293,12 @@ static int tcp_print_tuple(struct seq_file *s, } /* Print out the private part of the conntrack. */ -static int tcp_print_conntrack(struct seq_file *s, - const struct nf_conn *conntrack) +static int tcp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) { enum tcp_conntrack state; read_lock_bh(&tcp_lock); - state = conntrack->proto.tcp.state; + state = ct->proto.tcp.state; read_unlock_bh(&tcp_lock); return seq_printf(s, "%s ", tcp_conntrack_names[state]); @@ -344,7 +344,7 @@ static unsigned int get_conntrack_index(const struct tcphdr *tcph) static inline __u32 segment_seq_plus_len(__u32 seq, size_t len, unsigned int dataoff, - struct tcphdr *tcph) + const struct tcphdr *tcph) { /* XXX Should I use payload length field in IP/IPv6 header ? * - YK */ @@ -363,11 +363,11 @@ static inline __u32 segment_seq_plus_len(__u32 seq, */ static void tcp_options(const struct sk_buff *skb, unsigned int dataoff, - struct tcphdr *tcph, + const struct tcphdr *tcph, struct ip_ct_tcp_state *state) { unsigned char buff[(15 * 4) - sizeof(struct tcphdr)]; - unsigned char *ptr; + const unsigned char *ptr; int length = (tcph->doff*4) - sizeof(struct tcphdr); if (!length) @@ -418,10 +418,10 @@ static void tcp_options(const struct sk_buff *skb, } static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, - struct tcphdr *tcph, __u32 *sack) + const struct tcphdr *tcph, __u32 *sack) { unsigned char buff[(15 * 4) - sizeof(struct tcphdr)]; - unsigned char *ptr; + const unsigned char *ptr; int length = (tcph->doff*4) - sizeof(struct tcphdr); __u32 tmp; @@ -478,18 +478,18 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, } } -static int tcp_in_window(struct nf_conn *ct, +static int tcp_in_window(const struct nf_conn *ct, struct ip_ct_tcp *state, enum ip_conntrack_dir dir, unsigned int index, const struct sk_buff *skb, unsigned int dataoff, - struct tcphdr *tcph, + const struct tcphdr *tcph, int pf) { struct ip_ct_tcp_state *sender = &state->seen[dir]; struct ip_ct_tcp_state *receiver = &state->seen[!dir]; - struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; + const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; __u32 seq, ack, sack, end, win, swin; int res; @@ -687,14 +687,14 @@ static int tcp_in_window(struct nf_conn *ct, #ifdef CONFIG_NF_NAT_NEEDED /* Update sender->td_end after NAT successfully mangled the packet */ /* Caller must linearize skb at tcp header. */ -void nf_conntrack_tcp_update(struct sk_buff *skb, +void nf_conntrack_tcp_update(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conn *conntrack, + struct nf_conn *ct, int dir) { - struct tcphdr *tcph = (void *)skb->data + dataoff; - struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir]; - struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir]; + const struct tcphdr *tcph = (const void *)skb->data + dataoff; + const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; + const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[!dir]; __u32 end; end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); @@ -703,9 +703,9 @@ void nf_conntrack_tcp_update(struct sk_buff *skb, /* * We have to worry for the ack in the reply packet only... */ - if (after(end, conntrack->proto.tcp.seen[dir].td_end)) - conntrack->proto.tcp.seen[dir].td_end = end; - conntrack->proto.tcp.last_end = end; + if (after(end, ct->proto.tcp.seen[dir].td_end)) + ct->proto.tcp.seen[dir].td_end = end; + ct->proto.tcp.last_end = end; write_unlock_bh(&tcp_lock); pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " "receiver end=%u maxend=%u maxwin=%u scale=%i\n", @@ -727,7 +727,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); #define TH_CWR 0x80 /* table of valid flag combinations - PUSH, ECE and CWR are always valid */ -static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) + 1] = +static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) + 1] = { [TH_SYN] = 1, [TH_SYN|TH_URG] = 1, @@ -747,7 +747,8 @@ static int tcp_error(struct sk_buff *skb, int pf, unsigned int hooknum) { - struct tcphdr _tcph, *th; + const struct tcphdr *th; + struct tcphdr _tcph; unsigned int tcplen = skb->len - dataoff; u_int8_t tcpflags; @@ -794,7 +795,7 @@ static int tcp_error(struct sk_buff *skb, } /* Returns verdict for packet, or -1 for invalid. */ -static int tcp_packet(struct nf_conn *conntrack, +static int tcp_packet(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info ctinfo, @@ -804,7 +805,8 @@ static int tcp_packet(struct nf_conn *conntrack, struct nf_conntrack_tuple *tuple; enum tcp_conntrack new_state, old_state; enum ip_conntrack_dir dir; - struct tcphdr *th, _tcph; + const struct tcphdr *th; + struct tcphdr _tcph; unsigned long timeout; unsigned int index; @@ -812,26 +814,24 @@ static int tcp_packet(struct nf_conn *conntrack, BUG_ON(th == NULL); write_lock_bh(&tcp_lock); - old_state = conntrack->proto.tcp.state; + old_state = ct->proto.tcp.state; dir = CTINFO2DIR(ctinfo); index = get_conntrack_index(th); new_state = tcp_conntracks[dir][index][old_state]; - tuple = &conntrack->tuplehash[dir].tuple; + tuple = &ct->tuplehash[dir].tuple; switch (new_state) { case TCP_CONNTRACK_SYN_SENT: if (old_state < TCP_CONNTRACK_TIME_WAIT) break; - if ((conntrack->proto.tcp.seen[!dir].flags & - IP_CT_TCP_FLAG_CLOSE_INIT) - || (conntrack->proto.tcp.last_dir == dir - && conntrack->proto.tcp.last_index == TCP_RST_SET)) { + if ((ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_CLOSE_INIT) + || (ct->proto.tcp.last_dir == dir + && ct->proto.tcp.last_index == TCP_RST_SET)) { /* Attempt to reopen a closed/aborted connection. * Delete this connection and look up again. */ write_unlock_bh(&tcp_lock); - if (del_timer(&conntrack->timeout)) - conntrack->timeout.function((unsigned long) - conntrack); + if (del_timer(&ct->timeout)) + ct->timeout.function((unsigned long)ct); return -NF_REPEAT; } /* Fall through */ @@ -843,10 +843,9 @@ static int tcp_packet(struct nf_conn *conntrack, * c) ACK in reply direction after initial SYN in original. */ if (index == TCP_SYNACK_SET - && conntrack->proto.tcp.last_index == TCP_SYN_SET - && conntrack->proto.tcp.last_dir != dir - && ntohl(th->ack_seq) == - conntrack->proto.tcp.last_end) { + && ct->proto.tcp.last_index == TCP_SYN_SET + && ct->proto.tcp.last_dir != dir + && ntohl(th->ack_seq) == ct->proto.tcp.last_end) { /* This SYN/ACK acknowledges a SYN that we earlier * ignored as invalid. This means that the client and * the server are both in sync, while the firewall is @@ -858,15 +857,14 @@ static int tcp_packet(struct nf_conn *conntrack, if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: killing out of sync session "); - if (del_timer(&conntrack->timeout)) - conntrack->timeout.function((unsigned long) - conntrack); + if (del_timer(&ct->timeout)) + ct->timeout.function((unsigned long)ct); return -NF_DROP; } - conntrack->proto.tcp.last_index = index; - conntrack->proto.tcp.last_dir = dir; - conntrack->proto.tcp.last_seq = ntohl(th->seq); - conntrack->proto.tcp.last_end = + ct->proto.tcp.last_index = index; + ct->proto.tcp.last_dir = dir; + ct->proto.tcp.last_seq = ntohl(th->seq); + ct->proto.tcp.last_end = segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th); write_unlock_bh(&tcp_lock); @@ -885,11 +883,11 @@ static int tcp_packet(struct nf_conn *conntrack, return -NF_ACCEPT; case TCP_CONNTRACK_CLOSE: if (index == TCP_RST_SET - && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) - && conntrack->proto.tcp.last_index == TCP_SYN_SET) - || (!test_bit(IPS_ASSURED_BIT, &conntrack->status) - && conntrack->proto.tcp.last_index == TCP_ACK_SET)) - && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) { + && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status) + && ct->proto.tcp.last_index == TCP_SYN_SET) + || (!test_bit(IPS_ASSURED_BIT, &ct->status) + && ct->proto.tcp.last_index == TCP_ACK_SET)) + && ntohl(th->ack_seq) == ct->proto.tcp.last_end) { /* RST sent to invalid SYN or ACK we had let through * at a) and c) above: * @@ -907,15 +905,15 @@ static int tcp_packet(struct nf_conn *conntrack, break; } - if (!tcp_in_window(conntrack, &conntrack->proto.tcp, dir, index, + if (!tcp_in_window(ct, &ct->proto.tcp, dir, index, skb, dataoff, th, pf)) { write_unlock_bh(&tcp_lock); return -NF_ACCEPT; } in_window: /* From now on we have got in-window packets */ - conntrack->proto.tcp.last_index = index; - conntrack->proto.tcp.last_dir = dir; + ct->proto.tcp.last_index = index; + ct->proto.tcp.last_dir = dir; pr_debug("tcp_conntracks: "); NF_CT_DUMP_TUPLE(tuple); @@ -924,12 +922,12 @@ static int tcp_packet(struct nf_conn *conntrack, (th->fin ? 1 : 0), (th->rst ? 1 : 0), old_state, new_state); - conntrack->proto.tcp.state = new_state; + ct->proto.tcp.state = new_state; if (old_state != new_state && (new_state == TCP_CONNTRACK_FIN_WAIT || new_state == TCP_CONNTRACK_CLOSE)) - conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; - timeout = conntrack->proto.tcp.retrans >= nf_ct_tcp_max_retrans + ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; + timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans ? nf_ct_tcp_timeout_max_retrans : tcp_timeouts[new_state]; write_unlock_bh(&tcp_lock); @@ -938,41 +936,41 @@ static int tcp_packet(struct nf_conn *conntrack, if (new_state != old_state) nf_conntrack_event_cache(IPCT_PROTOINFO, skb); - if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { + if (!test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { /* If only reply is a RST, we can consider ourselves not to have an established connection: this is a fairly common problem case, so we can delete the conntrack immediately. --RR */ if (th->rst) { - if (del_timer(&conntrack->timeout)) - conntrack->timeout.function((unsigned long) - conntrack); + if (del_timer(&ct->timeout)) + ct->timeout.function((unsigned long)ct); return NF_ACCEPT; } - } else if (!test_bit(IPS_ASSURED_BIT, &conntrack->status) + } else if (!test_bit(IPS_ASSURED_BIT, &ct->status) && (old_state == TCP_CONNTRACK_SYN_RECV || old_state == TCP_CONNTRACK_ESTABLISHED) && new_state == TCP_CONNTRACK_ESTABLISHED) { /* Set ASSURED if we see see valid ack in ESTABLISHED after SYN_RECV or a valid answer for a picked up connection. */ - set_bit(IPS_ASSURED_BIT, &conntrack->status); + set_bit(IPS_ASSURED_BIT, &ct->status); nf_conntrack_event_cache(IPCT_STATUS, skb); } - nf_ct_refresh_acct(conntrack, ctinfo, skb, timeout); + nf_ct_refresh_acct(ct, ctinfo, skb, timeout); return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ -static int tcp_new(struct nf_conn *conntrack, +static int tcp_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { enum tcp_conntrack new_state; - struct tcphdr *th, _tcph; - struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0]; - struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1]; + const struct tcphdr *th; + struct tcphdr _tcph; + const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0]; + const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1]; th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); BUG_ON(th == NULL); @@ -990,17 +988,17 @@ static int tcp_new(struct nf_conn *conntrack, if (new_state == TCP_CONNTRACK_SYN_SENT) { /* SYN packet */ - conntrack->proto.tcp.seen[0].td_end = + ct->proto.tcp.seen[0].td_end = segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th); - conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window); - if (conntrack->proto.tcp.seen[0].td_maxwin == 0) - conntrack->proto.tcp.seen[0].td_maxwin = 1; - conntrack->proto.tcp.seen[0].td_maxend = - conntrack->proto.tcp.seen[0].td_end; - - tcp_options(skb, dataoff, th, &conntrack->proto.tcp.seen[0]); - conntrack->proto.tcp.seen[1].flags = 0; + ct->proto.tcp.seen[0].td_maxwin = ntohs(th->window); + if (ct->proto.tcp.seen[0].td_maxwin == 0) + ct->proto.tcp.seen[0].td_maxwin = 1; + ct->proto.tcp.seen[0].td_maxend = + ct->proto.tcp.seen[0].td_end; + + tcp_options(skb, dataoff, th, &ct->proto.tcp.seen[0]); + ct->proto.tcp.seen[1].flags = 0; } else if (nf_ct_tcp_loose == 0) { /* Don't try to pick up connections. */ return 0; @@ -1010,32 +1008,32 @@ static int tcp_new(struct nf_conn *conntrack, * its history is lost for us. * Let's try to use the data from the packet. */ - conntrack->proto.tcp.seen[0].td_end = + ct->proto.tcp.seen[0].td_end = segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th); - conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window); - if (conntrack->proto.tcp.seen[0].td_maxwin == 0) - conntrack->proto.tcp.seen[0].td_maxwin = 1; - conntrack->proto.tcp.seen[0].td_maxend = - conntrack->proto.tcp.seen[0].td_end + - conntrack->proto.tcp.seen[0].td_maxwin; - conntrack->proto.tcp.seen[0].td_scale = 0; + ct->proto.tcp.seen[0].td_maxwin = ntohs(th->window); + if (ct->proto.tcp.seen[0].td_maxwin == 0) + ct->proto.tcp.seen[0].td_maxwin = 1; + ct->proto.tcp.seen[0].td_maxend = + ct->proto.tcp.seen[0].td_end + + ct->proto.tcp.seen[0].td_maxwin; + ct->proto.tcp.seen[0].td_scale = 0; /* We assume SACK and liberal window checking to handle * window scaling */ - conntrack->proto.tcp.seen[0].flags = - conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM | - IP_CT_TCP_FLAG_BE_LIBERAL; + ct->proto.tcp.seen[0].flags = + ct->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM | + IP_CT_TCP_FLAG_BE_LIBERAL; } - conntrack->proto.tcp.seen[1].td_end = 0; - conntrack->proto.tcp.seen[1].td_maxend = 0; - conntrack->proto.tcp.seen[1].td_maxwin = 1; - conntrack->proto.tcp.seen[1].td_scale = 0; + ct->proto.tcp.seen[1].td_end = 0; + ct->proto.tcp.seen[1].td_maxend = 0; + ct->proto.tcp.seen[1].td_maxwin = 1; + ct->proto.tcp.seen[1].td_scale = 0; /* tcp_packet will set them */ - conntrack->proto.tcp.state = TCP_CONNTRACK_NONE; - conntrack->proto.tcp.last_index = TCP_NONE_SET; + ct->proto.tcp.state = TCP_CONNTRACK_NONE; + ct->proto.tcp.last_index = TCP_NONE_SET; pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i " "receiver end=%u maxend=%u maxwin=%u scale=%i\n", @@ -1098,16 +1096,16 @@ static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) { - struct nlattr *attr = cda[CTA_PROTOINFO_TCP]; + struct nlattr *pattr = cda[CTA_PROTOINFO_TCP]; struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1]; int err; /* updates could not contain anything about the private * protocol info, in that case skip the parsing */ - if (!attr) + if (!pattr) return 0; - err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, tcp_nla_policy); + err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, pattr, tcp_nla_policy); if (err < 0) return err; diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 3848754..b8a35cc 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -30,7 +30,8 @@ static int udp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { - struct udphdr _hdr, *hp; + const struct udphdr *hp; + struct udphdr _hdr; /* Actually only need first 8 bytes. */ hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); @@ -61,7 +62,7 @@ static int udp_print_tuple(struct seq_file *s, } /* Returns verdict for packet, and may modify conntracktype */ -static int udp_packet(struct nf_conn *conntrack, +static int udp_packet(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info ctinfo, @@ -70,20 +71,19 @@ static int udp_packet(struct nf_conn *conntrack, { /* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ - if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { - nf_ct_refresh_acct(conntrack, ctinfo, skb, - nf_ct_udp_timeout_stream); + if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { + nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream); /* Also, more likely to be important, and not a probe */ - if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status)) + if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) nf_conntrack_event_cache(IPCT_STATUS, skb); } else - nf_ct_refresh_acct(conntrack, ctinfo, skb, nf_ct_udp_timeout); + nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout); return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ -static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb, +static int udp_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { return 1; @@ -95,7 +95,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, unsigned int hooknum) { unsigned int udplen = skb->len - dataoff; - struct udphdr _hdr, *hdr; + const struct udphdr *hdr; + struct udphdr _hdr; /* Header is too small? */ hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 070056d..9dd03c7 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -31,7 +31,8 @@ static int udplite_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { - struct udphdr _hdr, *hp; + const struct udphdr *hp; + struct udphdr _hdr; hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); if (hp == NULL) @@ -60,7 +61,7 @@ static int udplite_print_tuple(struct seq_file *s, } /* Returns verdict for packet, and may modify conntracktype */ -static int udplite_packet(struct nf_conn *conntrack, +static int udplite_packet(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info ctinfo, @@ -69,21 +70,20 @@ static int udplite_packet(struct nf_conn *conntrack, { /* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ - if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { - nf_ct_refresh_acct(conntrack, ctinfo, skb, + if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { + nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout_stream); /* Also, more likely to be important, and not a probe */ - if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status)) + if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) nf_conntrack_event_cache(IPCT_STATUS, skb); } else - nf_ct_refresh_acct(conntrack, ctinfo, skb, - nf_ct_udplite_timeout); + nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout); return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ -static int udplite_new(struct nf_conn *conntrack, const struct sk_buff *skb, +static int udplite_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { return 1; @@ -95,7 +95,8 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff, unsigned int hooknum) { unsigned int udplen = skb->len - dataoff; - struct udphdr _hdr, *hdr; + const struct udphdr *hdr; + struct udphdr _hdr; unsigned int cscov; /* Header is too small? */ diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index b5a16c6..a70051d 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -62,8 +62,9 @@ static int help(struct sk_buff *skb, enum ip_conntrack_info ctinfo) { unsigned int dataoff, datalen; - struct tcphdr _tcph, *th; - char *sb_ptr; + const struct tcphdr *th; + struct tcphdr _tcph; + void *sb_ptr; int ret = NF_ACCEPT; int dir = CTINFO2DIR(ctinfo); struct nf_ct_sane_master *ct_sane_info; @@ -99,7 +100,7 @@ static int help(struct sk_buff *skb, if (datalen != sizeof(struct sane_request)) goto out; - req = (struct sane_request *)sb_ptr; + req = sb_ptr; if (req->RPC_code != htonl(SANE_NET_START)) { /* Not an interesting command */ ct_sane_info->state = SANE_STATE_NORMAL; @@ -123,7 +124,7 @@ static int help(struct sk_buff *skb, goto out; } - reply = (struct sane_reply_net_start *)sb_ptr; + reply = sb_ptr; if (reply->status != htonl(SANE_STATUS_SUCCESS)) { /* saned refused the command */ pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 47d8947..c521c89 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -28,7 +28,7 @@ MODULE_ALIAS("ip_conntrack_sip"); #define MAX_PORTS 8 static unsigned short ports[MAX_PORTS]; -static int ports_c; +static unsigned int ports_c; module_param_array(ports, ushort, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of SIP servers"); @@ -48,10 +48,10 @@ unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, const char *dptr) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_sdp_hook); -static int digits_len(struct nf_conn *, const char *, const char *, int *); -static int epaddr_len(struct nf_conn *, const char *, const char *, int *); -static int skp_digits_len(struct nf_conn *, const char *, const char *, int *); -static int skp_epaddr_len(struct nf_conn *, const char *, const char *, int *); +static int digits_len(const struct nf_conn *, const char *, const char *, int *); +static int epaddr_len(const struct nf_conn *, const char *, const char *, int *); +static int skp_digits_len(const struct nf_conn *, const char *, const char *, int *); +static int skp_epaddr_len(const struct nf_conn *, const char *, const char *, int *); struct sip_header_nfo { const char *lname; @@ -61,7 +61,7 @@ struct sip_header_nfo { size_t snlen; size_t ln_strlen; int case_sensitive; - int (*match_len)(struct nf_conn *, const char *, + int (*match_len)(const struct nf_conn *, const char *, const char *, int *); }; @@ -225,7 +225,7 @@ const char *ct_sip_search(const char *needle, const char *haystack, } EXPORT_SYMBOL_GPL(ct_sip_search); -static int digits_len(struct nf_conn *ct, const char *dptr, +static int digits_len(const struct nf_conn *ct, const char *dptr, const char *limit, int *shift) { int len = 0; @@ -237,7 +237,7 @@ static int digits_len(struct nf_conn *ct, const char *dptr, } /* get digits length, skipping blank spaces. */ -static int skp_digits_len(struct nf_conn *ct, const char *dptr, +static int skp_digits_len(const struct nf_conn *ct, const char *dptr, const char *limit, int *shift) { for (; dptr <= limit && *dptr == ' '; dptr++) @@ -246,8 +246,9 @@ static int skp_digits_len(struct nf_conn *ct, const char *dptr, return digits_len(ct, dptr, limit, shift); } -static int parse_addr(struct nf_conn *ct, const char *cp, const char **endp, - union nf_inet_addr *addr, const char *limit) +static int parse_addr(const struct nf_conn *ct, const char *cp, + const char **endp, union nf_inet_addr *addr, + const char *limit) { const char *end; int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; @@ -272,7 +273,7 @@ static int parse_addr(struct nf_conn *ct, const char *cp, const char **endp, } /* skip ip address. returns its length. */ -static int epaddr_len(struct nf_conn *ct, const char *dptr, +static int epaddr_len(const struct nf_conn *ct, const char *dptr, const char *limit, int *shift) { union nf_inet_addr addr; @@ -292,7 +293,7 @@ static int epaddr_len(struct nf_conn *ct, const char *dptr, } /* get address length, skiping user info. */ -static int skp_epaddr_len(struct nf_conn *ct, const char *dptr, +static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr, const char *limit, int *shift) { const char *start = dptr; @@ -319,7 +320,7 @@ static int skp_epaddr_len(struct nf_conn *ct, const char *dptr, } /* Returns 0 if not found, -1 error parsing. */ -int ct_sip_get_info(struct nf_conn *ct, +int ct_sip_get_info(const struct nf_conn *ct, const char *dptr, size_t dlen, unsigned int *matchoff, unsigned int *matchlen, @@ -407,7 +408,7 @@ static int sip_help(struct sk_buff *skb, unsigned int dataoff, datalen; const char *dptr; int ret = NF_ACCEPT; - int matchoff, matchlen; + unsigned int matchoff, matchlen; u_int16_t port; enum sip_header_pos pos; typeof(nf_nat_sip_hook) nf_nat_sip; diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 696074a..e88e96a 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -31,8 +31,8 @@ MODULE_LICENSE("GPL"); #ifdef CONFIG_PROC_FS int print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, - struct nf_conntrack_l3proto *l3proto, - struct nf_conntrack_l4proto *l4proto) + const struct nf_conntrack_l3proto *l3proto, + const struct nf_conntrack_l4proto *l4proto) { return l3proto->print_tuple(s, tuple) || l4proto->print_tuple(s, tuple); } @@ -58,12 +58,14 @@ struct ct_iter_state { static struct hlist_node *ct_get_first(struct seq_file *seq) { struct ct_iter_state *st = seq->private; + struct hlist_node *n; for (st->bucket = 0; st->bucket < nf_conntrack_htable_size; st->bucket++) { - if (!hlist_empty(&nf_conntrack_hash[st->bucket])) - return nf_conntrack_hash[st->bucket].first; + n = rcu_dereference(nf_conntrack_hash[st->bucket].first); + if (n) + return n; } return NULL; } @@ -73,11 +75,11 @@ static struct hlist_node *ct_get_next(struct seq_file *seq, { struct ct_iter_state *st = seq->private; - head = head->next; + head = rcu_dereference(head->next); while (head == NULL) { if (++st->bucket >= nf_conntrack_htable_size) return NULL; - head = nf_conntrack_hash[st->bucket].first; + head = rcu_dereference(nf_conntrack_hash[st->bucket].first); } return head; } @@ -93,8 +95,9 @@ static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) } static void *ct_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) { - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); return ct_get_idx(seq, *pos); } @@ -105,79 +108,80 @@ static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) } static void ct_seq_stop(struct seq_file *s, void *v) + __releases(RCU) { - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); } /* return 0 on success, 1 in case of error */ static int ct_seq_show(struct seq_file *s, void *v) { const struct nf_conntrack_tuple_hash *hash = v; - const struct nf_conn *conntrack = nf_ct_tuplehash_to_ctrack(hash); - struct nf_conntrack_l3proto *l3proto; - struct nf_conntrack_l4proto *l4proto; + const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); + const struct nf_conntrack_l3proto *l3proto; + const struct nf_conntrack_l4proto *l4proto; - NF_CT_ASSERT(conntrack); + NF_CT_ASSERT(ct); /* we only want to print DIR_ORIGINAL */ if (NF_CT_DIRECTION(hash)) return 0; - l3proto = __nf_ct_l3proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] + l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.src.l3num); NF_CT_ASSERT(l3proto); - l4proto = __nf_ct_l4proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] + l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.src.l3num, - conntrack->tuplehash[IP_CT_DIR_ORIGINAL] + ct->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.dst.protonum); NF_CT_ASSERT(l4proto); if (seq_printf(s, "%-8s %u %-8s %u %ld ", l3proto->name, - conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, l4proto->name, - conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum, - timer_pending(&conntrack->timeout) - ? (long)(conntrack->timeout.expires - jiffies)/HZ : 0) != 0) + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum, + timer_pending(&ct->timeout) + ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) return -ENOSPC; - if (l4proto->print_conntrack && l4proto->print_conntrack(s, conntrack)) + if (l4proto->print_conntrack && l4proto->print_conntrack(s, ct)) return -ENOSPC; - if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple, + if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, l3proto, l4proto)) return -ENOSPC; - if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL])) + if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) return -ENOSPC; - if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status))) + if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) if (seq_printf(s, "[UNREPLIED] ")) return -ENOSPC; - if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple, + if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, l3proto, l4proto)) return -ENOSPC; - if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY])) + if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) return -ENOSPC; - if (test_bit(IPS_ASSURED_BIT, &conntrack->status)) + if (test_bit(IPS_ASSURED_BIT, &ct->status)) if (seq_printf(s, "[ASSURED] ")) return -ENOSPC; #if defined(CONFIG_NF_CONNTRACK_MARK) - if (seq_printf(s, "mark=%u ", conntrack->mark)) + if (seq_printf(s, "mark=%u ", ct->mark)) return -ENOSPC; #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK - if (seq_printf(s, "secmark=%u ", conntrack->secmark)) + if (seq_printf(s, "secmark=%u ", ct->secmark)) return -ENOSPC; #endif - if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use))) + if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) return -ENOSPC; return 0; @@ -242,7 +246,7 @@ static void ct_cpu_seq_stop(struct seq_file *seq, void *v) static int ct_cpu_seq_show(struct seq_file *seq, void *v) { unsigned int nr_conntracks = atomic_read(&nf_conntrack_count); - struct ip_conntrack_stat *st = v; + const struct ip_conntrack_stat *st = v; if (v == SEQ_START_TOKEN) { seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n"); @@ -380,7 +384,7 @@ static ctl_table nf_ct_netfilter_table[] = { { .ctl_name = 0 } }; -struct ctl_path nf_ct_path[] = { +static struct ctl_path nf_ct_path[] = { { .procname = "net", .ctl_name = CTL_NET, }, { } }; diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index e894aa1f..bd2e800 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c @@ -25,7 +25,7 @@ MODULE_ALIAS("ip_conntrack_tftp"); #define MAX_PORTS 8 static unsigned short ports[MAX_PORTS]; -static int ports_c; +static unsigned int ports_c; module_param_array(ports, ushort, &ports_c, 0400); MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); @@ -39,7 +39,8 @@ static int tftp_help(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { - struct tftphdr _tftph, *tfh; + const struct tftphdr *tfh; + struct tftphdr _tftph; struct nf_conntrack_expect *exp; struct nf_conntrack_tuple *tuple; unsigned int ret = NF_ACCEPT; diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 4f5f288..cec9976 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -103,6 +103,7 @@ EXPORT_SYMBOL(nf_log_packet); #ifdef CONFIG_PROC_FS static void *seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) { rcu_read_lock(); @@ -123,6 +124,7 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos) } static void seq_stop(struct seq_file *s, void *v) + __releases(RCU) { rcu_read_unlock(); } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 5013cb9..7efa40d 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -467,7 +467,7 @@ __build_packet_message(struct nfulnl_instance *inst, read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) { __be32 uid = htonl(skb->sk->sk_socket->file->f_uid); - __be32 gid = htons(skb->sk->sk_socket->file->f_gid); + __be32 gid = htonl(skb->sk->sk_socket->file->f_gid); /* need to unlock here since NLA_PUT may goto */ read_unlock_bh(&skb->sk->sk_callback_lock); NLA_PUT_BE32(inst->skb, NFULA_UID, uid); @@ -866,6 +866,7 @@ static struct hlist_node *get_idx(struct iter_state *st, loff_t pos) } static void *seq_start(struct seq_file *seq, loff_t *pos) + __acquires(instances_lock) { read_lock_bh(&instances_lock); return get_idx(seq->private, *pos); @@ -878,6 +879,7 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos) } static void seq_stop(struct seq_file *s, void *v) + __releases(instances_lock) { read_unlock_bh(&instances_lock); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 51476f8..a48b20f 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -360,7 +360,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (data_len) { struct nlattr *nla; - int size = nla_attr_size(data_len); + int sz = nla_attr_size(data_len); if (skb_tailroom(skb) < nla_total_size(data_len)) { printk(KERN_WARNING "nf_queue: no tailroom!\n"); @@ -369,7 +369,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, nla = (struct nlattr *)skb_put(skb, nla_total_size(data_len)); nla->nla_type = NFQA_PAYLOAD; - nla->nla_len = size; + nla->nla_len = sz; if (skb_copy_bits(entskb, 0, nla_data(nla), data_len)) BUG(); @@ -845,6 +845,7 @@ static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) } static void *seq_start(struct seq_file *seq, loff_t *pos) + __acquires(instances_lock) { spin_lock(&instances_lock); return get_idx(seq, *pos); @@ -857,6 +858,7 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos) } static void seq_stop(struct seq_file *s, void *v) + __releases(instances_lock) { spin_unlock(&instances_lock); } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 8d4fca9..a679208 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -44,7 +44,6 @@ struct xt_af { struct mutex mutex; struct list_head match; struct list_head target; - struct list_head tables; #ifdef CONFIG_COMPAT struct mutex compat_mutex; struct compat_delta *compat_offsets; @@ -59,12 +58,6 @@ static struct xt_af *xt; #define duprintf(format, args...) #endif -enum { - TABLE, - TARGET, - MATCH, -}; - static const char *xt_prefix[NPROTO] = { [AF_INET] = "ip", [AF_INET6] = "ip6", @@ -400,7 +393,7 @@ int xt_compat_match_offset(struct xt_match *match) EXPORT_SYMBOL_GPL(xt_compat_match_offset); int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, - int *size) + unsigned int *size) { struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; @@ -427,7 +420,7 @@ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, EXPORT_SYMBOL_GPL(xt_compat_match_from_user); int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr, - int *size) + unsigned int *size) { struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match __user *cm = *dstptr; @@ -494,7 +487,7 @@ int xt_compat_target_offset(struct xt_target *target) EXPORT_SYMBOL_GPL(xt_compat_target_offset); void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, - int *size) + unsigned int *size) { struct xt_target *target = t->u.kernel.target; struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; @@ -520,7 +513,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, EXPORT_SYMBOL_GPL(xt_compat_target_from_user); int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr, - int *size) + unsigned int *size) { struct xt_target *target = t->u.kernel.target; struct compat_xt_entry_target __user *ct = *dstptr; @@ -597,14 +590,14 @@ void xt_free_table_info(struct xt_table_info *info) EXPORT_SYMBOL(xt_free_table_info); /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ -struct xt_table *xt_find_table_lock(int af, const char *name) +struct xt_table *xt_find_table_lock(struct net *net, int af, const char *name) { struct xt_table *t; if (mutex_lock_interruptible(&xt[af].mutex) != 0) return ERR_PTR(-EINTR); - list_for_each_entry(t, &xt[af].tables, list) + list_for_each_entry(t, &net->xt.tables[af], list) if (strcmp(t->name, name) == 0 && try_module_get(t->me)) return t; mutex_unlock(&xt[af].mutex); @@ -660,20 +653,27 @@ xt_replace_table(struct xt_table *table, } EXPORT_SYMBOL_GPL(xt_replace_table); -int xt_register_table(struct xt_table *table, - struct xt_table_info *bootstrap, - struct xt_table_info *newinfo) +struct xt_table *xt_register_table(struct net *net, struct xt_table *table, + struct xt_table_info *bootstrap, + struct xt_table_info *newinfo) { int ret; struct xt_table_info *private; struct xt_table *t; + /* Don't add one object to multiple lists. */ + table = kmemdup(table, sizeof(struct xt_table), GFP_KERNEL); + if (!table) { + ret = -ENOMEM; + goto out; + } + ret = mutex_lock_interruptible(&xt[table->af].mutex); if (ret != 0) - return ret; + goto out_free; /* Don't autoload: we'd eat our tail... */ - list_for_each_entry(t, &xt[table->af].tables, list) { + list_for_each_entry(t, &net->xt.tables[table->af], list) { if (strcmp(t->name, table->name) == 0) { ret = -EEXIST; goto unlock; @@ -692,12 +692,16 @@ int xt_register_table(struct xt_table *table, /* save number of initial entries */ private->initial_entries = private->number; - list_add(&table->list, &xt[table->af].tables); + list_add(&table->list, &net->xt.tables[table->af]); + mutex_unlock(&xt[table->af].mutex); + return table; - ret = 0; unlock: mutex_unlock(&xt[table->af].mutex); - return ret; +out_free: + kfree(table); +out: + return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(xt_register_table); @@ -709,130 +713,204 @@ void *xt_unregister_table(struct xt_table *table) private = table->private; list_del(&table->list); mutex_unlock(&xt[table->af].mutex); + kfree(table); return private; } EXPORT_SYMBOL_GPL(xt_unregister_table); #ifdef CONFIG_PROC_FS -static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos) +struct xt_names_priv { + struct seq_net_private p; + int af; +}; +static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos) { - struct list_head *head = list->next; + struct xt_names_priv *priv = seq->private; + struct net *net = priv->p.net; + int af = priv->af; - if (!head || list_empty(list)) - return NULL; + mutex_lock(&xt[af].mutex); + return seq_list_start(&net->xt.tables[af], *pos); +} - while (pos && (head = head->next)) { - if (head == list) - return NULL; - pos--; - } - return pos ? NULL : head; -} - -static struct list_head *type2list(u_int16_t af, u_int16_t type) -{ - struct list_head *list; - - switch (type) { - case TARGET: - list = &xt[af].target; - break; - case MATCH: - list = &xt[af].match; - break; - case TABLE: - list = &xt[af].tables; - break; - default: - list = NULL; - break; - } +static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct xt_names_priv *priv = seq->private; + struct net *net = priv->p.net; + int af = priv->af; - return list; + return seq_list_next(v, &net->xt.tables[af], pos); } -static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos) +static void xt_table_seq_stop(struct seq_file *seq, void *v) { - struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private; - u_int16_t af = (unsigned long)pde->data & 0xffff; - u_int16_t type = (unsigned long)pde->data >> 16; - struct list_head *list; + struct xt_names_priv *priv = seq->private; + int af = priv->af; - if (af >= NPROTO) - return NULL; + mutex_unlock(&xt[af].mutex); +} - list = type2list(af, type); - if (!list) - return NULL; +static int xt_table_seq_show(struct seq_file *seq, void *v) +{ + struct xt_table *table = list_entry(v, struct xt_table, list); - if (mutex_lock_interruptible(&xt[af].mutex) != 0) - return NULL; + if (strlen(table->name)) + return seq_printf(seq, "%s\n", table->name); + else + return 0; +} + +static const struct seq_operations xt_table_seq_ops = { + .start = xt_table_seq_start, + .next = xt_table_seq_next, + .stop = xt_table_seq_stop, + .show = xt_table_seq_show, +}; - return xt_get_idx(list, seq, *pos); +static int xt_table_open(struct inode *inode, struct file *file) +{ + int ret; + struct xt_names_priv *priv; + + ret = seq_open_net(inode, file, &xt_table_seq_ops, + sizeof(struct xt_names_priv)); + if (!ret) { + priv = ((struct seq_file *)file->private_data)->private; + priv->af = (unsigned long)PDE(inode)->data; + } + return ret; } -static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static const struct file_operations xt_table_ops = { + .owner = THIS_MODULE, + .open = xt_table_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) { - struct proc_dir_entry *pde = seq->private; - u_int16_t af = (unsigned long)pde->data & 0xffff; - u_int16_t type = (unsigned long)pde->data >> 16; - struct list_head *list; + struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; + u_int16_t af = (unsigned long)pde->data; - if (af >= NPROTO) - return NULL; + mutex_lock(&xt[af].mutex); + return seq_list_start(&xt[af].match, *pos); +} - list = type2list(af, type); - if (!list) - return NULL; +static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; + u_int16_t af = (unsigned long)pde->data; - (*pos)++; - return xt_get_idx(list, seq, *pos); + return seq_list_next(v, &xt[af].match, pos); } -static void xt_tgt_seq_stop(struct seq_file *seq, void *v) +static void xt_match_seq_stop(struct seq_file *seq, void *v) { struct proc_dir_entry *pde = seq->private; - u_int16_t af = (unsigned long)pde->data & 0xffff; + u_int16_t af = (unsigned long)pde->data; mutex_unlock(&xt[af].mutex); } -static int xt_name_seq_show(struct seq_file *seq, void *v) +static int xt_match_seq_show(struct seq_file *seq, void *v) { - char *name = (char *)v + sizeof(struct list_head); + struct xt_match *match = list_entry(v, struct xt_match, list); - if (strlen(name)) - return seq_printf(seq, "%s\n", name); + if (strlen(match->name)) + return seq_printf(seq, "%s\n", match->name); else return 0; } -static const struct seq_operations xt_tgt_seq_ops = { - .start = xt_tgt_seq_start, - .next = xt_tgt_seq_next, - .stop = xt_tgt_seq_stop, - .show = xt_name_seq_show, +static const struct seq_operations xt_match_seq_ops = { + .start = xt_match_seq_start, + .next = xt_match_seq_next, + .stop = xt_match_seq_stop, + .show = xt_match_seq_show, }; -static int xt_tgt_open(struct inode *inode, struct file *file) +static int xt_match_open(struct inode *inode, struct file *file) { int ret; - ret = seq_open(file, &xt_tgt_seq_ops); + ret = seq_open(file, &xt_match_seq_ops); if (!ret) { struct seq_file *seq = file->private_data; - struct proc_dir_entry *pde = PDE(inode); - seq->private = pde; + seq->private = PDE(inode); } + return ret; +} + +static const struct file_operations xt_match_ops = { + .owner = THIS_MODULE, + .open = xt_match_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; + u_int16_t af = (unsigned long)pde->data; + + mutex_lock(&xt[af].mutex); + return seq_list_start(&xt[af].target, *pos); +} + +static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; + u_int16_t af = (unsigned long)pde->data; + + return seq_list_next(v, &xt[af].target, pos); +} + +static void xt_target_seq_stop(struct seq_file *seq, void *v) +{ + struct proc_dir_entry *pde = seq->private; + u_int16_t af = (unsigned long)pde->data; + + mutex_unlock(&xt[af].mutex); +} +static int xt_target_seq_show(struct seq_file *seq, void *v) +{ + struct xt_target *target = list_entry(v, struct xt_target, list); + + if (strlen(target->name)) + return seq_printf(seq, "%s\n", target->name); + else + return 0; +} + +static const struct seq_operations xt_target_seq_ops = { + .start = xt_target_seq_start, + .next = xt_target_seq_next, + .stop = xt_target_seq_stop, + .show = xt_target_seq_show, +}; + +static int xt_target_open(struct inode *inode, struct file *file) +{ + int ret; + + ret = seq_open(file, &xt_target_seq_ops); + if (!ret) { + struct seq_file *seq = file->private_data; + + seq->private = PDE(inode); + } return ret; } -static const struct file_operations xt_file_ops = { +static const struct file_operations xt_target_ops = { .owner = THIS_MODULE, - .open = xt_tgt_open, + .open = xt_target_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, @@ -844,7 +922,7 @@ static const struct file_operations xt_file_ops = { #endif /* CONFIG_PROC_FS */ -int xt_proto_init(int af) +int xt_proto_init(struct net *net, int af) { #ifdef CONFIG_PROC_FS char buf[XT_FUNCTION_MAXNAMELEN]; @@ -858,25 +936,25 @@ int xt_proto_init(int af) #ifdef CONFIG_PROC_FS strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_TABLES, sizeof(buf)); - proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops); + proc = proc_net_fops_create(net, buf, 0440, &xt_table_ops); if (!proc) goto out; - proc->data = (void *) ((unsigned long) af | (TABLE << 16)); + proc->data = (void *)(unsigned long)af; strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_MATCHES, sizeof(buf)); - proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops); + proc = proc_net_fops_create(net, buf, 0440, &xt_match_ops); if (!proc) goto out_remove_tables; - proc->data = (void *) ((unsigned long) af | (MATCH << 16)); + proc->data = (void *)(unsigned long)af; strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_TARGETS, sizeof(buf)); - proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops); + proc = proc_net_fops_create(net, buf, 0440, &xt_target_ops); if (!proc) goto out_remove_matches; - proc->data = (void *) ((unsigned long) af | (TARGET << 16)); + proc->data = (void *)(unsigned long)af; #endif return 0; @@ -885,42 +963,54 @@ int xt_proto_init(int af) out_remove_matches: strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_MATCHES, sizeof(buf)); - proc_net_remove(&init_net, buf); + proc_net_remove(net, buf); out_remove_tables: strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_TABLES, sizeof(buf)); - proc_net_remove(&init_net, buf); + proc_net_remove(net, buf); out: return -1; #endif } EXPORT_SYMBOL_GPL(xt_proto_init); -void xt_proto_fini(int af) +void xt_proto_fini(struct net *net, int af) { #ifdef CONFIG_PROC_FS char buf[XT_FUNCTION_MAXNAMELEN]; strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_TABLES, sizeof(buf)); - proc_net_remove(&init_net, buf); + proc_net_remove(net, buf); strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_TARGETS, sizeof(buf)); - proc_net_remove(&init_net, buf); + proc_net_remove(net, buf); strlcpy(buf, xt_prefix[af], sizeof(buf)); strlcat(buf, FORMAT_MATCHES, sizeof(buf)); - proc_net_remove(&init_net, buf); + proc_net_remove(net, buf); #endif /*CONFIG_PROC_FS*/ } EXPORT_SYMBOL_GPL(xt_proto_fini); +static int __net_init xt_net_init(struct net *net) +{ + int i; + + for (i = 0; i < NPROTO; i++) + INIT_LIST_HEAD(&net->xt.tables[i]); + return 0; +} + +static struct pernet_operations xt_net_ops = { + .init = xt_net_init, +}; static int __init xt_init(void) { - int i; + int i, rv; xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL); if (!xt) @@ -934,13 +1024,16 @@ static int __init xt_init(void) #endif INIT_LIST_HEAD(&xt[i].target); INIT_LIST_HEAD(&xt[i].match); - INIT_LIST_HEAD(&xt[i].tables); } - return 0; + rv = register_pernet_subsys(&xt_net_ops); + if (rv < 0) + kfree(xt); + return rv; } static void __exit xt_fini(void) { + unregister_pernet_subsys(&xt_net_ops); kfree(xt); } diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 60e3767..217e2b6 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -13,7 +13,10 @@ #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/tcp.h> +#include <net/dst.h> +#include <net/flow.h> #include <net/ipv6.h> +#include <net/route.h> #include <net/tcp.h> #include <linux/netfilter_ipv4/ip_tables.h> @@ -41,6 +44,7 @@ optlen(const u_int8_t *opt, unsigned int offset) static int tcpmss_mangle_packet(struct sk_buff *skb, const struct xt_tcpmss_info *info, + unsigned int in_mtu, unsigned int tcphoff, unsigned int minlen) { @@ -76,7 +80,13 @@ tcpmss_mangle_packet(struct sk_buff *skb, dst_mtu(skb->dst)); return -1; } - newmss = dst_mtu(skb->dst) - minlen; + if (in_mtu <= minlen) { + if (net_ratelimit()) + printk(KERN_ERR "xt_TCPMSS: unknown or " + "invalid path-MTU (%u)\n", in_mtu); + return -1; + } + newmss = min(dst_mtu(skb->dst), in_mtu) - minlen; } else newmss = info->mss; @@ -137,6 +147,28 @@ tcpmss_mangle_packet(struct sk_buff *skb, return TCPOLEN_MSS; } +static u_int32_t tcpmss_reverse_mtu4(const struct iphdr *iph) +{ + struct flowi fl = { + .fl4_dst = iph->saddr, + }; + const struct nf_afinfo *ai; + struct rtable *rt = NULL; + u_int32_t mtu = ~0U; + + rcu_read_lock(); + ai = nf_get_afinfo(AF_INET); + if (ai != NULL) + ai->route((struct dst_entry **)&rt, &fl); + rcu_read_unlock(); + + if (rt != NULL) { + mtu = dst_mtu(&rt->u.dst); + dst_release(&rt->u.dst); + } + return mtu; +} + static unsigned int tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, @@ -146,7 +178,8 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, __be16 newlen; int ret; - ret = tcpmss_mangle_packet(skb, targinfo, iph->ihl * 4, + ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu4(iph), + iph->ihl * 4, sizeof(*iph) + sizeof(struct tcphdr)); if (ret < 0) return NF_DROP; @@ -160,6 +193,28 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in, } #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) +static u_int32_t tcpmss_reverse_mtu6(const struct ipv6hdr *iph) +{ + struct flowi fl = { + .fl6_dst = iph->saddr, + }; + const struct nf_afinfo *ai; + struct rtable *rt = NULL; + u_int32_t mtu = ~0U; + + rcu_read_lock(); + ai = nf_get_afinfo(AF_INET6); + if (ai != NULL) + ai->route((struct dst_entry **)&rt, &fl); + rcu_read_unlock(); + + if (rt != NULL) { + mtu = dst_mtu(&rt->u.dst); + dst_release(&rt->u.dst); + } + return mtu; +} + static unsigned int tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, @@ -174,7 +229,8 @@ tcpmss_tg6(struct sk_buff *skb, const struct net_device *in, tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); if (tcphoff < 0) return NF_DROP; - ret = tcpmss_mangle_packet(skb, targinfo, tcphoff, + ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu6(ipv6h), + tcphoff, sizeof(*ipv6h) + sizeof(struct tcphdr)); if (ret < 0) return NF_DROP; diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index e00ecd9..3b01119 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -120,11 +120,11 @@ static int count_them(struct xt_connlimit_data *data, else hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; - read_lock_bh(&nf_conntrack_lock); + rcu_read_lock(); /* check the saved connections */ list_for_each_entry_safe(conn, tmp, hash, list) { - found = __nf_conntrack_find(&conn->tuple, NULL); + found = __nf_conntrack_find(&conn->tuple); found_ct = NULL; if (found != NULL) @@ -163,7 +163,7 @@ static int count_them(struct xt_connlimit_data *data, ++matches; } - read_unlock_bh(&nf_conntrack_lock); + rcu_read_unlock(); if (addit) { /* save the new connection in our list */ diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index e92190e..8533085 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -4,7 +4,6 @@ * * (C) 2001 Marc Boucher (marc@mbsi.ca). * Copyright © CC Computer Consultants GmbH, 2007 - 2008 - * Jan Engelhardt <jengelh@computergmbh.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,6 +19,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); +MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); MODULE_DESCRIPTION("Xtables: connection tracking state match"); MODULE_ALIAS("ipt_conntrack"); MODULE_ALIAS("ip6t_conntrack"); @@ -166,6 +166,44 @@ conntrack_mt_repldst(const struct nf_conn *ct, &info->repldst_addr, &info->repldst_mask, family); } +static inline bool +ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, + const struct nf_conn *ct) +{ + const struct nf_conntrack_tuple *tuple; + + tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + if ((info->match_flags & XT_CONNTRACK_PROTO) && + (tuple->dst.protonum == info->l4proto) ^ + !(info->invert_flags & XT_CONNTRACK_PROTO)) + return false; + + /* Shortcut to match all recognized protocols by using ->src.all. */ + if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) && + (tuple->src.u.all == info->origsrc_port) ^ + !(info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT)) + return false; + + if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) && + (tuple->dst.u.all == info->origdst_port) ^ + !(info->invert_flags & XT_CONNTRACK_ORIGDST_PORT)) + return false; + + tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; + + if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) && + (tuple->src.u.all == info->replsrc_port) ^ + !(info->invert_flags & XT_CONNTRACK_REPLSRC_PORT)) + return false; + + if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) && + (tuple->dst.u.all == info->repldst_port) ^ + !(info->invert_flags & XT_CONNTRACK_REPLDST_PORT)) + return false; + + return true; +} + static bool conntrack_mt(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct xt_match *match, @@ -200,10 +238,9 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in, if (ct == NULL) return info->match_flags & XT_CONNTRACK_STATE; - - if ((info->match_flags & XT_CONNTRACK_PROTO) && - ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == - info->l4proto) ^ !(info->invert_flags & XT_CONNTRACK_PROTO))) + if ((info->match_flags & XT_CONNTRACK_DIRECTION) && + (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^ + !!(info->invert_flags & XT_CONNTRACK_DIRECTION)) return false; if (info->match_flags & XT_CONNTRACK_ORIGSRC) @@ -226,6 +263,9 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in, !(info->invert_flags & XT_CONNTRACK_REPLDST)) return false; + if (!ct_proto_port_check(info, ct)) + return false; + if ((info->match_flags & XT_CONNTRACK_STATUS) && (!!(info->status_mask & ct->status) ^ !(info->invert_flags & XT_CONNTRACK_STATUS))) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index d479ca9..744c7f2 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -1,9 +1,9 @@ -/* iptables match extension to limit the number of packets per second - * seperately for each hashbucket (sourceip/sourceport/dstip/dstport) +/* + * xt_hashlimit - Netfilter module to limit the number of packets per time + * seperately for each hashbucket (sourceip/sourceport/dstip/dstport) * - * (C) 2003-2004 by Harald Welte <laforge@netfilter.org> - * - * $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $ + * (C) 2003-2004 by Harald Welte <laforge@netfilter.org> + * Copyright © CC Computer Consultants GmbH, 2007 - 2008 * * Development of this code was funded by Astaro AG, http://www.astaro.com/ */ @@ -35,6 +35,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); +MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match"); MODULE_ALIAS("ipt_hashlimit"); MODULE_ALIAS("ip6t_hashlimit"); @@ -57,7 +58,7 @@ struct dsthash_dst { __be32 dst[4]; } ip6; #endif - } addr; + }; __be16 src_port; __be16 dst_port; }; @@ -81,7 +82,7 @@ struct xt_hashlimit_htable { atomic_t use; int family; - struct hashlimit_cfg cfg; /* config */ + struct hashlimit_cfg1 cfg; /* config */ /* used internally */ spinlock_t lock; /* lock for list_head */ @@ -184,7 +185,7 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) } static void htable_gc(unsigned long htlong); -static int htable_create(struct xt_hashlimit_info *minfo, int family) +static int htable_create_v0(struct xt_hashlimit_info *minfo, int family) { struct xt_hashlimit_htable *hinfo; unsigned int size; @@ -210,7 +211,18 @@ static int htable_create(struct xt_hashlimit_info *minfo, int family) minfo->hinfo = hinfo; /* copy match config into hashtable config */ - memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg)); + hinfo->cfg.mode = minfo->cfg.mode; + hinfo->cfg.avg = minfo->cfg.avg; + hinfo->cfg.burst = minfo->cfg.burst; + hinfo->cfg.max = minfo->cfg.max; + hinfo->cfg.gc_interval = minfo->cfg.gc_interval; + hinfo->cfg.expire = minfo->cfg.expire; + + if (family == AF_INET) + hinfo->cfg.srcmask = hinfo->cfg.dstmask = 32; + else + hinfo->cfg.srcmask = hinfo->cfg.dstmask = 128; + hinfo->cfg.size = size; if (!hinfo->cfg.max) hinfo->cfg.max = 8 * hinfo->cfg.size; @@ -246,6 +258,70 @@ static int htable_create(struct xt_hashlimit_info *minfo, int family) return 0; } +static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, + unsigned int family) +{ + struct xt_hashlimit_htable *hinfo; + unsigned int size; + unsigned int i; + + if (minfo->cfg.size) { + size = minfo->cfg.size; + } else { + size = (num_physpages << PAGE_SHIFT) / 16384 / + sizeof(struct list_head); + if (num_physpages > 1024 * 1024 * 1024 / PAGE_SIZE) + size = 8192; + if (size < 16) + size = 16; + } + /* FIXME: don't use vmalloc() here or anywhere else -HW */ + hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) + + sizeof(struct list_head) * size); + if (hinfo == NULL) { + printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n"); + return -1; + } + minfo->hinfo = hinfo; + + /* copy match config into hashtable config */ + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg)); + hinfo->cfg.size = size; + if (hinfo->cfg.max == 0) + hinfo->cfg.max = 8 * hinfo->cfg.size; + else if (hinfo->cfg.max < hinfo->cfg.size) + hinfo->cfg.max = hinfo->cfg.size; + + for (i = 0; i < hinfo->cfg.size; i++) + INIT_HLIST_HEAD(&hinfo->hash[i]); + + atomic_set(&hinfo->use, 1); + hinfo->count = 0; + hinfo->family = family; + hinfo->rnd_initialized = 0; + spin_lock_init(&hinfo->lock); + + hinfo->pde = create_proc_entry(minfo->name, 0, + family == AF_INET ? hashlimit_procdir4 : + hashlimit_procdir6); + if (hinfo->pde == NULL) { + vfree(hinfo); + return -1; + } + hinfo->pde->proc_fops = &dl_file_ops; + hinfo->pde->data = hinfo; + + setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); + hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); + add_timer(&hinfo->timer); + + spin_lock_bh(&hashlimit_lock); + hlist_add_head(&hinfo->node, &hashlimit_htables); + spin_unlock_bh(&hashlimit_lock); + + return 0; +} + static bool select_all(const struct xt_hashlimit_htable *ht, const struct dsthash_ent *he) { @@ -388,6 +464,48 @@ static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) dh->rateinfo.prev = now; } +static inline __be32 maskl(__be32 a, unsigned int l) +{ + return htonl(ntohl(a) & ~(~(u_int32_t)0 >> l)); +} + +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) +static void hashlimit_ipv6_mask(__be32 *i, unsigned int p) +{ + switch (p) { + case 0: + i[0] = i[1] = 0; + i[2] = i[3] = 0; + break; + case 1 ... 31: + i[0] = maskl(i[0], p); + i[1] = i[2] = i[3] = 0; + break; + case 32: + i[1] = i[2] = i[3] = 0; + break; + case 33 ... 63: + i[1] = maskl(i[1], p - 32); + i[2] = i[3] = 0; + break; + case 64: + i[2] = i[3] = 0; + break; + case 65 ... 95: + i[2] = maskl(i[2], p - 64); + i[3] = 0; + case 96: + i[3] = 0; + break; + case 97 ... 127: + i[3] = maskl(i[3], p - 96); + break; + case 128: + break; + } +} +#endif + static int hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst, @@ -401,9 +519,11 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, switch (hinfo->family) { case AF_INET: if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) - dst->addr.ip.dst = ip_hdr(skb)->daddr; + dst->ip.dst = maskl(ip_hdr(skb)->daddr, + hinfo->cfg.dstmask); if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) - dst->addr.ip.src = ip_hdr(skb)->saddr; + dst->ip.src = maskl(ip_hdr(skb)->saddr, + hinfo->cfg.srcmask); if (!(hinfo->cfg.mode & (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) @@ -412,12 +532,16 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, break; #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) case AF_INET6: - if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) - memcpy(&dst->addr.ip6.dst, &ipv6_hdr(skb)->daddr, - sizeof(dst->addr.ip6.dst)); - if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) - memcpy(&dst->addr.ip6.src, &ipv6_hdr(skb)->saddr, - sizeof(dst->addr.ip6.src)); + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) { + memcpy(&dst->ip6.dst, &ipv6_hdr(skb)->daddr, + sizeof(dst->ip6.dst)); + hashlimit_ipv6_mask(dst->ip6.dst, hinfo->cfg.dstmask); + } + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) { + memcpy(&dst->ip6.src, &ipv6_hdr(skb)->saddr, + sizeof(dst->ip6.src)); + hashlimit_ipv6_mask(dst->ip6.src, hinfo->cfg.srcmask); + } if (!(hinfo->cfg.mode & (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) @@ -457,10 +581,10 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, } static bool -hashlimit_mt(const struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, const struct xt_match *match, - const void *matchinfo, int offset, unsigned int protoff, - bool *hotdrop) +hashlimit_mt_v0(const struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, const struct xt_match *match, + const void *matchinfo, int offset, unsigned int protoff, + bool *hotdrop) { const struct xt_hashlimit_info *r = ((const struct xt_hashlimit_info *)matchinfo)->u.master; @@ -512,9 +636,62 @@ hotdrop: } static bool -hashlimit_mt_check(const char *tablename, const void *inf, - const struct xt_match *match, void *matchinfo, - unsigned int hook_mask) +hashlimit_mt(const struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, const struct xt_match *match, + const void *matchinfo, int offset, unsigned int protoff, + bool *hotdrop) +{ + const struct xt_hashlimit_mtinfo1 *info = matchinfo; + struct xt_hashlimit_htable *hinfo = info->hinfo; + unsigned long now = jiffies; + struct dsthash_ent *dh; + struct dsthash_dst dst; + + if (hashlimit_init_dst(hinfo, &dst, skb, protoff) < 0) + goto hotdrop; + + spin_lock_bh(&hinfo->lock); + dh = dsthash_find(hinfo, &dst); + if (dh == NULL) { + dh = dsthash_alloc_init(hinfo, &dst); + if (dh == NULL) { + spin_unlock_bh(&hinfo->lock); + goto hotdrop; + } + + dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); + dh->rateinfo.prev = jiffies; + dh->rateinfo.credit = user2credits(hinfo->cfg.avg * + hinfo->cfg.burst); + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * + hinfo->cfg.burst); + dh->rateinfo.cost = user2credits(hinfo->cfg.avg); + } else { + /* update expiration timeout */ + dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); + rateinfo_recalc(dh, now); + } + + if (dh->rateinfo.credit >= dh->rateinfo.cost) { + /* below the limit */ + dh->rateinfo.credit -= dh->rateinfo.cost; + spin_unlock_bh(&hinfo->lock); + return !(info->cfg.mode & XT_HASHLIMIT_INVERT); + } + + spin_unlock_bh(&hinfo->lock); + /* default match is underlimit - so over the limit, we need to invert */ + return info->cfg.mode & XT_HASHLIMIT_INVERT; + + hotdrop: + *hotdrop = true; + return false; +} + +static bool +hashlimit_mt_check_v0(const char *tablename, const void *inf, + const struct xt_match *match, void *matchinfo, + unsigned int hook_mask) { struct xt_hashlimit_info *r = matchinfo; @@ -546,7 +723,7 @@ hashlimit_mt_check(const char *tablename, const void *inf, * create duplicate proc files. -HW */ mutex_lock(&hlimit_mutex); r->hinfo = htable_find_get(r->name, match->family); - if (!r->hinfo && htable_create(r, match->family) != 0) { + if (!r->hinfo && htable_create_v0(r, match->family) != 0) { mutex_unlock(&hlimit_mutex); return false; } @@ -557,14 +734,68 @@ hashlimit_mt_check(const char *tablename, const void *inf, return true; } +static bool +hashlimit_mt_check(const char *tablename, const void *inf, + const struct xt_match *match, void *matchinfo, + unsigned int hook_mask) +{ + struct xt_hashlimit_mtinfo1 *info = matchinfo; + + /* Check for overflow. */ + if (info->cfg.burst == 0 || + user2credits(info->cfg.avg * info->cfg.burst) < + user2credits(info->cfg.avg)) { + printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n", + info->cfg.avg, info->cfg.burst); + return false; + } + if (info->cfg.gc_interval == 0 || info->cfg.expire == 0) + return false; + if (info->name[sizeof(info->name)-1] != '\0') + return false; + if (match->family == AF_INET) { + if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32) + return false; + } else { + if (info->cfg.srcmask > 128 || info->cfg.dstmask > 128) + return false; + } + + /* This is the best we've got: We cannot release and re-grab lock, + * since checkentry() is called before x_tables.c grabs xt_mutex. + * We also cannot grab the hashtable spinlock, since htable_create will + * call vmalloc, and that can sleep. And we cannot just re-search + * the list of htable's in htable_create(), since then we would + * create duplicate proc files. -HW */ + mutex_lock(&hlimit_mutex); + info->hinfo = htable_find_get(info->name, match->family); + if (!info->hinfo && htable_create(info, match->family) != 0) { + mutex_unlock(&hlimit_mutex); + return false; + } + mutex_unlock(&hlimit_mutex); + + /* Ugly hack: For SMP, we only want to use one set */ + info->master = info; + return true; +} + static void -hashlimit_mt_destroy(const struct xt_match *match, void *matchinfo) +hashlimit_mt_destroy_v0(const struct xt_match *match, void *matchinfo) { const struct xt_hashlimit_info *r = matchinfo; htable_put(r->hinfo); } +static void +hashlimit_mt_destroy(const struct xt_match *match, void *matchinfo) +{ + const struct xt_hashlimit_mtinfo1 *info = matchinfo; + + htable_put(info->hinfo); +} + #ifdef CONFIG_COMPAT struct compat_xt_hashlimit_info { char name[IFNAMSIZ]; @@ -592,38 +823,60 @@ static int hashlimit_mt_compat_to_user(void __user *dst, void *src) static struct xt_match hashlimit_mt_reg[] __read_mostly = { { .name = "hashlimit", + .revision = 0, .family = AF_INET, - .match = hashlimit_mt, + .match = hashlimit_mt_v0, .matchsize = sizeof(struct xt_hashlimit_info), #ifdef CONFIG_COMPAT .compatsize = sizeof(struct compat_xt_hashlimit_info), .compat_from_user = hashlimit_mt_compat_from_user, .compat_to_user = hashlimit_mt_compat_to_user, #endif - .checkentry = hashlimit_mt_check, - .destroy = hashlimit_mt_destroy, + .checkentry = hashlimit_mt_check_v0, + .destroy = hashlimit_mt_destroy_v0, .me = THIS_MODULE }, + { + .name = "hashlimit", + .revision = 1, + .family = AF_INET, + .match = hashlimit_mt, + .matchsize = sizeof(struct xt_hashlimit_mtinfo1), + .checkentry = hashlimit_mt_check, + .destroy = hashlimit_mt_destroy, + .me = THIS_MODULE, + }, #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) { .name = "hashlimit", .family = AF_INET6, - .match = hashlimit_mt, + .match = hashlimit_mt_v0, .matchsize = sizeof(struct xt_hashlimit_info), #ifdef CONFIG_COMPAT .compatsize = sizeof(struct compat_xt_hashlimit_info), .compat_from_user = hashlimit_mt_compat_from_user, .compat_to_user = hashlimit_mt_compat_to_user, #endif - .checkentry = hashlimit_mt_check, - .destroy = hashlimit_mt_destroy, + .checkentry = hashlimit_mt_check_v0, + .destroy = hashlimit_mt_destroy_v0, .me = THIS_MODULE }, + { + .name = "hashlimit", + .revision = 1, + .family = AF_INET6, + .match = hashlimit_mt, + .matchsize = sizeof(struct xt_hashlimit_mtinfo1), + .checkentry = hashlimit_mt_check, + .destroy = hashlimit_mt_destroy, + .me = THIS_MODULE, + }, #endif }; /* PROC stuff */ static void *dl_seq_start(struct seq_file *s, loff_t *pos) + __acquires(htable->lock) { struct proc_dir_entry *pde = s->private; struct xt_hashlimit_htable *htable = pde->data; @@ -656,6 +909,7 @@ static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos) } static void dl_seq_stop(struct seq_file *s, void *v) + __releases(htable->lock) { struct proc_dir_entry *pde = s->private; struct xt_hashlimit_htable *htable = pde->data; @@ -676,9 +930,9 @@ static int dl_seq_real_show(struct dsthash_ent *ent, int family, return seq_printf(s, "%ld %u.%u.%u.%u:%u->" "%u.%u.%u.%u:%u %u %u %u\n", (long)(ent->expires - jiffies)/HZ, - NIPQUAD(ent->dst.addr.ip.src), + NIPQUAD(ent->dst.ip.src), ntohs(ent->dst.src_port), - NIPQUAD(ent->dst.addr.ip.dst), + NIPQUAD(ent->dst.ip.dst), ntohs(ent->dst.dst_port), ent->rateinfo.credit, ent->rateinfo.credit_cap, ent->rateinfo.cost); @@ -687,9 +941,9 @@ static int dl_seq_real_show(struct dsthash_ent *ent, int family, return seq_printf(s, "%ld " NIP6_FMT ":%u->" NIP6_FMT ":%u %u %u %u\n", (long)(ent->expires - jiffies)/HZ, - NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.src), + NIP6(*(struct in6_addr *)&ent->dst.ip6.src), ntohs(ent->dst.src_port), - NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.dst), + NIP6(*(struct in6_addr *)&ent->dst.ip6.dst), ntohs(ent->dst.dst_port), ent->rateinfo.credit, ent->rateinfo.credit_cap, ent->rateinfo.cost); diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c index dbea0e0..01035fc 100644 --- a/net/netfilter/xt_iprange.c +++ b/net/netfilter/xt_iprange.c @@ -101,7 +101,7 @@ iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b) int r; for (i = 0; i < 4; ++i) { - r = a->s6_addr32[i] - b->s6_addr32[i]; + r = (__force u32)a->s6_addr32[i] - (__force u32)b->s6_addr32[i]; if (r != 0) return r; } diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c index d382f9c..9059c16 100644 --- a/net/netfilter/xt_owner.c +++ b/net/netfilter/xt_owner.c @@ -4,8 +4,8 @@ * * (C) 2000 Marc Boucher <marc@mbsi.ca> * - * Copyright © CC Computer Consultants GmbH, 2007 - * Contact: <jengelh@computergmbh.de> + * Copyright © CC Computer Consultants GmbH, 2007 - 2008 + * <jengelh@computergmbh.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -102,13 +102,15 @@ owner_mt(const struct sk_buff *skb, const struct net_device *in, (XT_OWNER_UID | XT_OWNER_GID)) == 0; if (info->match & XT_OWNER_UID) - if ((filp->f_uid != info->uid) ^ - !!(info->invert & XT_OWNER_UID)) + if ((filp->f_uid >= info->uid_min && + filp->f_uid <= info->uid_max) ^ + !(info->invert & XT_OWNER_UID)) return false; if (info->match & XT_OWNER_GID) - if ((filp->f_gid != info->gid) ^ - !!(info->invert & XT_OWNER_GID)) + if ((filp->f_gid >= info->gid_min && + filp->f_gid <= info->gid_max) ^ + !(info->invert & XT_OWNER_GID)) return false; return true; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 6b178e1..ff9fb6b 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1344,6 +1344,22 @@ static void netlink_data_ready(struct sock *sk, int len) * queueing. */ +static void __netlink_release(struct sock *sk) +{ + /* + * Last sock_put should drop referrence to sk->sk_net. It has already + * been dropped in netlink_kernel_create. Taking referrence to stopping + * namespace is not an option. + * Take referrence to a socket to remove it from netlink lookup table + * _alive_ and after that destroy it in the context of init_net. + */ + + sock_hold(sk); + sock_release(sk->sk_socket); + sk->sk_net = get_net(&init_net); + sock_put(sk); +} + struct sock * netlink_kernel_create(struct net *net, int unit, unsigned int groups, void (*input)(struct sk_buff *skb), @@ -1362,8 +1378,18 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) return NULL; - if (__netlink_create(net, sock, cb_mutex, unit) < 0) - goto out_sock_release; + /* + * We have to just have a reference on the net from sk, but don't + * get_net it. Besides, we cannot get and then put the net here. + * So we create one inside init_net and the move it to net. + */ + + if (__netlink_create(&init_net, sock, cb_mutex, unit) < 0) + goto out_sock_release_nosk; + + sk = sock->sk; + put_net(sk->sk_net); + sk->sk_net = net; if (groups < 32) groups = 32; @@ -1372,7 +1398,6 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, if (!listeners) goto out_sock_release; - sk = sock->sk; sk->sk_data_ready = netlink_data_ready; if (input) nlk_sk(sk)->netlink_rcv = input; @@ -1395,14 +1420,14 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, nl_table[unit].registered++; } netlink_table_ungrab(); - - /* Do not hold an extra referrence to a namespace as this socket is - * internal to a namespace and does not prevent it to stop. */ - put_net(net); return sk; out_sock_release: kfree(listeners); + __netlink_release(sk); + return NULL; + +out_sock_release_nosk: sock_release(sock); return NULL; } @@ -1415,18 +1440,7 @@ netlink_kernel_release(struct sock *sk) if (sk == NULL || sk->sk_socket == NULL) return; - /* - * Last sock_put should drop referrence to sk->sk_net. It has already - * been dropped in netlink_kernel_create. Taking referrence to stopping - * namespace is not an option. - * Take referrence to a socket to remove it from netlink lookup table - * _alive_ and after that destroy it in the context of init_net. - */ - sock_hold(sk); - sock_release(sk->sk_socket); - - sk->sk_net = get_net(&init_net); - sock_put(sk); + __netlink_release(sk); } EXPORT_SYMBOL(netlink_kernel_release); diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index d1e9d68..e4b051d 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c @@ -84,6 +84,7 @@ static void rfkill_schedule_toggle(struct rfkill_task *task) static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN); static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH); static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); +static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); static void rfkill_event(struct input_handle *handle, unsigned int type, unsigned int code, int down) @@ -99,6 +100,9 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, case KEY_UWB: rfkill_schedule_toggle(&rfkill_uwb); break; + case KEY_WIMAX: + rfkill_schedule_toggle(&rfkill_wimax); + break; default: break; } @@ -159,6 +163,11 @@ static const struct input_device_id rfkill_ids[] = { .evbit = { BIT_MASK(EV_KEY) }, .keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) }, }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) }, + }, { } }; diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index d06d338..6562f86 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -126,6 +126,9 @@ static ssize_t rfkill_type_show(struct device *dev, case RFKILL_TYPE_UWB: type = "ultrawideband"; break; + case RFKILL_TYPE_WIMAX: + type = "wimax"; + break; default: BUG(); } diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c index 3c04b00..d923124 100644 --- a/net/rxrpc/ar-call.c +++ b/net/rxrpc/ar-call.c @@ -15,7 +15,7 @@ #include <net/af_rxrpc.h> #include "ar-internal.h" -const char *rxrpc_call_states[] = { +const char *const rxrpc_call_states[] = { [RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq", [RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl", [RXRPC_CALL_CLIENT_RECV_REPLY] = "ClRcvRpl", diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 58aaf89..1aaa2e8 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -565,9 +565,9 @@ extern void __exit rxrpc_destroy_all_peers(void); /* * ar-proc.c */ -extern const char *rxrpc_call_states[]; -extern struct file_operations rxrpc_call_seq_fops; -extern struct file_operations rxrpc_connection_seq_fops; +extern const char *const rxrpc_call_states[]; +extern const struct file_operations rxrpc_call_seq_fops; +extern const struct file_operations rxrpc_connection_seq_fops; /* * ar-recvmsg.c diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c index 2e83ce3..83eda24 100644 --- a/net/rxrpc/ar-proc.c +++ b/net/rxrpc/ar-proc.c @@ -14,7 +14,7 @@ #include <net/af_rxrpc.h> #include "ar-internal.h" -static const char *rxrpc_conn_states[] = { +static const char *const rxrpc_conn_states[] = { [RXRPC_CONN_UNUSED] = "Unused ", [RXRPC_CONN_CLIENT] = "Client ", [RXRPC_CONN_SERVER_UNSECURED] = "SvUnsec ", @@ -98,7 +98,7 @@ static int rxrpc_call_seq_open(struct inode *inode, struct file *file) return seq_open(file, &rxrpc_call_seq_ops); } -struct file_operations rxrpc_call_seq_fops = { +const struct file_operations rxrpc_call_seq_fops = { .owner = THIS_MODULE, .open = rxrpc_call_seq_open, .read = seq_read, @@ -183,7 +183,7 @@ static int rxrpc_connection_seq_open(struct inode *inode, struct file *file) return seq_open(file, &rxrpc_connection_seq_ops); } -struct file_operations rxrpc_connection_seq_fops = { +const struct file_operations rxrpc_connection_seq_fops = { .owner = THIS_MODULE, .open = rxrpc_connection_seq_open, .read = seq_read, diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 87af7c9..82adfe6 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -198,7 +198,7 @@ config NET_SCH_NETEM config NET_SCH_INGRESS tristate "Ingress Qdisc" - depends on NET_CLS_ACT || NETFILTER + depends on NET_CLS_ACT ---help--- Say Y here if you want to use classifiers for incoming packets. If unsure, say Y. @@ -307,6 +307,17 @@ config NET_CLS_RSVP6 To compile this code as a module, choose M here: the module will be called cls_rsvp6. +config NET_CLS_FLOW + tristate "Flow classifier" + select NET_CLS + ---help--- + If you say Y here, you will be able to classify packets based on + a configurable combination of packet keys. This is mostly useful + in combination with SFQ. + + To compile this code as a module, choose M here: the + module will be called cls_flow. + config NET_EMATCH bool "Extended Matches" select NET_CLS diff --git a/net/sched/Makefile b/net/sched/Makefile index 81ecbe8..1d2b0f7 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o +obj-$(CONFIG_NET_CLS_FLOW) += cls_flow.o obj-$(CONFIG_NET_EMATCH) += ematch.o obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 3377ca0..0fbedca 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -482,7 +482,7 @@ EXPORT_SYMBOL(tcf_exts_destroy); int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb, struct nlattr *rate_tlv, struct tcf_exts *exts, - struct tcf_ext_map *map) + const struct tcf_ext_map *map) { memset(exts, 0, sizeof(*exts)); @@ -535,7 +535,7 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, EXPORT_SYMBOL(tcf_exts_change); int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, - struct tcf_ext_map *map) + const struct tcf_ext_map *map) { #ifdef CONFIG_NET_CLS_ACT if (map->action && exts->action) { @@ -571,7 +571,7 @@ EXPORT_SYMBOL(tcf_exts_dump); int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts, - struct tcf_ext_map *map) + const struct tcf_ext_map *map) { #ifdef CONFIG_NET_CLS_ACT if (exts->action) diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index bfb4342..956915c 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -35,7 +35,7 @@ struct basic_filter struct list_head link; }; -static struct tcf_ext_map basic_ext_map = { +static const struct tcf_ext_map basic_ext_map = { .action = TCA_BASIC_ACT, .police = TCA_BASIC_POLICE }; diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c new file mode 100644 index 0000000..5a7f6a3 --- /dev/null +++ b/net/sched/cls_flow.c @@ -0,0 +1,660 @@ +/* + * net/sched/cls_flow.c Generic flow classifier + * + * Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/jhash.h> +#include <linux/random.h> +#include <linux/pkt_cls.h> +#include <linux/skbuff.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/ipv6.h> + +#include <net/pkt_cls.h> +#include <net/ip.h> +#include <net/route.h> +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +#include <net/netfilter/nf_conntrack.h> +#endif + +struct flow_head { + struct list_head filters; +}; + +struct flow_filter { + struct list_head list; + struct tcf_exts exts; + struct tcf_ematch_tree ematches; + u32 handle; + + u32 nkeys; + u32 keymask; + u32 mode; + u32 mask; + u32 xor; + u32 rshift; + u32 addend; + u32 divisor; + u32 baseclass; +}; + +static u32 flow_hashrnd __read_mostly; +static int flow_hashrnd_initted __read_mostly; + +static const struct tcf_ext_map flow_ext_map = { + .action = TCA_FLOW_ACT, + .police = TCA_FLOW_POLICE, +}; + +static inline u32 addr_fold(void *addr) +{ + unsigned long a = (unsigned long)addr; + + return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0); +} + +static u32 flow_get_src(const struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + return ntohl(ip_hdr(skb)->saddr); + case __constant_htons(ETH_P_IPV6): + return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]); + default: + return addr_fold(skb->sk); + } +} + +static u32 flow_get_dst(const struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + return ntohl(ip_hdr(skb)->daddr); + case __constant_htons(ETH_P_IPV6): + return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); + default: + return addr_fold(skb->dst) ^ (__force u16)skb->protocol; + } +} + +static u32 flow_get_proto(const struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + return ip_hdr(skb)->protocol; + case __constant_htons(ETH_P_IPV6): + return ipv6_hdr(skb)->nexthdr; + default: + return 0; + } +} + +static int has_ports(u8 protocol) +{ + switch (protocol) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_UDPLITE: + case IPPROTO_SCTP: + case IPPROTO_DCCP: + case IPPROTO_ESP: + return 1; + default: + return 0; + } +} + +static u32 flow_get_proto_src(const struct sk_buff *skb) +{ + u32 res = 0; + + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): { + struct iphdr *iph = ip_hdr(skb); + + if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && + has_ports(iph->protocol)) + res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); + break; + } + case __constant_htons(ETH_P_IPV6): { + struct ipv6hdr *iph = ipv6_hdr(skb); + + if (has_ports(iph->nexthdr)) + res = ntohs(*(__be16 *)&iph[1]); + break; + } + default: + res = addr_fold(skb->sk); + } + + return res; +} + +static u32 flow_get_proto_dst(const struct sk_buff *skb) +{ + u32 res = 0; + + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): { + struct iphdr *iph = ip_hdr(skb); + + if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && + has_ports(iph->protocol)) + res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); + break; + } + case __constant_htons(ETH_P_IPV6): { + struct ipv6hdr *iph = ipv6_hdr(skb); + + if (has_ports(iph->nexthdr)) + res = ntohs(*(__be16 *)((void *)&iph[1] + 2)); + break; + } + default: + res = addr_fold(skb->dst) ^ (__force u16)skb->protocol; + } + + return res; +} + +static u32 flow_get_iif(const struct sk_buff *skb) +{ + return skb->iif; +} + +static u32 flow_get_priority(const struct sk_buff *skb) +{ + return skb->priority; +} + +static u32 flow_get_mark(const struct sk_buff *skb) +{ + return skb->mark; +} + +static u32 flow_get_nfct(const struct sk_buff *skb) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + return addr_fold(skb->nfct); +#else + return 0; +#endif +} + +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +#define CTTUPLE(skb, member) \ +({ \ + enum ip_conntrack_info ctinfo; \ + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); \ + if (ct == NULL) \ + goto fallback; \ + ct->tuplehash[CTINFO2DIR(ctinfo)].tuple.member; \ +}) +#else +#define CTTUPLE(skb, member) \ +({ \ + goto fallback; \ + 0; \ +}) +#endif + +static u32 flow_get_nfct_src(const struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + return ntohl(CTTUPLE(skb, src.u3.ip)); + case __constant_htons(ETH_P_IPV6): + return ntohl(CTTUPLE(skb, src.u3.ip6[3])); + } +fallback: + return flow_get_src(skb); +} + +static u32 flow_get_nfct_dst(const struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + return ntohl(CTTUPLE(skb, dst.u3.ip)); + case __constant_htons(ETH_P_IPV6): + return ntohl(CTTUPLE(skb, dst.u3.ip6[3])); + } +fallback: + return flow_get_dst(skb); +} + +static u32 flow_get_nfct_proto_src(const struct sk_buff *skb) +{ + return ntohs(CTTUPLE(skb, src.u.all)); +fallback: + return flow_get_proto_src(skb); +} + +static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb) +{ + return ntohs(CTTUPLE(skb, dst.u.all)); +fallback: + return flow_get_proto_dst(skb); +} + +static u32 flow_get_rtclassid(const struct sk_buff *skb) +{ +#ifdef CONFIG_NET_CLS_ROUTE + if (skb->dst) + return skb->dst->tclassid; +#endif + return 0; +} + +static u32 flow_get_skuid(const struct sk_buff *skb) +{ + if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) + return skb->sk->sk_socket->file->f_uid; + return 0; +} + +static u32 flow_get_skgid(const struct sk_buff *skb) +{ + if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) + return skb->sk->sk_socket->file->f_gid; + return 0; +} + +static u32 flow_key_get(const struct sk_buff *skb, int key) +{ + switch (key) { + case FLOW_KEY_SRC: + return flow_get_src(skb); + case FLOW_KEY_DST: + return flow_get_dst(skb); + case FLOW_KEY_PROTO: + return flow_get_proto(skb); + case FLOW_KEY_PROTO_SRC: + return flow_get_proto_src(skb); + case FLOW_KEY_PROTO_DST: + return flow_get_proto_dst(skb); + case FLOW_KEY_IIF: + return flow_get_iif(skb); + case FLOW_KEY_PRIORITY: + return flow_get_priority(skb); + case FLOW_KEY_MARK: + return flow_get_mark(skb); + case FLOW_KEY_NFCT: + return flow_get_nfct(skb); + case FLOW_KEY_NFCT_SRC: + return flow_get_nfct_src(skb); + case FLOW_KEY_NFCT_DST: + return flow_get_nfct_dst(skb); + case FLOW_KEY_NFCT_PROTO_SRC: + return flow_get_nfct_proto_src(skb); + case FLOW_KEY_NFCT_PROTO_DST: + return flow_get_nfct_proto_dst(skb); + case FLOW_KEY_RTCLASSID: + return flow_get_rtclassid(skb); + case FLOW_KEY_SKUID: + return flow_get_skuid(skb); + case FLOW_KEY_SKGID: + return flow_get_skgid(skb); + default: + WARN_ON(1); + return 0; + } +} + +static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp, + struct tcf_result *res) +{ + struct flow_head *head = tp->root; + struct flow_filter *f; + u32 keymask; + u32 classid; + unsigned int n, key; + int r; + + list_for_each_entry(f, &head->filters, list) { + u32 keys[f->nkeys]; + + if (!tcf_em_tree_match(skb, &f->ematches, NULL)) + continue; + + keymask = f->keymask; + + for (n = 0; n < f->nkeys; n++) { + key = ffs(keymask) - 1; + keymask &= ~(1 << key); + keys[n] = flow_key_get(skb, key); + } + + if (f->mode == FLOW_MODE_HASH) + classid = jhash2(keys, f->nkeys, flow_hashrnd); + else { + classid = keys[0]; + classid = (classid & f->mask) ^ f->xor; + classid = (classid >> f->rshift) + f->addend; + } + + if (f->divisor) + classid %= f->divisor; + + res->class = 0; + res->classid = TC_H_MAKE(f->baseclass, f->baseclass + classid); + + r = tcf_exts_exec(skb, &f->exts, res); + if (r < 0) + continue; + return r; + } + return -1; +} + +static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = { + [TCA_FLOW_KEYS] = { .type = NLA_U32 }, + [TCA_FLOW_MODE] = { .type = NLA_U32 }, + [TCA_FLOW_BASECLASS] = { .type = NLA_U32 }, + [TCA_FLOW_RSHIFT] = { .type = NLA_U32 }, + [TCA_FLOW_ADDEND] = { .type = NLA_U32 }, + [TCA_FLOW_MASK] = { .type = NLA_U32 }, + [TCA_FLOW_XOR] = { .type = NLA_U32 }, + [TCA_FLOW_DIVISOR] = { .type = NLA_U32 }, + [TCA_FLOW_ACT] = { .type = NLA_NESTED }, + [TCA_FLOW_POLICE] = { .type = NLA_NESTED }, + [TCA_FLOW_EMATCHES] = { .type = NLA_NESTED }, +}; + +static int flow_change(struct tcf_proto *tp, unsigned long base, + u32 handle, struct nlattr **tca, + unsigned long *arg) +{ + struct flow_head *head = tp->root; + struct flow_filter *f; + struct nlattr *opt = tca[TCA_OPTIONS]; + struct nlattr *tb[TCA_FLOW_MAX + 1]; + struct tcf_exts e; + struct tcf_ematch_tree t; + unsigned int nkeys = 0; + u32 baseclass = 0; + u32 keymask = 0; + u32 mode; + int err; + + if (opt == NULL) + return -EINVAL; + + err = nla_parse_nested(tb, TCA_FLOW_MAX, opt, flow_policy); + if (err < 0) + return err; + + if (tb[TCA_FLOW_BASECLASS]) { + baseclass = nla_get_u32(tb[TCA_FLOW_BASECLASS]); + if (TC_H_MIN(baseclass) == 0) + return -EINVAL; + } + + if (tb[TCA_FLOW_KEYS]) { + keymask = nla_get_u32(tb[TCA_FLOW_KEYS]); + if (fls(keymask) - 1 > FLOW_KEY_MAX) + return -EOPNOTSUPP; + + nkeys = hweight32(keymask); + if (nkeys == 0) + return -EINVAL; + } + + err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &flow_ext_map); + if (err < 0) + return err; + + err = tcf_em_tree_validate(tp, tb[TCA_FLOW_EMATCHES], &t); + if (err < 0) + goto err1; + + f = (struct flow_filter *)*arg; + if (f != NULL) { + err = -EINVAL; + if (f->handle != handle && handle) + goto err2; + + mode = f->mode; + if (tb[TCA_FLOW_MODE]) + mode = nla_get_u32(tb[TCA_FLOW_MODE]); + if (mode != FLOW_MODE_HASH && nkeys > 1) + goto err2; + } else { + err = -EINVAL; + if (!handle) + goto err2; + if (!tb[TCA_FLOW_KEYS]) + goto err2; + + mode = FLOW_MODE_MAP; + if (tb[TCA_FLOW_MODE]) + mode = nla_get_u32(tb[TCA_FLOW_MODE]); + if (mode != FLOW_MODE_HASH && nkeys > 1) + goto err2; + + if (TC_H_MAJ(baseclass) == 0) + baseclass = TC_H_MAKE(tp->q->handle, baseclass); + if (TC_H_MIN(baseclass) == 0) + baseclass = TC_H_MAKE(baseclass, 1); + + err = -ENOBUFS; + f = kzalloc(sizeof(*f), GFP_KERNEL); + if (f == NULL) + goto err2; + + f->handle = handle; + f->mask = ~0U; + } + + tcf_exts_change(tp, &f->exts, &e); + tcf_em_tree_change(tp, &f->ematches, &t); + + tcf_tree_lock(tp); + + if (tb[TCA_FLOW_KEYS]) { + f->keymask = keymask; + f->nkeys = nkeys; + } + + f->mode = mode; + + if (tb[TCA_FLOW_MASK]) + f->mask = nla_get_u32(tb[TCA_FLOW_MASK]); + if (tb[TCA_FLOW_XOR]) + f->xor = nla_get_u32(tb[TCA_FLOW_XOR]); + if (tb[TCA_FLOW_RSHIFT]) + f->rshift = nla_get_u32(tb[TCA_FLOW_RSHIFT]); + if (tb[TCA_FLOW_ADDEND]) + f->addend = nla_get_u32(tb[TCA_FLOW_ADDEND]); + + if (tb[TCA_FLOW_DIVISOR]) + f->divisor = nla_get_u32(tb[TCA_FLOW_DIVISOR]); + if (baseclass) + f->baseclass = baseclass; + + if (*arg == 0) + list_add_tail(&f->list, &head->filters); + + tcf_tree_unlock(tp); + + *arg = (unsigned long)f; + return 0; + +err2: + tcf_em_tree_destroy(tp, &t); +err1: + tcf_exts_destroy(tp, &e); + return err; +} + +static void flow_destroy_filter(struct tcf_proto *tp, struct flow_filter *f) +{ + tcf_exts_destroy(tp, &f->exts); + tcf_em_tree_destroy(tp, &f->ematches); + kfree(f); +} + +static int flow_delete(struct tcf_proto *tp, unsigned long arg) +{ + struct flow_filter *f = (struct flow_filter *)arg; + + tcf_tree_lock(tp); + list_del(&f->list); + tcf_tree_unlock(tp); + flow_destroy_filter(tp, f); + return 0; +} + +static int flow_init(struct tcf_proto *tp) +{ + struct flow_head *head; + + if (!flow_hashrnd_initted) { + get_random_bytes(&flow_hashrnd, 4); + flow_hashrnd_initted = 1; + } + + head = kzalloc(sizeof(*head), GFP_KERNEL); + if (head == NULL) + return -ENOBUFS; + INIT_LIST_HEAD(&head->filters); + tp->root = head; + return 0; +} + +static void flow_destroy(struct tcf_proto *tp) +{ + struct flow_head *head = tp->root; + struct flow_filter *f, *next; + + list_for_each_entry_safe(f, next, &head->filters, list) { + list_del(&f->list); + flow_destroy_filter(tp, f); + } + kfree(head); +} + +static unsigned long flow_get(struct tcf_proto *tp, u32 handle) +{ + struct flow_head *head = tp->root; + struct flow_filter *f; + + list_for_each_entry(f, &head->filters, list) + if (f->handle == handle) + return (unsigned long)f; + return 0; +} + +static void flow_put(struct tcf_proto *tp, unsigned long f) +{ + return; +} + +static int flow_dump(struct tcf_proto *tp, unsigned long fh, + struct sk_buff *skb, struct tcmsg *t) +{ + struct flow_filter *f = (struct flow_filter *)fh; + struct nlattr *nest; + + if (f == NULL) + return skb->len; + + t->tcm_handle = f->handle; + + nest = nla_nest_start(skb, TCA_OPTIONS); + if (nest == NULL) + goto nla_put_failure; + + NLA_PUT_U32(skb, TCA_FLOW_KEYS, f->keymask); + NLA_PUT_U32(skb, TCA_FLOW_MODE, f->mode); + + if (f->mask != ~0 || f->xor != 0) { + NLA_PUT_U32(skb, TCA_FLOW_MASK, f->mask); + NLA_PUT_U32(skb, TCA_FLOW_XOR, f->xor); + } + if (f->rshift) + NLA_PUT_U32(skb, TCA_FLOW_RSHIFT, f->rshift); + if (f->addend) + NLA_PUT_U32(skb, TCA_FLOW_ADDEND, f->addend); + + if (f->divisor) + NLA_PUT_U32(skb, TCA_FLOW_DIVISOR, f->divisor); + if (f->baseclass) + NLA_PUT_U32(skb, TCA_FLOW_BASECLASS, f->baseclass); + + if (tcf_exts_dump(skb, &f->exts, &flow_ext_map) < 0) + goto nla_put_failure; + + if (f->ematches.hdr.nmatches && + tcf_em_tree_dump(skb, &f->ematches, TCA_FLOW_EMATCHES) < 0) + goto nla_put_failure; + + nla_nest_end(skb, nest); + + if (tcf_exts_dump_stats(skb, &f->exts, &flow_ext_map) < 0) + goto nla_put_failure; + + return skb->len; + +nla_put_failure: + nlmsg_trim(skb, nest); + return -1; +} + +static void flow_walk(struct tcf_proto *tp, struct tcf_walker *arg) +{ + struct flow_head *head = tp->root; + struct flow_filter *f; + + list_for_each_entry(f, &head->filters, list) { + if (arg->count < arg->skip) + goto skip; + if (arg->fn(tp, (unsigned long)f, arg) < 0) { + arg->stop = 1; + break; + } +skip: + arg->count++; + } +} + +static struct tcf_proto_ops cls_flow_ops __read_mostly = { + .kind = "flow", + .classify = flow_classify, + .init = flow_init, + .destroy = flow_destroy, + .change = flow_change, + .delete = flow_delete, + .get = flow_get, + .put = flow_put, + .dump = flow_dump, + .walk = flow_walk, + .owner = THIS_MODULE, +}; + +static int __init cls_flow_init(void) +{ + return register_tcf_proto_ops(&cls_flow_ops); +} + +static void __exit cls_flow_exit(void) +{ + unregister_tcf_proto_ops(&cls_flow_ops); +} + +module_init(cls_flow_init); +module_exit(cls_flow_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); +MODULE_DESCRIPTION("TC flow classifier"); diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 436a6e7..b0f90e5 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -47,7 +47,7 @@ struct fw_filter struct tcf_exts exts; }; -static struct tcf_ext_map fw_ext_map = { +static const struct tcf_ext_map fw_ext_map = { .action = TCA_FW_ACT, .police = TCA_FW_POLICE }; diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index f7e7d39..784dcb8 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -62,7 +62,7 @@ struct route4_filter #define ROUTE4_FAILURE ((struct route4_filter*)(-1L)) -static struct tcf_ext_map route_ext_map = { +static const struct tcf_ext_map route_ext_map = { .police = TCA_ROUTE4_POLICE, .action = TCA_ROUTE4_ACT }; diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index ee60b2d..7a7bff5 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -55,7 +55,7 @@ struct tcindex_data { int fall_through; /* 0: only classify if explicit match */ }; -static struct tcf_ext_map tcindex_ext_map = { +static const struct tcf_ext_map tcindex_ext_map = { .police = TCA_TCINDEX_POLICE, .action = TCA_TCINDEX_ACT }; diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index e8a7756..b18fa95 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -82,7 +82,7 @@ struct tc_u_common u32 hgenerator; }; -static struct tcf_ext_map u32_ext_map = { +static const struct tcf_ext_map u32_ext_map = { .action = TCA_U32_ACT, .police = TCA_U32_POLICE }; diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index 3f72d52..274b1dd 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c @@ -12,18 +12,10 @@ #include <linux/list.h> #include <linux/skbuff.h> #include <linux/rtnetlink.h> -#include <linux/netfilter_ipv4.h> -#include <linux/netfilter_ipv6.h> -#include <linux/netfilter.h> #include <net/netlink.h> #include <net/pkt_sched.h> -/* Thanks to Doron Oz for this hack */ -#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER) -static int nf_registered; -#endif - struct ingress_qdisc_data { struct tcf_proto *filter_list; }; @@ -84,11 +76,6 @@ static int ingress_enqueue(struct sk_buff *skb, struct Qdisc *sch) result = tc_classify(skb, p->filter_list, &res); - /* - * Unlike normal "enqueue" functions, ingress_enqueue returns a - * firewall FW_* code. - */ -#ifdef CONFIG_NET_CLS_ACT sch->bstats.packets++; sch->bstats.bytes += skb->len; switch (result) { @@ -107,71 +94,10 @@ static int ingress_enqueue(struct sk_buff *skb, struct Qdisc *sch) result = TC_ACT_OK; break; } -#else - result = NF_ACCEPT; - sch->bstats.packets++; - sch->bstats.bytes += skb->len; -#endif return result; } -#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER) -static unsigned int ing_hook(unsigned int hook, struct sk_buff *skb, - const struct net_device *indev, - const struct net_device *outdev, - int (*okfn)(struct sk_buff *)) -{ - - struct Qdisc *q; - struct net_device *dev = skb->dev; - int fwres = NF_ACCEPT; - - if (dev->qdisc_ingress) { - spin_lock(&dev->ingress_lock); - if ((q = dev->qdisc_ingress) != NULL) - fwres = q->enqueue(skb, q); - spin_unlock(&dev->ingress_lock); - } - - return fwres; -} - -/* after ipt_filter */ -static struct nf_hook_ops ing_ops[] __read_mostly = { - { - .hook = ing_hook, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP_PRI_FILTER + 1, - }, - { - .hook = ing_hook, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP6_PRI_FILTER + 1, - }, -}; -#endif - -static int ingress_init(struct Qdisc *sch, struct nlattr *opt) -{ -#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER) - printk("Ingress scheduler: Classifier actions prefered over netfilter\n"); - - if (!nf_registered) { - if (nf_register_hooks(ing_ops, ARRAY_SIZE(ing_ops)) < 0) { - printk("ingress qdisc registration error \n"); - return -EINVAL; - } - nf_registered++; - } -#endif - return 0; -} - /* ------------------------------------------------------------- */ static void ingress_destroy(struct Qdisc *sch) @@ -213,7 +139,6 @@ static struct Qdisc_ops ingress_qdisc_ops __read_mostly = { .id = "ingress", .priv_size = sizeof(struct ingress_qdisc_data), .enqueue = ingress_enqueue, - .init = ingress_init, .destroy = ingress_destroy, .dump = ingress_dump, .owner = THIS_MODULE, @@ -227,10 +152,6 @@ static int __init ingress_module_init(void) static void __exit ingress_module_exit(void) { unregister_qdisc(&ingress_qdisc_ops); -#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER) - if (nf_registered) - nf_unregister_hooks(ing_ops, ARRAY_SIZE(ing_ops)); -#endif } module_init(ingress_module_init) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 91af539..a20e2ef 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -95,6 +95,7 @@ struct sfq_sched_data int limit; /* Variables */ + struct tcf_proto *filter_list; struct timer_list perturb_timer; u32 perturbation; sfq_index tail; /* Index of current slot in round */ @@ -155,6 +156,39 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) return sfq_fold_hash(q, h, h2); } +static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, + int *qerr) +{ + struct sfq_sched_data *q = qdisc_priv(sch); + struct tcf_result res; + int result; + + if (TC_H_MAJ(skb->priority) == sch->handle && + TC_H_MIN(skb->priority) > 0 && + TC_H_MIN(skb->priority) <= SFQ_HASH_DIVISOR) + return TC_H_MIN(skb->priority); + + if (!q->filter_list) + return sfq_hash(q, skb) + 1; + + *qerr = NET_XMIT_BYPASS; + result = tc_classify(skb, q->filter_list, &res); + if (result >= 0) { +#ifdef CONFIG_NET_CLS_ACT + switch (result) { + case TC_ACT_STOLEN: + case TC_ACT_QUEUED: + *qerr = NET_XMIT_SUCCESS; + case TC_ACT_SHOT: + return 0; + } +#endif + if (TC_H_MIN(res.classid) <= SFQ_HASH_DIVISOR) + return TC_H_MIN(res.classid); + } + return 0; +} + static inline void sfq_link(struct sfq_sched_data *q, sfq_index x) { sfq_index p, n; @@ -245,8 +279,18 @@ static int sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct sfq_sched_data *q = qdisc_priv(sch); - unsigned hash = sfq_hash(q, skb); + unsigned int hash; sfq_index x; + int ret; + + hash = sfq_classify(skb, sch, &ret); + if (hash == 0) { + if (ret == NET_XMIT_BYPASS) + sch->qstats.drops++; + kfree_skb(skb); + return ret; + } + hash--; x = q->ht[hash]; if (x == SFQ_DEPTH) { @@ -289,8 +333,18 @@ static int sfq_requeue(struct sk_buff *skb, struct Qdisc *sch) { struct sfq_sched_data *q = qdisc_priv(sch); - unsigned hash = sfq_hash(q, skb); + unsigned int hash; sfq_index x; + int ret; + + hash = sfq_classify(skb, sch, &ret); + if (hash == 0) { + if (ret == NET_XMIT_BYPASS) + sch->qstats.drops++; + kfree_skb(skb); + return ret; + } + hash--; x = q->ht[hash]; if (x == SFQ_DEPTH) { @@ -465,6 +519,8 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt) static void sfq_destroy(struct Qdisc *sch) { struct sfq_sched_data *q = qdisc_priv(sch); + + tcf_destroy_chain(q->filter_list); del_timer(&q->perturb_timer); } @@ -490,9 +546,79 @@ nla_put_failure: return -1; } +static int sfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, + struct nlattr **tca, unsigned long *arg) +{ + return -EOPNOTSUPP; +} + +static unsigned long sfq_get(struct Qdisc *sch, u32 classid) +{ + return 0; +} + +static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl) +{ + struct sfq_sched_data *q = qdisc_priv(sch); + + if (cl) + return NULL; + return &q->filter_list; +} + +static int sfq_dump_class(struct Qdisc *sch, unsigned long cl, + struct sk_buff *skb, struct tcmsg *tcm) +{ + tcm->tcm_handle |= TC_H_MIN(cl); + return 0; +} + +static int sfq_dump_class_stats(struct Qdisc *sch, unsigned long cl, + struct gnet_dump *d) +{ + struct sfq_sched_data *q = qdisc_priv(sch); + sfq_index idx = q->ht[cl-1]; + struct gnet_stats_queue qs = { .qlen = q->qs[idx].qlen }; + struct tc_sfq_xstats xstats = { .allot = q->allot[idx] }; + + if (gnet_stats_copy_queue(d, &qs) < 0) + return -1; + return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); +} + +static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) +{ + struct sfq_sched_data *q = qdisc_priv(sch); + unsigned int i; + + if (arg->stop) + return; + + for (i = 0; i < SFQ_HASH_DIVISOR; i++) { + if (q->ht[i] == SFQ_DEPTH || + arg->count < arg->skip) { + arg->count++; + continue; + } + if (arg->fn(sch, i + 1, arg) < 0) { + arg->stop = 1; + break; + } + arg->count++; + } +} + +static const struct Qdisc_class_ops sfq_class_ops = { + .get = sfq_get, + .change = sfq_change_class, + .tcf_chain = sfq_find_tcf, + .dump = sfq_dump_class, + .dump_stats = sfq_dump_class_stats, + .walk = sfq_walk, +}; + static struct Qdisc_ops sfq_qdisc_ops __read_mostly = { - .next = NULL, - .cl_ops = NULL, + .cl_ops = &sfq_class_ops, .id = "sfq", .priv_size = sizeof(struct sfq_sched_data), .enqueue = sfq_enqueue, diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 1411c7b1..0444fd0 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -71,7 +71,7 @@ struct teql_sched_data #define NEXT_SLAVE(q) (((struct teql_sched_data*)qdisc_priv(q))->next) -#define FMASK (IFF_BROADCAST|IFF_POINTOPOINT|IFF_BROADCAST) +#define FMASK (IFF_BROADCAST|IFF_POINTOPOINT) /* "teql*" qdisc routines */ diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index dd98763..77383e9 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2056,7 +2056,7 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, break; case SCTP_PARAM_HMAC_ALGO: - if (!sctp_auth_enable) + if (sctp_auth_enable) break; /* Fall Through */ fallthrough: diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 07fad7c..339ca4a 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1652,7 +1652,7 @@ static int __init x25_init(void) register_netdevice_notifier(&x25_dev_notifier); - printk(KERN_INFO "X.25 for Linux. Version 0.2 for Linux 2.1.15\n"); + printk(KERN_INFO "X.25 for Linux Version 0.2\n"); #ifdef CONFIG_SYSCTL x25_register_sysctl(); diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index b5c5347..6cc1525 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -28,6 +28,105 @@ * that instantiated crypto transforms have correct parameters for IPsec * purposes. */ +static struct xfrm_algo_desc aead_list[] = { +{ + .name = "rfc4106(gcm(aes))", + + .uinfo = { + .aead = { + .icv_truncbits = 64, + } + }, + + .desc = { + .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV8, + .sadb_alg_ivlen = 8, + .sadb_alg_minbits = 128, + .sadb_alg_maxbits = 256 + } +}, +{ + .name = "rfc4106(gcm(aes))", + + .uinfo = { + .aead = { + .icv_truncbits = 96, + } + }, + + .desc = { + .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV12, + .sadb_alg_ivlen = 8, + .sadb_alg_minbits = 128, + .sadb_alg_maxbits = 256 + } +}, +{ + .name = "rfc4106(gcm(aes))", + + .uinfo = { + .aead = { + .icv_truncbits = 128, + } + }, + + .desc = { + .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV16, + .sadb_alg_ivlen = 8, + .sadb_alg_minbits = 128, + .sadb_alg_maxbits = 256 + } +}, +{ + .name = "rfc4309(ccm(aes))", + + .uinfo = { + .aead = { + .icv_truncbits = 64, + } + }, + + .desc = { + .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV8, + .sadb_alg_ivlen = 8, + .sadb_alg_minbits = 128, + .sadb_alg_maxbits = 256 + } +}, +{ + .name = "rfc4309(ccm(aes))", + + .uinfo = { + .aead = { + .icv_truncbits = 96, + } + }, + + .desc = { + .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV12, + .sadb_alg_ivlen = 8, + .sadb_alg_minbits = 128, + .sadb_alg_maxbits = 256 + } +}, +{ + .name = "rfc4309(ccm(aes))", + + .uinfo = { + .aead = { + .icv_truncbits = 128, + } + }, + + .desc = { + .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV16, + .sadb_alg_ivlen = 8, + .sadb_alg_minbits = 128, + .sadb_alg_maxbits = 256 + } +}, +}; + static struct xfrm_algo_desc aalg_list[] = { { .name = "hmac(digest_null)", @@ -332,6 +431,11 @@ static struct xfrm_algo_desc calg_list[] = { }, }; +static inline int aead_entries(void) +{ + return ARRAY_SIZE(aead_list); +} + static inline int aalg_entries(void) { return ARRAY_SIZE(aalg_list); @@ -354,25 +458,32 @@ struct xfrm_algo_list { u32 mask; }; +static const struct xfrm_algo_list xfrm_aead_list = { + .algs = aead_list, + .entries = ARRAY_SIZE(aead_list), + .type = CRYPTO_ALG_TYPE_AEAD, + .mask = CRYPTO_ALG_TYPE_MASK, +}; + static const struct xfrm_algo_list xfrm_aalg_list = { .algs = aalg_list, .entries = ARRAY_SIZE(aalg_list), .type = CRYPTO_ALG_TYPE_HASH, - .mask = CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC, + .mask = CRYPTO_ALG_TYPE_HASH_MASK, }; static const struct xfrm_algo_list xfrm_ealg_list = { .algs = ealg_list, .entries = ARRAY_SIZE(ealg_list), .type = CRYPTO_ALG_TYPE_BLKCIPHER, - .mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC, + .mask = CRYPTO_ALG_TYPE_BLKCIPHER_MASK, }; static const struct xfrm_algo_list xfrm_calg_list = { .algs = calg_list, .entries = ARRAY_SIZE(calg_list), .type = CRYPTO_ALG_TYPE_COMPRESS, - .mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC, + .mask = CRYPTO_ALG_TYPE_MASK, }; static struct xfrm_algo_desc *xfrm_find_algo( @@ -461,6 +572,33 @@ struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe) } EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); +struct xfrm_aead_name { + const char *name; + int icvbits; +}; + +static int xfrm_aead_name_match(const struct xfrm_algo_desc *entry, + const void *data) +{ + const struct xfrm_aead_name *aead = data; + const char *name = aead->name; + + return aead->icvbits == entry->uinfo.aead.icv_truncbits && name && + !strcmp(name, entry->name); +} + +struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len, int probe) +{ + struct xfrm_aead_name data = { + .name = name, + .icvbits = icv_len, + }; + + return xfrm_find_algo(&xfrm_aead_list, xfrm_aead_name_match, &data, + probe); +} +EXPORT_SYMBOL_GPL(xfrm_aead_get_byname); + struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx) { if (idx >= aalg_entries()) diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 039e701..4d6ebc6 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -81,7 +81,6 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) *seq = *(__be32*)(skb_transport_header(skb) + offset_seq); return 0; } -EXPORT_SYMBOL(xfrm_parse_spi); int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) { @@ -160,12 +159,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) } if ((x->encap ? x->encap->encap_type : 0) != encap_type) { - XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID); + XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH); goto drop_unlock; } if (x->props.replay_window && xfrm_replay_check(x, skb, seq)) { - XFRM_INC_STATS(LINUX_MIB_XFRMINSEQOUTOFWINDOW); + XFRM_INC_STATS(LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index f4a1047..fc69036 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -64,6 +64,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { XFRM_SKB_CB(skb)->seq = ++x->replay.oseq; if (unlikely(x->replay.oseq == 0)) { + XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATESEQERROR); x->replay.oseq--; xfrm_audit_state_replay_overflow(x, skb); err = -EOVERFLOW; diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index 31d0354..2b0db13 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -22,7 +22,7 @@ static struct snmp_mib xfrm_mib_list[] = { SNMP_MIB_ITEM("XfrmInNoStates", LINUX_MIB_XFRMINNOSTATES), SNMP_MIB_ITEM("XfrmInStateProtoError", LINUX_MIB_XFRMINSTATEPROTOERROR), SNMP_MIB_ITEM("XfrmInStateModeError", LINUX_MIB_XFRMINSTATEMODEERROR), - SNMP_MIB_ITEM("XfrmInSeqOutOfWindow", LINUX_MIB_XFRMINSEQOUTOFWINDOW), + SNMP_MIB_ITEM("XfrmInStateSeqError", LINUX_MIB_XFRMINSTATESEQERROR), SNMP_MIB_ITEM("XfrmInStateExpired", LINUX_MIB_XFRMINSTATEEXPIRED), SNMP_MIB_ITEM("XfrmInStateMismatch", LINUX_MIB_XFRMINSTATEMISMATCH), SNMP_MIB_ITEM("XfrmInStateInvalid", LINUX_MIB_XFRMINSTATEINVALID), @@ -36,6 +36,7 @@ static struct snmp_mib xfrm_mib_list[] = { SNMP_MIB_ITEM("XfrmOutNoStates", LINUX_MIB_XFRMOUTNOSTATES), SNMP_MIB_ITEM("XfrmOutStateProtoError", LINUX_MIB_XFRMOUTSTATEPROTOERROR), SNMP_MIB_ITEM("XfrmOutStateModeError", LINUX_MIB_XFRMOUTSTATEMODEERROR), + SNMP_MIB_ITEM("XfrmOutStateSeqError", LINUX_MIB_XFRMOUTSTATESEQERROR), SNMP_MIB_ITEM("XfrmOutStateExpired", LINUX_MIB_XFRMOUTSTATEEXPIRED), SNMP_MIB_ITEM("XfrmOutPolBlock", LINUX_MIB_XFRMOUTPOLBLOCK), SNMP_MIB_ITEM("XfrmOutPolDead", LINUX_MIB_XFRMOUTPOLDEAD), diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 3003503..3ff76e8 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -216,10 +216,10 @@ static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo) write_unlock_bh(&xfrm_state_afinfo_lock); } -int xfrm_register_type(struct xfrm_type *type, unsigned short family) +int xfrm_register_type(const struct xfrm_type *type, unsigned short family) { struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); - struct xfrm_type **typemap; + const struct xfrm_type **typemap; int err = 0; if (unlikely(afinfo == NULL)) @@ -235,10 +235,10 @@ int xfrm_register_type(struct xfrm_type *type, unsigned short family) } EXPORT_SYMBOL(xfrm_register_type); -int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) +int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) { struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); - struct xfrm_type **typemap; + const struct xfrm_type **typemap; int err = 0; if (unlikely(afinfo == NULL)) @@ -254,11 +254,11 @@ int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) } EXPORT_SYMBOL(xfrm_unregister_type); -static struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) +static const struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) { struct xfrm_state_afinfo *afinfo; - struct xfrm_type **typemap; - struct xfrm_type *type; + const struct xfrm_type **typemap; + const struct xfrm_type *type; int modload_attempted = 0; retry: @@ -281,7 +281,7 @@ retry: return type; } -static void xfrm_put_type(struct xfrm_type *type) +static void xfrm_put_type(const struct xfrm_type *type) { module_put(type->owner); } @@ -1645,7 +1645,6 @@ err: xfrm_audit_state_replay(x, skb, net_seq); return -EINVAL; } -EXPORT_SYMBOL(xfrm_replay_check); void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) { @@ -1667,7 +1666,6 @@ void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) if (xfrm_aevent_is_on()) xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } -EXPORT_SYMBOL(xfrm_replay_advance); static LIST_HEAD(xfrm_km_list); static DEFINE_RWLOCK(xfrm_km_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e0ccdf2..7833807 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -31,6 +31,11 @@ #include <linux/in6.h> #endif +static inline int aead_len(struct xfrm_algo_aead *alg) +{ + return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); +} + static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) { struct nlattr *rt = attrs[type]; @@ -68,6 +73,22 @@ static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) return 0; } +static int verify_aead(struct nlattr **attrs) +{ + struct nlattr *rt = attrs[XFRMA_ALG_AEAD]; + struct xfrm_algo_aead *algp; + + if (!rt) + return 0; + + algp = nla_data(rt); + if (nla_len(rt) < aead_len(algp)) + return -EINVAL; + + algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; + return 0; +} + static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type, xfrm_address_t **addrp) { @@ -119,20 +140,28 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, switch (p->id.proto) { case IPPROTO_AH: if (!attrs[XFRMA_ALG_AUTH] || + attrs[XFRMA_ALG_AEAD] || attrs[XFRMA_ALG_CRYPT] || attrs[XFRMA_ALG_COMP]) goto out; break; case IPPROTO_ESP: - if ((!attrs[XFRMA_ALG_AUTH] && - !attrs[XFRMA_ALG_CRYPT]) || - attrs[XFRMA_ALG_COMP]) + if (attrs[XFRMA_ALG_COMP]) + goto out; + if (!attrs[XFRMA_ALG_AUTH] && + !attrs[XFRMA_ALG_CRYPT] && + !attrs[XFRMA_ALG_AEAD]) + goto out; + if ((attrs[XFRMA_ALG_AUTH] || + attrs[XFRMA_ALG_CRYPT]) && + attrs[XFRMA_ALG_AEAD]) goto out; break; case IPPROTO_COMP: if (!attrs[XFRMA_ALG_COMP] || + attrs[XFRMA_ALG_AEAD] || attrs[XFRMA_ALG_AUTH] || attrs[XFRMA_ALG_CRYPT]) goto out; @@ -143,6 +172,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, case IPPROTO_ROUTING: if (attrs[XFRMA_ALG_COMP] || attrs[XFRMA_ALG_AUTH] || + attrs[XFRMA_ALG_AEAD] || attrs[XFRMA_ALG_CRYPT] || attrs[XFRMA_ENCAP] || attrs[XFRMA_SEC_CTX] || @@ -155,6 +185,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, goto out; } + if ((err = verify_aead(attrs))) + goto out; if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH))) goto out; if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT))) @@ -208,6 +240,31 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, return 0; } +static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, + struct nlattr *rta) +{ + struct xfrm_algo_aead *p, *ualg; + struct xfrm_algo_desc *algo; + + if (!rta) + return 0; + + ualg = nla_data(rta); + + algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1); + if (!algo) + return -ENOSYS; + *props = algo->desc.sadb_alg_id; + + p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL); + if (!p) + return -ENOMEM; + + strcpy(p->alg_name, algo->name); + *algpp = p; + return 0; +} + static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) { int len = 0; @@ -286,6 +343,9 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, copy_from_user_state(x, p); + if ((err = attach_aead(&x->aead, &x->props.ealgo, + attrs[XFRMA_ALG_AEAD]))) + goto error; if ((err = attach_one_algo(&x->aalg, &x->props.aalgo, xfrm_aalg_get_byname, attrs[XFRMA_ALG_AUTH]))) @@ -510,6 +570,8 @@ static int copy_to_user_state_extra(struct xfrm_state *x, if (x->lastused) NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); + if (x->aead) + NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead); if (x->aalg) NLA_PUT(skb, XFRMA_ALG_AUTH, xfrm_alg_len(x->aalg), x->aalg); if (x->ealg) @@ -1808,6 +1870,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { #undef XMSGSIZE static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { + [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) }, @@ -1972,6 +2035,8 @@ static int xfrm_notify_sa_flush(struct km_event *c) static inline size_t xfrm_sa_len(struct xfrm_state *x) { size_t l = 0; + if (x->aead) + l += nla_total_size(aead_len(x->aead)); if (x->aalg) l += nla_total_size(xfrm_alg_len(x->aalg)); if (x->ealg) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index f96dec1..880d455 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2692,7 +2692,6 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) netlbl_sid_to_secattr_failure: POLICY_RDUNLOCK; - netlbl_secattr_destroy(secattr); return rc; } #endif /* CONFIG_NETLABEL */ |