diff options
| -rw-r--r-- | drivers/net/phy/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/phy/at803x.c | 176 | ||||
| -rw-r--r-- | drivers/net/usb/ipheth.c | 5 | ||||
| -rw-r--r-- | drivers/net/usb/qmi_wwan.c | 41 | ||||
| -rw-r--r-- | net/8021q/vlan.c | 4 | ||||
| -rw-r--r-- | net/ipv4/route.c | 9 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 8 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 3 | ||||
| -rw-r--r-- | net/netfilter/xt_CT.c | 10 | ||||
| -rw-r--r-- | net/netfilter/xt_TEE.c | 1 | ||||
| -rw-r--r-- | net/netfilter/xt_nat.c | 8 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 19 |
13 files changed, 268 insertions, 22 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 983bbf4d5ef6..961f0b293913 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
| @@ -15,6 +15,11 @@ if PHYLIB | |||
| 15 | 15 | ||
| 16 | comment "MII PHY device drivers" | 16 | comment "MII PHY device drivers" |
| 17 | 17 | ||
| 18 | config AT803X_PHY | ||
| 19 | tristate "Drivers for Atheros AT803X PHYs" | ||
| 20 | ---help--- | ||
| 21 | Currently supports the AT8030 and AT8035 model | ||
| 22 | |||
| 18 | config AMD_PHY | 23 | config AMD_PHY |
| 19 | tristate "Drivers for the AMD PHYs" | 24 | tristate "Drivers for the AMD PHYs" |
| 20 | ---help--- | 25 | ---help--- |
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 426674debae4..9645e389a58d 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile | |||
| @@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP) += ste10Xp.o | |||
| 25 | obj-$(CONFIG_MICREL_PHY) += micrel.o | 25 | obj-$(CONFIG_MICREL_PHY) += micrel.o |
| 26 | obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o | 26 | obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o |
| 27 | obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o | 27 | obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o |
| 28 | obj-$(CONFIG_AT803X_PHY) += at803x.o | ||
| 28 | obj-$(CONFIG_AMD_PHY) += amd.o | 29 | obj-$(CONFIG_AMD_PHY) += amd.o |
| 29 | obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o | 30 | obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o |
| 30 | obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o | 31 | obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o |
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c new file mode 100644 index 000000000000..45cbc10de01c --- /dev/null +++ b/drivers/net/phy/at803x.c | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | /* | ||
| 2 | * drivers/net/phy/at803x.c | ||
| 3 | * | ||
| 4 | * Driver for Atheros 803x PHY | ||
| 5 | * | ||
| 6 | * Author: Matus Ujhelyi <ujhelyi.m@gmail.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/phy.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/string.h> | ||
| 17 | #include <linux/netdevice.h> | ||
| 18 | #include <linux/etherdevice.h> | ||
| 19 | |||
| 20 | #define AT803X_INTR_ENABLE 0x12 | ||
| 21 | #define AT803X_INTR_STATUS 0x13 | ||
| 22 | #define AT803X_WOL_ENABLE 0x01 | ||
| 23 | #define AT803X_DEVICE_ADDR 0x03 | ||
| 24 | #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C | ||
| 25 | #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B | ||
| 26 | #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A | ||
| 27 | #define AT803X_MMD_ACCESS_CONTROL 0x0D | ||
| 28 | #define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E | ||
| 29 | #define AT803X_FUNC_DATA 0x4003 | ||
| 30 | |||
| 31 | MODULE_DESCRIPTION("Atheros 803x PHY driver"); | ||
| 32 | MODULE_AUTHOR("Matus Ujhelyi"); | ||
| 33 | MODULE_LICENSE("GPL"); | ||
| 34 | |||
| 35 | static void at803x_set_wol_mac_addr(struct phy_device *phydev) | ||
| 36 | { | ||
| 37 | struct net_device *ndev = phydev->attached_dev; | ||
| 38 | const u8 *mac; | ||
| 39 | unsigned int i, offsets[] = { | ||
| 40 | AT803X_LOC_MAC_ADDR_32_47_OFFSET, | ||
| 41 | AT803X_LOC_MAC_ADDR_16_31_OFFSET, | ||
| 42 | AT803X_LOC_MAC_ADDR_0_15_OFFSET, | ||
| 43 | }; | ||
| 44 | |||
| 45 | if (!ndev) | ||
| 46 | return; | ||
| 47 | |||
| 48 | mac = (const u8 *) ndev->dev_addr; | ||
| 49 | |||
| 50 | if (!is_valid_ether_addr(mac)) | ||
| 51 | return; | ||
| 52 | |||
| 53 | for (i = 0; i < 3; i++) { | ||
| 54 | phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, | ||
| 55 | AT803X_DEVICE_ADDR); | ||
| 56 | phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, | ||
| 57 | offsets[i]); | ||
| 58 | phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, | ||
| 59 | AT803X_FUNC_DATA); | ||
| 60 | phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, | ||
| 61 | mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | static int at803x_config_init(struct phy_device *phydev) | ||
| 66 | { | ||
| 67 | int val; | ||
| 68 | u32 features; | ||
| 69 | int status; | ||
| 70 | |||
| 71 | features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | | ||
| 72 | SUPPORTED_FIBRE | SUPPORTED_BNC; | ||
| 73 | |||
| 74 | val = phy_read(phydev, MII_BMSR); | ||
| 75 | if (val < 0) | ||
| 76 | return val; | ||
| 77 | |||
| 78 | if (val & BMSR_ANEGCAPABLE) | ||
| 79 | features |= SUPPORTED_Autoneg; | ||
| 80 | if (val & BMSR_100FULL) | ||
| 81 | features |= SUPPORTED_100baseT_Full; | ||
| 82 | if (val & BMSR_100HALF) | ||
| 83 | features |= SUPPORTED_100baseT_Half; | ||
| 84 | if (val & BMSR_10FULL) | ||
| 85 | features |= SUPPORTED_10baseT_Full; | ||
| 86 | if (val & BMSR_10HALF) | ||
| 87 | features |= SUPPORTED_10baseT_Half; | ||
| 88 | |||
| 89 | if (val & BMSR_ESTATEN) { | ||
| 90 | val = phy_read(phydev, MII_ESTATUS); | ||
| 91 | if (val < 0) | ||
| 92 | return val; | ||
| 93 | |||
| 94 | if (val & ESTATUS_1000_TFULL) | ||
| 95 | features |= SUPPORTED_1000baseT_Full; | ||
| 96 | if (val & ESTATUS_1000_THALF) | ||
| 97 | features |= SUPPORTED_1000baseT_Half; | ||
| 98 | } | ||
| 99 | |||
| 100 | phydev->supported = features; | ||
| 101 | phydev->advertising = features; | ||
| 102 | |||
| 103 | /* enable WOL */ | ||
| 104 | at803x_set_wol_mac_addr(phydev); | ||
| 105 | status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE); | ||
| 106 | status = phy_read(phydev, AT803X_INTR_STATUS); | ||
| 107 | |||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | /* ATHEROS 8035 */ | ||
| 112 | static struct phy_driver at8035_driver = { | ||
| 113 | .phy_id = 0x004dd072, | ||
| 114 | .name = "Atheros 8035 ethernet", | ||
| 115 | .phy_id_mask = 0xffffffef, | ||
| 116 | .config_init = at803x_config_init, | ||
| 117 | .features = PHY_GBIT_FEATURES, | ||
| 118 | .flags = PHY_HAS_INTERRUPT, | ||
| 119 | .config_aneg = &genphy_config_aneg, | ||
| 120 | .read_status = &genphy_read_status, | ||
| 121 | .driver = { | ||
| 122 | .owner = THIS_MODULE, | ||
| 123 | }, | ||
| 124 | }; | ||
| 125 | |||
| 126 | /* ATHEROS 8030 */ | ||
| 127 | static struct phy_driver at8030_driver = { | ||
| 128 | .phy_id = 0x004dd076, | ||
| 129 | .name = "Atheros 8030 ethernet", | ||
| 130 | .phy_id_mask = 0xffffffef, | ||
| 131 | .config_init = at803x_config_init, | ||
| 132 | .features = PHY_GBIT_FEATURES, | ||
| 133 | .flags = PHY_HAS_INTERRUPT, | ||
| 134 | .config_aneg = &genphy_config_aneg, | ||
| 135 | .read_status = &genphy_read_status, | ||
| 136 | .driver = { | ||
| 137 | .owner = THIS_MODULE, | ||
| 138 | }, | ||
| 139 | }; | ||
| 140 | |||
| 141 | static int __init atheros_init(void) | ||
| 142 | { | ||
| 143 | int ret; | ||
| 144 | |||
| 145 | ret = phy_driver_register(&at8035_driver); | ||
| 146 | if (ret) | ||
| 147 | goto err1; | ||
| 148 | |||
| 149 | ret = phy_driver_register(&at8030_driver); | ||
| 150 | if (ret) | ||
| 151 | goto err2; | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | |||
| 155 | err2: | ||
| 156 | phy_driver_unregister(&at8035_driver); | ||
| 157 | err1: | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | static void __exit atheros_exit(void) | ||
| 162 | { | ||
| 163 | phy_driver_unregister(&at8035_driver); | ||
| 164 | phy_driver_unregister(&at8030_driver); | ||
| 165 | } | ||
| 166 | |||
| 167 | module_init(atheros_init); | ||
| 168 | module_exit(atheros_exit); | ||
| 169 | |||
| 170 | static struct mdio_device_id __maybe_unused atheros_tbl[] = { | ||
| 171 | { 0x004dd076, 0xffffffef }, | ||
| 172 | { 0x004dd072, 0xffffffef }, | ||
| 173 | { } | ||
| 174 | }; | ||
| 175 | |||
| 176 | MODULE_DEVICE_TABLE(mdio, atheros_tbl); | ||
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index a28a983d465e..534d8becbbdc 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | #define USB_PRODUCT_IPAD 0x129a | 62 | #define USB_PRODUCT_IPAD 0x129a |
| 63 | #define USB_PRODUCT_IPHONE_4_VZW 0x129c | 63 | #define USB_PRODUCT_IPHONE_4_VZW 0x129c |
| 64 | #define USB_PRODUCT_IPHONE_4S 0x12a0 | 64 | #define USB_PRODUCT_IPHONE_4S 0x12a0 |
| 65 | #define USB_PRODUCT_IPHONE_5 0x12a8 | ||
| 65 | 66 | ||
| 66 | #define IPHETH_USBINTF_CLASS 255 | 67 | #define IPHETH_USBINTF_CLASS 255 |
| 67 | #define IPHETH_USBINTF_SUBCLASS 253 | 68 | #define IPHETH_USBINTF_SUBCLASS 253 |
| @@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = { | |||
| 113 | USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, | 114 | USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, |
| 114 | IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, | 115 | IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, |
| 115 | IPHETH_USBINTF_PROTO) }, | 116 | IPHETH_USBINTF_PROTO) }, |
| 117 | { USB_DEVICE_AND_INTERFACE_INFO( | ||
| 118 | USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, | ||
| 119 | IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, | ||
| 120 | IPHETH_USBINTF_PROTO) }, | ||
| 116 | { } | 121 | { } |
| 117 | }; | 122 | }; |
| 118 | MODULE_DEVICE_TABLE(usb, ipheth_table); | 123 | MODULE_DEVICE_TABLE(usb, ipheth_table); |
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6883c371c59f..9d23ba2fe981 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
| @@ -371,16 +371,57 @@ static const struct usb_device_id products[] = { | |||
| 371 | }, | 371 | }, |
| 372 | 372 | ||
| 373 | /* 3. Combined interface devices matching on interface number */ | 373 | /* 3. Combined interface devices matching on interface number */ |
| 374 | {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, | ||
| 375 | {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, | ||
| 376 | {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, | ||
| 377 | {QMI_FIXED_INTF(0x19d2, 0x0021, 4)}, | ||
| 378 | {QMI_FIXED_INTF(0x19d2, 0x0025, 1)}, | ||
| 379 | {QMI_FIXED_INTF(0x19d2, 0x0031, 4)}, | ||
| 380 | {QMI_FIXED_INTF(0x19d2, 0x0042, 4)}, | ||
| 381 | {QMI_FIXED_INTF(0x19d2, 0x0049, 5)}, | ||
| 382 | {QMI_FIXED_INTF(0x19d2, 0x0052, 4)}, | ||
| 374 | {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ | 383 | {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ |
| 384 | {QMI_FIXED_INTF(0x19d2, 0x0058, 4)}, | ||
| 375 | {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ | 385 | {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ |
| 376 | {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ | 386 | {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ |
| 387 | {QMI_FIXED_INTF(0x19d2, 0x0113, 5)}, | ||
| 388 | {QMI_FIXED_INTF(0x19d2, 0x0118, 5)}, | ||
| 389 | {QMI_FIXED_INTF(0x19d2, 0x0121, 5)}, | ||
| 390 | {QMI_FIXED_INTF(0x19d2, 0x0123, 4)}, | ||
| 391 | {QMI_FIXED_INTF(0x19d2, 0x0124, 5)}, | ||
| 392 | {QMI_FIXED_INTF(0x19d2, 0x0125, 6)}, | ||
| 393 | {QMI_FIXED_INTF(0x19d2, 0x0126, 5)}, | ||
| 394 | {QMI_FIXED_INTF(0x19d2, 0x0130, 1)}, | ||
| 395 | {QMI_FIXED_INTF(0x19d2, 0x0133, 3)}, | ||
| 396 | {QMI_FIXED_INTF(0x19d2, 0x0141, 5)}, | ||
| 377 | {QMI_FIXED_INTF(0x19d2, 0x0157, 5)}, /* ZTE MF683 */ | 397 | {QMI_FIXED_INTF(0x19d2, 0x0157, 5)}, /* ZTE MF683 */ |
| 398 | {QMI_FIXED_INTF(0x19d2, 0x0158, 3)}, | ||
| 378 | {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ | 399 | {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ |
| 400 | {QMI_FIXED_INTF(0x19d2, 0x0168, 4)}, | ||
| 401 | {QMI_FIXED_INTF(0x19d2, 0x0176, 3)}, | ||
| 402 | {QMI_FIXED_INTF(0x19d2, 0x0178, 3)}, | ||
| 403 | {QMI_FIXED_INTF(0x19d2, 0x0191, 4)}, /* ZTE EuFi890 */ | ||
| 404 | {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ | ||
| 405 | {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, | ||
| 406 | {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ | ||
| 379 | {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ | 407 | {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ |
| 380 | {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ | 408 | {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ |
| 381 | {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ | 409 | {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ |
| 410 | {QMI_FIXED_INTF(0x19d2, 0x1012, 4)}, | ||
| 382 | {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ | 411 | {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ |
| 412 | {QMI_FIXED_INTF(0x19d2, 0x1021, 2)}, | ||
| 413 | {QMI_FIXED_INTF(0x19d2, 0x1245, 4)}, | ||
| 414 | {QMI_FIXED_INTF(0x19d2, 0x1247, 4)}, | ||
| 415 | {QMI_FIXED_INTF(0x19d2, 0x1252, 4)}, | ||
| 416 | {QMI_FIXED_INTF(0x19d2, 0x1254, 4)}, | ||
| 417 | {QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, | ||
| 418 | {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, | ||
| 419 | {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, | ||
| 420 | {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, | ||
| 383 | {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ | 421 | {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ |
| 422 | {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, | ||
| 423 | {QMI_FIXED_INTF(0x19d2, 0x1425, 2)}, | ||
| 424 | {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ | ||
| 384 | {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ | 425 | {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ |
| 385 | {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ | 426 | {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ |
| 386 | {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ | 427 | {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 9096bcb08132..ee070722a3a3 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
| @@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
| 463 | 463 | ||
| 464 | case NETDEV_PRE_TYPE_CHANGE: | 464 | case NETDEV_PRE_TYPE_CHANGE: |
| 465 | /* Forbid underlaying device to change its type. */ | 465 | /* Forbid underlaying device to change its type. */ |
| 466 | return NOTIFY_BAD; | 466 | if (vlan_uses_dev(dev)) |
| 467 | return NOTIFY_BAD; | ||
| 468 | break; | ||
| 467 | 469 | ||
| 468 | case NETDEV_NOTIFY_PEERS: | 470 | case NETDEV_NOTIFY_PEERS: |
| 469 | case NETDEV_BONDING_FAILOVER: | 471 | case NETDEV_BONDING_FAILOVER: |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 432f4bb77238..a8c651216fa6 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | |||
| 1163 | spin_lock_bh(&fnhe_lock); | 1163 | spin_lock_bh(&fnhe_lock); |
| 1164 | 1164 | ||
| 1165 | if (daddr == fnhe->fnhe_daddr) { | 1165 | if (daddr == fnhe->fnhe_daddr) { |
| 1166 | struct rtable *orig; | 1166 | struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); |
| 1167 | 1167 | if (orig && rt_is_expired(orig)) { | |
| 1168 | fnhe->fnhe_gw = 0; | ||
| 1169 | fnhe->fnhe_pmtu = 0; | ||
| 1170 | fnhe->fnhe_expires = 0; | ||
| 1171 | } | ||
| 1168 | if (fnhe->fnhe_pmtu) { | 1172 | if (fnhe->fnhe_pmtu) { |
| 1169 | unsigned long expires = fnhe->fnhe_expires; | 1173 | unsigned long expires = fnhe->fnhe_expires; |
| 1170 | unsigned long diff = expires - jiffies; | 1174 | unsigned long diff = expires - jiffies; |
| @@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | |||
| 1181 | } else if (!rt->rt_gateway) | 1185 | } else if (!rt->rt_gateway) |
| 1182 | rt->rt_gateway = daddr; | 1186 | rt->rt_gateway = daddr; |
| 1183 | 1187 | ||
| 1184 | orig = rcu_dereference(fnhe->fnhe_rth); | ||
| 1185 | rcu_assign_pointer(fnhe->fnhe_rth, rt); | 1188 | rcu_assign_pointer(fnhe->fnhe_rth, rt); |
| 1186 | if (orig) | 1189 | if (orig) |
| 1187 | rt_free(orig); | 1190 | rt_free(orig); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f32c02e2a543..b7c2f439b54f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
| 549 | !tp->urg_data || | 549 | !tp->urg_data || |
| 550 | before(tp->urg_seq, tp->copied_seq) || | 550 | before(tp->urg_seq, tp->copied_seq) || |
| 551 | !before(tp->urg_seq, tp->rcv_nxt)) { | 551 | !before(tp->urg_seq, tp->rcv_nxt)) { |
| 552 | struct sk_buff *skb; | ||
| 553 | 552 | ||
| 554 | answ = tp->rcv_nxt - tp->copied_seq; | 553 | answ = tp->rcv_nxt - tp->copied_seq; |
| 555 | 554 | ||
| 556 | /* Subtract 1, if FIN is in queue. */ | 555 | /* Subtract 1, if FIN was received */ |
| 557 | skb = skb_peek_tail(&sk->sk_receive_queue); | 556 | if (answ && sock_flag(sk, SOCK_DONE)) |
| 558 | if (answ && skb) | 557 | answ--; |
| 559 | answ -= tcp_hdr(skb)->fin; | ||
| 560 | } else | 558 | } else |
| 561 | answ = tp->urg_seq - tp->copied_seq; | 559 | answ = tp->urg_seq - tp->copied_seq; |
| 562 | release_sock(sk); | 560 | release_sock(sk); |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 7e7198b51c06..c4ee43710aab 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
| @@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u) | |||
| 2589 | struct ip_vs_proto_data *pd; | 2589 | struct ip_vs_proto_data *pd; |
| 2590 | #endif | 2590 | #endif |
| 2591 | 2591 | ||
| 2592 | memset(u, 0, sizeof (*u)); | ||
| 2593 | |||
| 2592 | #ifdef CONFIG_IP_VS_PROTO_TCP | 2594 | #ifdef CONFIG_IP_VS_PROTO_TCP |
| 2593 | pd = ip_vs_proto_data_get(net, IPPROTO_TCP); | 2595 | pd = ip_vs_proto_data_get(net, IPPROTO_TCP); |
| 2594 | u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; | 2596 | u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; |
| @@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 2766 | { | 2768 | { |
| 2767 | struct ip_vs_timeout_user t; | 2769 | struct ip_vs_timeout_user t; |
| 2768 | 2770 | ||
| 2769 | memset(&t, 0, sizeof(t)); | ||
| 2770 | __ip_vs_get_timeouts(net, &t); | 2771 | __ip_vs_get_timeouts(net, &t); |
| 2771 | if (copy_to_user(user, &t, sizeof(t)) != 0) | 2772 | if (copy_to_user(user, &t, sizeof(t)) != 0) |
| 2772 | ret = -EFAULT; | 2773 | ret = -EFAULT; |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 16c712563860..ae7f5daeee43 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
| @@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
| 180 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; | 180 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; |
| 181 | struct ctnl_timeout *timeout; | 181 | struct ctnl_timeout *timeout; |
| 182 | struct nf_conn_timeout *timeout_ext; | 182 | struct nf_conn_timeout *timeout_ext; |
| 183 | const struct ipt_entry *e = par->entryinfo; | ||
| 184 | struct nf_conntrack_l4proto *l4proto; | 183 | struct nf_conntrack_l4proto *l4proto; |
| 185 | int ret = 0; | 184 | int ret = 0; |
| 185 | u8 proto; | ||
| 186 | 186 | ||
| 187 | rcu_read_lock(); | 187 | rcu_read_lock(); |
| 188 | timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); | 188 | timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); |
| @@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
| 192 | goto out; | 192 | goto out; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | if (e->ip.invflags & IPT_INV_PROTO) { | 195 | proto = xt_ct_find_proto(par); |
| 196 | if (!proto) { | ||
| 196 | ret = -EINVAL; | 197 | ret = -EINVAL; |
| 197 | pr_info("You cannot use inversion on L4 protocol\n"); | 198 | pr_info("You must specify a L4 protocol, and not use " |
| 199 | "inversions on it.\n"); | ||
| 198 | goto out; | 200 | goto out; |
| 199 | } | 201 | } |
| 200 | 202 | ||
| @@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
| 214 | /* Make sure the timeout policy matches any existing protocol tracker, | 216 | /* Make sure the timeout policy matches any existing protocol tracker, |
| 215 | * otherwise default to generic. | 217 | * otherwise default to generic. |
| 216 | */ | 218 | */ |
| 217 | l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); | 219 | l4proto = __nf_ct_l4proto_find(par->family, proto); |
| 218 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | 220 | if (timeout->l4proto->l4proto != l4proto->l4proto) { |
| 219 | ret = -EINVAL; | 221 | ret = -EINVAL; |
| 220 | pr_info("Timeout policy `%s' can only be used by L4 protocol " | 222 | pr_info("Timeout policy `%s' can only be used by L4 protocol " |
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index ee2e5bc5a8c7..bd93e51d30ac 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c | |||
| @@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) | |||
| 70 | fl4.daddr = info->gw.ip; | 70 | fl4.daddr = info->gw.ip; |
| 71 | fl4.flowi4_tos = RT_TOS(iph->tos); | 71 | fl4.flowi4_tos = RT_TOS(iph->tos); |
| 72 | fl4.flowi4_scope = RT_SCOPE_UNIVERSE; | 72 | fl4.flowi4_scope = RT_SCOPE_UNIVERSE; |
| 73 | fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; | ||
| 73 | rt = ip_route_output_key(net, &fl4); | 74 | rt = ip_route_output_key(net, &fl4); |
| 74 | if (IS_ERR(rt)) | 75 | if (IS_ERR(rt)) |
| 75 | return false; | 76 | return false; |
diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c index 81aafa8e4fef..bea7464cc43f 100644 --- a/net/netfilter/xt_nat.c +++ b/net/netfilter/xt_nat.c | |||
| @@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
| 111 | .family = NFPROTO_IPV4, | 111 | .family = NFPROTO_IPV4, |
| 112 | .table = "nat", | 112 | .table = "nat", |
| 113 | .hooks = (1 << NF_INET_POST_ROUTING) | | 113 | .hooks = (1 << NF_INET_POST_ROUTING) | |
| 114 | (1 << NF_INET_LOCAL_OUT), | 114 | (1 << NF_INET_LOCAL_IN), |
| 115 | .me = THIS_MODULE, | 115 | .me = THIS_MODULE, |
| 116 | }, | 116 | }, |
| 117 | { | 117 | { |
| @@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
| 123 | .family = NFPROTO_IPV4, | 123 | .family = NFPROTO_IPV4, |
| 124 | .table = "nat", | 124 | .table = "nat", |
| 125 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 125 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
| 126 | (1 << NF_INET_LOCAL_IN), | 126 | (1 << NF_INET_LOCAL_OUT), |
| 127 | .me = THIS_MODULE, | 127 | .me = THIS_MODULE, |
| 128 | }, | 128 | }, |
| 129 | { | 129 | { |
| @@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
| 133 | .targetsize = sizeof(struct nf_nat_range), | 133 | .targetsize = sizeof(struct nf_nat_range), |
| 134 | .table = "nat", | 134 | .table = "nat", |
| 135 | .hooks = (1 << NF_INET_POST_ROUTING) | | 135 | .hooks = (1 << NF_INET_POST_ROUTING) | |
| 136 | (1 << NF_INET_LOCAL_OUT), | 136 | (1 << NF_INET_LOCAL_IN), |
| 137 | .me = THIS_MODULE, | 137 | .me = THIS_MODULE, |
| 138 | }, | 138 | }, |
| 139 | { | 139 | { |
| @@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
| 143 | .targetsize = sizeof(struct nf_nat_range), | 143 | .targetsize = sizeof(struct nf_nat_range), |
| 144 | .table = "nat", | 144 | .table = "nat", |
| 145 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 145 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
| 146 | (1 << NF_INET_LOCAL_IN), | 146 | (1 << NF_INET_LOCAL_OUT), |
| 147 | .me = THIS_MODULE, | 147 | .me = THIS_MODULE, |
| 148 | }, | 148 | }, |
| 149 | }; | 149 | }; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 01e944a017a4..4da797fa5ec5 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk); | |||
| 138 | static DEFINE_RWLOCK(nl_table_lock); | 138 | static DEFINE_RWLOCK(nl_table_lock); |
| 139 | static atomic_t nl_table_users = ATOMIC_INIT(0); | 139 | static atomic_t nl_table_users = ATOMIC_INIT(0); |
| 140 | 140 | ||
| 141 | #define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); | ||
| 142 | |||
| 141 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); | 143 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); |
| 142 | 144 | ||
| 143 | static inline u32 netlink_group_mask(u32 group) | 145 | static inline u32 netlink_group_mask(u32 group) |
| @@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk) | |||
| 345 | struct hlist_node *node; | 347 | struct hlist_node *node; |
| 346 | unsigned long mask; | 348 | unsigned long mask; |
| 347 | unsigned int i; | 349 | unsigned int i; |
| 350 | struct listeners *listeners; | ||
| 351 | |||
| 352 | listeners = nl_deref_protected(tbl->listeners); | ||
| 353 | if (!listeners) | ||
| 354 | return; | ||
| 348 | 355 | ||
| 349 | for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { | 356 | for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { |
| 350 | mask = 0; | 357 | mask = 0; |
| @@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk) | |||
| 352 | if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) | 359 | if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) |
| 353 | mask |= nlk_sk(sk)->groups[i]; | 360 | mask |= nlk_sk(sk)->groups[i]; |
| 354 | } | 361 | } |
| 355 | tbl->listeners->masks[i] = mask; | 362 | listeners->masks[i] = mask; |
| 356 | } | 363 | } |
| 357 | /* this function is only called with the netlink table "grabbed", which | 364 | /* this function is only called with the netlink table "grabbed", which |
| 358 | * makes sure updates are visible before bind or setsockopt return. */ | 365 | * makes sure updates are visible before bind or setsockopt return. */ |
| @@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock) | |||
| 536 | if (netlink_is_kernel(sk)) { | 543 | if (netlink_is_kernel(sk)) { |
| 537 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); | 544 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); |
| 538 | if (--nl_table[sk->sk_protocol].registered == 0) { | 545 | if (--nl_table[sk->sk_protocol].registered == 0) { |
| 539 | kfree(nl_table[sk->sk_protocol].listeners); | 546 | struct listeners *old; |
| 547 | |||
| 548 | old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); | ||
| 549 | RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); | ||
| 550 | kfree_rcu(old, rcu); | ||
| 540 | nl_table[sk->sk_protocol].module = NULL; | 551 | nl_table[sk->sk_protocol].module = NULL; |
| 541 | nl_table[sk->sk_protocol].bind = NULL; | 552 | nl_table[sk->sk_protocol].bind = NULL; |
| 542 | nl_table[sk->sk_protocol].flags = 0; | 553 | nl_table[sk->sk_protocol].flags = 0; |
| @@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) | |||
| 982 | rcu_read_lock(); | 993 | rcu_read_lock(); |
| 983 | listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); | 994 | listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); |
| 984 | 995 | ||
| 985 | if (group - 1 < nl_table[sk->sk_protocol].groups) | 996 | if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) |
| 986 | res = test_bit(group - 1, listeners->masks); | 997 | res = test_bit(group - 1, listeners->masks); |
| 987 | 998 | ||
| 988 | rcu_read_unlock(); | 999 | rcu_read_unlock(); |
| @@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) | |||
| 1625 | new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); | 1636 | new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); |
| 1626 | if (!new) | 1637 | if (!new) |
| 1627 | return -ENOMEM; | 1638 | return -ENOMEM; |
| 1628 | old = rcu_dereference_protected(tbl->listeners, 1); | 1639 | old = nl_deref_protected(tbl->listeners); |
| 1629 | memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); | 1640 | memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); |
| 1630 | rcu_assign_pointer(tbl->listeners, new); | 1641 | rcu_assign_pointer(tbl->listeners, new); |
| 1631 | 1642 | ||
