diff options
Diffstat (limited to 'net')
90 files changed, 1049 insertions, 701 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index ec9909935fb6..175273f38cb1 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
| @@ -307,9 +307,11 @@ static void vlan_sync_address(struct net_device *dev, | |||
| 307 | static void vlan_transfer_features(struct net_device *dev, | 307 | static void vlan_transfer_features(struct net_device *dev, |
| 308 | struct net_device *vlandev) | 308 | struct net_device *vlandev) |
| 309 | { | 309 | { |
| 310 | struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); | ||
| 311 | |||
| 310 | vlandev->gso_max_size = dev->gso_max_size; | 312 | vlandev->gso_max_size = dev->gso_max_size; |
| 311 | 313 | ||
| 312 | if (dev->features & NETIF_F_HW_VLAN_CTAG_TX) | 314 | if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto)) |
| 313 | vlandev->hard_header_len = dev->hard_header_len; | 315 | vlandev->hard_header_len = dev->hard_header_len; |
| 314 | else | 316 | else |
| 315 | vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN; | 317 | vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index de51c48c4393..27bfe2f8e2de 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -538,6 +538,9 @@ static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev | |||
| 538 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); | 538 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
| 539 | struct net_device *real_dev = vlan->real_dev; | 539 | struct net_device *real_dev = vlan->real_dev; |
| 540 | 540 | ||
| 541 | if (saddr == NULL) | ||
| 542 | saddr = dev->dev_addr; | ||
| 543 | |||
| 541 | return dev_hard_header(skb, real_dev, type, daddr, saddr, len); | 544 | return dev_hard_header(skb, real_dev, type, daddr, saddr, len); |
| 542 | } | 545 | } |
| 543 | 546 | ||
| @@ -575,6 +578,9 @@ static int vlan_dev_init(struct net_device *dev) | |||
| 575 | 578 | ||
| 576 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX; | 579 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX; |
| 577 | dev->gso_max_size = real_dev->gso_max_size; | 580 | dev->gso_max_size = real_dev->gso_max_size; |
| 581 | if (dev->features & NETIF_F_VLAN_FEATURES) | ||
| 582 | netdev_warn(real_dev, "VLAN features are set incorrectly. Q-in-Q configurations may not work correctly.\n"); | ||
| 583 | |||
| 578 | 584 | ||
| 579 | /* ipv6 shared card related stuff */ | 585 | /* ipv6 shared card related stuff */ |
| 580 | dev->dev_id = real_dev->dev_id; | 586 | dev->dev_id = real_dev->dev_id; |
| @@ -589,7 +595,8 @@ static int vlan_dev_init(struct net_device *dev) | |||
| 589 | #endif | 595 | #endif |
| 590 | 596 | ||
| 591 | dev->needed_headroom = real_dev->needed_headroom; | 597 | dev->needed_headroom = real_dev->needed_headroom; |
| 592 | if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) { | 598 | if (vlan_hw_offload_capable(real_dev->features, |
| 599 | vlan_dev_priv(dev)->vlan_proto)) { | ||
| 593 | dev->header_ops = &vlan_passthru_header_ops; | 600 | dev->header_ops = &vlan_passthru_header_ops; |
| 594 | dev->hard_header_len = real_dev->hard_header_len; | 601 | dev->hard_header_len = real_dev->hard_header_len; |
| 595 | } else { | 602 | } else { |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 63f0455c0bc3..8fe8b71b487a 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -49,14 +49,14 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 49 | brstats->tx_bytes += skb->len; | 49 | brstats->tx_bytes += skb->len; |
| 50 | u64_stats_update_end(&brstats->syncp); | 50 | u64_stats_update_end(&brstats->syncp); |
| 51 | 51 | ||
| 52 | if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid)) | ||
| 53 | goto out; | ||
| 54 | |||
| 55 | BR_INPUT_SKB_CB(skb)->brdev = dev; | 52 | BR_INPUT_SKB_CB(skb)->brdev = dev; |
| 56 | 53 | ||
| 57 | skb_reset_mac_header(skb); | 54 | skb_reset_mac_header(skb); |
| 58 | skb_pull(skb, ETH_HLEN); | 55 | skb_pull(skb, ETH_HLEN); |
| 59 | 56 | ||
| 57 | if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid)) | ||
| 58 | goto out; | ||
| 59 | |||
| 60 | if (is_broadcast_ether_addr(dest)) | 60 | if (is_broadcast_ether_addr(dest)) |
| 61 | br_flood_deliver(br, skb, false); | 61 | br_flood_deliver(br, skb, false); |
| 62 | else if (is_multicast_ether_addr(dest)) { | 62 | else if (is_multicast_ether_addr(dest)) { |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 28d544627422..d0cca3c65f01 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -29,6 +29,7 @@ static int br_pass_frame_up(struct sk_buff *skb) | |||
| 29 | struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; | 29 | struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; |
| 30 | struct net_bridge *br = netdev_priv(brdev); | 30 | struct net_bridge *br = netdev_priv(brdev); |
| 31 | struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats); | 31 | struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats); |
| 32 | struct net_port_vlans *pv; | ||
| 32 | 33 | ||
| 33 | u64_stats_update_begin(&brstats->syncp); | 34 | u64_stats_update_begin(&brstats->syncp); |
| 34 | brstats->rx_packets++; | 35 | brstats->rx_packets++; |
| @@ -39,18 +40,18 @@ static int br_pass_frame_up(struct sk_buff *skb) | |||
| 39 | * packet is allowed except in promisc modue when someone | 40 | * packet is allowed except in promisc modue when someone |
| 40 | * may be running packet capture. | 41 | * may be running packet capture. |
| 41 | */ | 42 | */ |
| 43 | pv = br_get_vlan_info(br); | ||
| 42 | if (!(brdev->flags & IFF_PROMISC) && | 44 | if (!(brdev->flags & IFF_PROMISC) && |
| 43 | !br_allowed_egress(br, br_get_vlan_info(br), skb)) { | 45 | !br_allowed_egress(br, pv, skb)) { |
| 44 | kfree_skb(skb); | 46 | kfree_skb(skb); |
| 45 | return NET_RX_DROP; | 47 | return NET_RX_DROP; |
| 46 | } | 48 | } |
| 47 | 49 | ||
| 48 | skb = br_handle_vlan(br, br_get_vlan_info(br), skb); | ||
| 49 | if (!skb) | ||
| 50 | return NET_RX_DROP; | ||
| 51 | |||
| 52 | indev = skb->dev; | 50 | indev = skb->dev; |
| 53 | skb->dev = brdev; | 51 | skb->dev = brdev; |
| 52 | skb = br_handle_vlan(br, pv, skb); | ||
| 53 | if (!skb) | ||
| 54 | return NET_RX_DROP; | ||
| 54 | 55 | ||
| 55 | return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, | 56 | return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, |
| 56 | netif_receive_skb); | 57 | netif_receive_skb); |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index ef66365b7354..93067ecdb9a2 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -1127,9 +1127,10 @@ static void br_multicast_query_received(struct net_bridge *br, | |||
| 1127 | struct net_bridge_port *port, | 1127 | struct net_bridge_port *port, |
| 1128 | struct bridge_mcast_querier *querier, | 1128 | struct bridge_mcast_querier *querier, |
| 1129 | int saddr, | 1129 | int saddr, |
| 1130 | bool is_general_query, | ||
| 1130 | unsigned long max_delay) | 1131 | unsigned long max_delay) |
| 1131 | { | 1132 | { |
| 1132 | if (saddr) | 1133 | if (saddr && is_general_query) |
| 1133 | br_multicast_update_querier_timer(br, querier, max_delay); | 1134 | br_multicast_update_querier_timer(br, querier, max_delay); |
| 1134 | else if (timer_pending(&querier->timer)) | 1135 | else if (timer_pending(&querier->timer)) |
| 1135 | return; | 1136 | return; |
| @@ -1181,8 +1182,16 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
| 1181 | IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; | 1182 | IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; |
| 1182 | } | 1183 | } |
| 1183 | 1184 | ||
| 1185 | /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer | ||
| 1186 | * all-systems destination addresses (224.0.0.1) for general queries | ||
| 1187 | */ | ||
| 1188 | if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) { | ||
| 1189 | err = -EINVAL; | ||
| 1190 | goto out; | ||
| 1191 | } | ||
| 1192 | |||
| 1184 | br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, | 1193 | br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, |
| 1185 | max_delay); | 1194 | !group, max_delay); |
| 1186 | 1195 | ||
| 1187 | if (!group) | 1196 | if (!group) |
| 1188 | goto out; | 1197 | goto out; |
| @@ -1228,6 +1237,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1228 | unsigned long max_delay; | 1237 | unsigned long max_delay; |
| 1229 | unsigned long now = jiffies; | 1238 | unsigned long now = jiffies; |
| 1230 | const struct in6_addr *group = NULL; | 1239 | const struct in6_addr *group = NULL; |
| 1240 | bool is_general_query; | ||
| 1231 | int err = 0; | 1241 | int err = 0; |
| 1232 | 1242 | ||
| 1233 | spin_lock(&br->multicast_lock); | 1243 | spin_lock(&br->multicast_lock); |
| @@ -1235,6 +1245,12 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1235 | (port && port->state == BR_STATE_DISABLED)) | 1245 | (port && port->state == BR_STATE_DISABLED)) |
| 1236 | goto out; | 1246 | goto out; |
| 1237 | 1247 | ||
| 1248 | /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */ | ||
| 1249 | if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) { | ||
| 1250 | err = -EINVAL; | ||
| 1251 | goto out; | ||
| 1252 | } | ||
| 1253 | |||
| 1238 | if (skb->len == sizeof(*mld)) { | 1254 | if (skb->len == sizeof(*mld)) { |
| 1239 | if (!pskb_may_pull(skb, sizeof(*mld))) { | 1255 | if (!pskb_may_pull(skb, sizeof(*mld))) { |
| 1240 | err = -EINVAL; | 1256 | err = -EINVAL; |
| @@ -1256,8 +1272,19 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1256 | max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); | 1272 | max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); |
| 1257 | } | 1273 | } |
| 1258 | 1274 | ||
| 1275 | is_general_query = group && ipv6_addr_any(group); | ||
| 1276 | |||
| 1277 | /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer | ||
| 1278 | * all-nodes destination address (ff02::1) for general queries | ||
| 1279 | */ | ||
| 1280 | if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) { | ||
| 1281 | err = -EINVAL; | ||
| 1282 | goto out; | ||
| 1283 | } | ||
| 1284 | |||
| 1259 | br_multicast_query_received(br, port, &br->ip6_querier, | 1285 | br_multicast_query_received(br, port, &br->ip6_querier, |
| 1260 | !ipv6_addr_any(&ip6h->saddr), max_delay); | 1286 | !ipv6_addr_any(&ip6h->saddr), |
| 1287 | is_general_query, max_delay); | ||
| 1261 | 1288 | ||
| 1262 | if (!group) | 1289 | if (!group) |
| 1263 | goto out; | 1290 | goto out; |
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 8249ca764c79..f23c74b3a953 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
| @@ -119,22 +119,6 @@ static void __vlan_flush(struct net_port_vlans *v) | |||
| 119 | kfree_rcu(v, rcu); | 119 | kfree_rcu(v, rcu); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /* Strip the tag from the packet. Will return skb with tci set 0. */ | ||
| 123 | static struct sk_buff *br_vlan_untag(struct sk_buff *skb) | ||
| 124 | { | ||
| 125 | if (skb->protocol != htons(ETH_P_8021Q)) { | ||
| 126 | skb->vlan_tci = 0; | ||
| 127 | return skb; | ||
| 128 | } | ||
| 129 | |||
| 130 | skb->vlan_tci = 0; | ||
| 131 | skb = vlan_untag(skb); | ||
| 132 | if (skb) | ||
| 133 | skb->vlan_tci = 0; | ||
| 134 | |||
| 135 | return skb; | ||
| 136 | } | ||
| 137 | |||
| 138 | struct sk_buff *br_handle_vlan(struct net_bridge *br, | 122 | struct sk_buff *br_handle_vlan(struct net_bridge *br, |
| 139 | const struct net_port_vlans *pv, | 123 | const struct net_port_vlans *pv, |
| 140 | struct sk_buff *skb) | 124 | struct sk_buff *skb) |
| @@ -144,13 +128,27 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, | |||
| 144 | if (!br->vlan_enabled) | 128 | if (!br->vlan_enabled) |
| 145 | goto out; | 129 | goto out; |
| 146 | 130 | ||
| 131 | /* Vlan filter table must be configured at this point. The | ||
| 132 | * only exception is the bridge is set in promisc mode and the | ||
| 133 | * packet is destined for the bridge device. In this case | ||
| 134 | * pass the packet as is. | ||
| 135 | */ | ||
| 136 | if (!pv) { | ||
| 137 | if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { | ||
| 138 | goto out; | ||
| 139 | } else { | ||
| 140 | kfree_skb(skb); | ||
| 141 | return NULL; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 147 | /* At this point, we know that the frame was filtered and contains | 145 | /* At this point, we know that the frame was filtered and contains |
| 148 | * a valid vlan id. If the vlan id is set in the untagged bitmap, | 146 | * a valid vlan id. If the vlan id is set in the untagged bitmap, |
| 149 | * send untagged; otherwise, send tagged. | 147 | * send untagged; otherwise, send tagged. |
| 150 | */ | 148 | */ |
| 151 | br_vlan_get_tag(skb, &vid); | 149 | br_vlan_get_tag(skb, &vid); |
| 152 | if (test_bit(vid, pv->untagged_bitmap)) | 150 | if (test_bit(vid, pv->untagged_bitmap)) |
| 153 | skb = br_vlan_untag(skb); | 151 | skb->vlan_tci = 0; |
| 154 | 152 | ||
| 155 | out: | 153 | out: |
| 156 | return skb; | 154 | return skb; |
| @@ -174,6 +172,18 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 174 | if (!v) | 172 | if (!v) |
| 175 | return false; | 173 | return false; |
| 176 | 174 | ||
| 175 | /* If vlan tx offload is disabled on bridge device and frame was | ||
| 176 | * sent from vlan device on the bridge device, it does not have | ||
| 177 | * HW accelerated vlan tag. | ||
| 178 | */ | ||
| 179 | if (unlikely(!vlan_tx_tag_present(skb) && | ||
| 180 | (skb->protocol == htons(ETH_P_8021Q) || | ||
| 181 | skb->protocol == htons(ETH_P_8021AD)))) { | ||
| 182 | skb = vlan_untag(skb); | ||
| 183 | if (unlikely(!skb)) | ||
| 184 | return false; | ||
| 185 | } | ||
| 186 | |||
| 177 | err = br_vlan_get_tag(skb, vid); | 187 | err = br_vlan_get_tag(skb, vid); |
| 178 | if (!*vid) { | 188 | if (!*vid) { |
| 179 | u16 pvid = br_get_pvid(v); | 189 | u16 pvid = br_get_pvid(v); |
diff --git a/net/can/raw.c b/net/can/raw.c index 8be757cca2ec..081e81fd017f 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
| @@ -121,13 +121,9 @@ static void raw_rcv(struct sk_buff *oskb, void *data) | |||
| 121 | if (!ro->recv_own_msgs && oskb->sk == sk) | 121 | if (!ro->recv_own_msgs && oskb->sk == sk) |
| 122 | return; | 122 | return; |
| 123 | 123 | ||
| 124 | /* do not pass frames with DLC > 8 to a legacy socket */ | 124 | /* do not pass non-CAN2.0 frames to a legacy socket */ |
| 125 | if (!ro->fd_frames) { | 125 | if (!ro->fd_frames && oskb->len != CAN_MTU) |
| 126 | struct canfd_frame *cfd = (struct canfd_frame *)oskb->data; | 126 | return; |
| 127 | |||
| 128 | if (unlikely(cfd->len > CAN_MAX_DLEN)) | ||
| 129 | return; | ||
| 130 | } | ||
| 131 | 127 | ||
| 132 | /* clone the given skb to be able to enqueue it into the rcv queue */ | 128 | /* clone the given skb to be able to enqueue it into the rcv queue */ |
| 133 | skb = skb_clone(oskb, GFP_ATOMIC); | 129 | skb = skb_clone(oskb, GFP_ATOMIC); |
| @@ -738,9 +734,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 738 | struct msghdr *msg, size_t size, int flags) | 734 | struct msghdr *msg, size_t size, int flags) |
| 739 | { | 735 | { |
| 740 | struct sock *sk = sock->sk; | 736 | struct sock *sk = sock->sk; |
| 741 | struct raw_sock *ro = raw_sk(sk); | ||
| 742 | struct sk_buff *skb; | 737 | struct sk_buff *skb; |
| 743 | int rxmtu; | ||
| 744 | int err = 0; | 738 | int err = 0; |
| 745 | int noblock; | 739 | int noblock; |
| 746 | 740 | ||
| @@ -751,20 +745,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 751 | if (!skb) | 745 | if (!skb) |
| 752 | return err; | 746 | return err; |
| 753 | 747 | ||
| 754 | /* | 748 | if (size < skb->len) |
| 755 | * when serving a legacy socket the DLC <= 8 is already checked inside | ||
| 756 | * raw_rcv(). Now check if we need to pass a canfd_frame to a legacy | ||
| 757 | * socket and cut the possible CANFD_MTU/CAN_MTU length to CAN_MTU | ||
| 758 | */ | ||
| 759 | if (!ro->fd_frames) | ||
| 760 | rxmtu = CAN_MTU; | ||
| 761 | else | ||
| 762 | rxmtu = skb->len; | ||
| 763 | |||
| 764 | if (size < rxmtu) | ||
| 765 | msg->msg_flags |= MSG_TRUNC; | 749 | msg->msg_flags |= MSG_TRUNC; |
| 766 | else | 750 | else |
| 767 | size = rxmtu; | 751 | size = skb->len; |
| 768 | 752 | ||
| 769 | err = memcpy_toiovec(msg->msg_iov, skb->data, size); | 753 | err = memcpy_toiovec(msg->msg_iov, skb->data, size); |
| 770 | if (err < 0) { | 754 | if (err < 0) { |
diff --git a/net/compat.c b/net/compat.c index f50161fb812e..9a76eaf63184 100644 --- a/net/compat.c +++ b/net/compat.c | |||
| @@ -384,8 +384,8 @@ static int compat_sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 384 | return sock_setsockopt(sock, level, optname, optval, optlen); | 384 | return sock_setsockopt(sock, level, optname, optval, optlen); |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, | 387 | COMPAT_SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, |
| 388 | char __user *optval, unsigned int optlen) | 388 | char __user *, optval, unsigned int, optlen) |
| 389 | { | 389 | { |
| 390 | int err; | 390 | int err; |
| 391 | struct socket *sock = sockfd_lookup(fd, &err); | 391 | struct socket *sock = sockfd_lookup(fd, &err); |
| @@ -504,8 +504,8 @@ int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *usersta | |||
| 504 | } | 504 | } |
| 505 | EXPORT_SYMBOL(compat_sock_get_timestampns); | 505 | EXPORT_SYMBOL(compat_sock_get_timestampns); |
| 506 | 506 | ||
| 507 | asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, | 507 | COMPAT_SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, |
| 508 | char __user *optval, int __user *optlen) | 508 | char __user *, optval, int __user *, optlen) |
| 509 | { | 509 | { |
| 510 | int err; | 510 | int err; |
| 511 | struct socket *sock = sockfd_lookup(fd, &err); | 511 | struct socket *sock = sockfd_lookup(fd, &err); |
| @@ -735,15 +735,15 @@ static unsigned char nas[21] = { | |||
| 735 | }; | 735 | }; |
| 736 | #undef AL | 736 | #undef AL |
| 737 | 737 | ||
| 738 | asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) | 738 | COMPAT_SYSCALL_DEFINE3(sendmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags) |
| 739 | { | 739 | { |
| 740 | if (flags & MSG_CMSG_COMPAT) | 740 | if (flags & MSG_CMSG_COMPAT) |
| 741 | return -EINVAL; | 741 | return -EINVAL; |
| 742 | return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | 742 | return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); |
| 743 | } | 743 | } |
| 744 | 744 | ||
| 745 | asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, | 745 | COMPAT_SYSCALL_DEFINE4(sendmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, |
| 746 | unsigned int vlen, unsigned int flags) | 746 | unsigned int, vlen, unsigned int, flags) |
| 747 | { | 747 | { |
| 748 | if (flags & MSG_CMSG_COMPAT) | 748 | if (flags & MSG_CMSG_COMPAT) |
| 749 | return -EINVAL; | 749 | return -EINVAL; |
| @@ -751,28 +751,28 @@ asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, | |||
| 751 | flags | MSG_CMSG_COMPAT); | 751 | flags | MSG_CMSG_COMPAT); |
| 752 | } | 752 | } |
| 753 | 753 | ||
| 754 | asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) | 754 | COMPAT_SYSCALL_DEFINE3(recvmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags) |
| 755 | { | 755 | { |
| 756 | if (flags & MSG_CMSG_COMPAT) | 756 | if (flags & MSG_CMSG_COMPAT) |
| 757 | return -EINVAL; | 757 | return -EINVAL; |
| 758 | return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | 758 | return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); |
| 759 | } | 759 | } |
| 760 | 760 | ||
| 761 | asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags) | 761 | COMPAT_SYSCALL_DEFINE4(recv, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags) |
| 762 | { | 762 | { |
| 763 | return sys_recv(fd, buf, len, flags | MSG_CMSG_COMPAT); | 763 | return sys_recv(fd, buf, len, flags | MSG_CMSG_COMPAT); |
| 764 | } | 764 | } |
| 765 | 765 | ||
| 766 | asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len, | 766 | COMPAT_SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, buf, compat_size_t, len, |
| 767 | unsigned int flags, struct sockaddr __user *addr, | 767 | unsigned int, flags, struct sockaddr __user *, addr, |
| 768 | int __user *addrlen) | 768 | int __user *, addrlen) |
| 769 | { | 769 | { |
| 770 | return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); | 770 | return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, | 773 | COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, |
| 774 | unsigned int vlen, unsigned int flags, | 774 | unsigned int, vlen, unsigned int, flags, |
| 775 | struct compat_timespec __user *timeout) | 775 | struct compat_timespec __user *, timeout) |
| 776 | { | 776 | { |
| 777 | int datagrams; | 777 | int datagrams; |
| 778 | struct timespec ktspec; | 778 | struct timespec ktspec; |
| @@ -795,7 +795,7 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, | |||
| 795 | return datagrams; | 795 | return datagrams; |
| 796 | } | 796 | } |
| 797 | 797 | ||
| 798 | asmlinkage long compat_sys_socketcall(int call, u32 __user *args) | 798 | COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args) |
| 799 | { | 799 | { |
| 800 | int ret; | 800 | int ret; |
| 801 | u32 a[6]; | 801 | u32 a[6]; |
diff --git a/net/core/dev.c b/net/core/dev.c index b1b0c8d4d7df..45fa2f11f84d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2286,7 +2286,7 @@ out: | |||
| 2286 | } | 2286 | } |
| 2287 | EXPORT_SYMBOL(skb_checksum_help); | 2287 | EXPORT_SYMBOL(skb_checksum_help); |
| 2288 | 2288 | ||
| 2289 | __be16 skb_network_protocol(struct sk_buff *skb) | 2289 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
| 2290 | { | 2290 | { |
| 2291 | __be16 type = skb->protocol; | 2291 | __be16 type = skb->protocol; |
| 2292 | int vlan_depth = ETH_HLEN; | 2292 | int vlan_depth = ETH_HLEN; |
| @@ -2313,6 +2313,8 @@ __be16 skb_network_protocol(struct sk_buff *skb) | |||
| 2313 | vlan_depth += VLAN_HLEN; | 2313 | vlan_depth += VLAN_HLEN; |
| 2314 | } | 2314 | } |
| 2315 | 2315 | ||
| 2316 | *depth = vlan_depth; | ||
| 2317 | |||
| 2316 | return type; | 2318 | return type; |
| 2317 | } | 2319 | } |
| 2318 | 2320 | ||
| @@ -2326,12 +2328,13 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb, | |||
| 2326 | { | 2328 | { |
| 2327 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); | 2329 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); |
| 2328 | struct packet_offload *ptype; | 2330 | struct packet_offload *ptype; |
| 2329 | __be16 type = skb_network_protocol(skb); | 2331 | int vlan_depth = skb->mac_len; |
| 2332 | __be16 type = skb_network_protocol(skb, &vlan_depth); | ||
| 2330 | 2333 | ||
| 2331 | if (unlikely(!type)) | 2334 | if (unlikely(!type)) |
| 2332 | return ERR_PTR(-EINVAL); | 2335 | return ERR_PTR(-EINVAL); |
| 2333 | 2336 | ||
| 2334 | __skb_pull(skb, skb->mac_len); | 2337 | __skb_pull(skb, vlan_depth); |
| 2335 | 2338 | ||
| 2336 | rcu_read_lock(); | 2339 | rcu_read_lock(); |
| 2337 | list_for_each_entry_rcu(ptype, &offload_base, list) { | 2340 | list_for_each_entry_rcu(ptype, &offload_base, list) { |
| @@ -2498,8 +2501,10 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
| 2498 | const struct net_device *dev, | 2501 | const struct net_device *dev, |
| 2499 | netdev_features_t features) | 2502 | netdev_features_t features) |
| 2500 | { | 2503 | { |
| 2504 | int tmp; | ||
| 2505 | |||
| 2501 | if (skb->ip_summed != CHECKSUM_NONE && | 2506 | if (skb->ip_summed != CHECKSUM_NONE && |
| 2502 | !can_checksum_protocol(features, skb_network_protocol(skb))) { | 2507 | !can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) { |
| 2503 | features &= ~NETIF_F_ALL_CSUM; | 2508 | features &= ~NETIF_F_ALL_CSUM; |
| 2504 | } else if (illegal_highdma(dev, skb)) { | 2509 | } else if (illegal_highdma(dev, skb)) { |
| 2505 | features &= ~NETIF_F_SG; | 2510 | features &= ~NETIF_F_SG; |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b9e9e0d38672..e16129019c66 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -766,9 +766,6 @@ static void neigh_periodic_work(struct work_struct *work) | |||
| 766 | nht = rcu_dereference_protected(tbl->nht, | 766 | nht = rcu_dereference_protected(tbl->nht, |
| 767 | lockdep_is_held(&tbl->lock)); | 767 | lockdep_is_held(&tbl->lock)); |
| 768 | 768 | ||
| 769 | if (atomic_read(&tbl->entries) < tbl->gc_thresh1) | ||
| 770 | goto out; | ||
| 771 | |||
| 772 | /* | 769 | /* |
| 773 | * periodically recompute ReachableTime from random function | 770 | * periodically recompute ReachableTime from random function |
| 774 | */ | 771 | */ |
| @@ -781,6 +778,9 @@ static void neigh_periodic_work(struct work_struct *work) | |||
| 781 | neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); | 778 | neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); |
| 782 | } | 779 | } |
| 783 | 780 | ||
| 781 | if (atomic_read(&tbl->entries) < tbl->gc_thresh1) | ||
| 782 | goto out; | ||
| 783 | |||
| 784 | for (i = 0 ; i < (1 << nht->hash_shift); i++) { | 784 | for (i = 0 ; i < (1 << nht->hash_shift); i++) { |
| 785 | np = &nht->hash_buckets[i]; | 785 | np = &nht->hash_buckets[i]; |
| 786 | 786 | ||
| @@ -3046,7 +3046,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
| 3046 | if (!t) | 3046 | if (!t) |
| 3047 | goto err; | 3047 | goto err; |
| 3048 | 3048 | ||
| 3049 | for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) { | 3049 | for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) { |
| 3050 | t->neigh_vars[i].data += (long) p; | 3050 | t->neigh_vars[i].data += (long) p; |
| 3051 | t->neigh_vars[i].extra1 = dev; | 3051 | t->neigh_vars[i].extra1 = dev; |
| 3052 | t->neigh_vars[i].extra2 = p; | 3052 | t->neigh_vars[i].extra2 = p; |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a664f7829a6d..df9e6b1a9759 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -742,7 +742,7 @@ static bool pkt_is_ns(struct sk_buff *skb) | |||
| 742 | struct nd_msg *msg; | 742 | struct nd_msg *msg; |
| 743 | struct ipv6hdr *hdr; | 743 | struct ipv6hdr *hdr; |
| 744 | 744 | ||
| 745 | if (skb->protocol != htons(ETH_P_ARP)) | 745 | if (skb->protocol != htons(ETH_P_IPV6)) |
| 746 | return false; | 746 | return false; |
| 747 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg))) | 747 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg))) |
| 748 | return false; | 748 | return false; |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1a0dac2ef9ad..120eecc0f5a4 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -2121,12 +2121,13 @@ EXPORT_SYMBOL(rtmsg_ifinfo); | |||
| 2121 | static int nlmsg_populate_fdb_fill(struct sk_buff *skb, | 2121 | static int nlmsg_populate_fdb_fill(struct sk_buff *skb, |
| 2122 | struct net_device *dev, | 2122 | struct net_device *dev, |
| 2123 | u8 *addr, u32 pid, u32 seq, | 2123 | u8 *addr, u32 pid, u32 seq, |
| 2124 | int type, unsigned int flags) | 2124 | int type, unsigned int flags, |
| 2125 | int nlflags) | ||
| 2125 | { | 2126 | { |
| 2126 | struct nlmsghdr *nlh; | 2127 | struct nlmsghdr *nlh; |
| 2127 | struct ndmsg *ndm; | 2128 | struct ndmsg *ndm; |
| 2128 | 2129 | ||
| 2129 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI); | 2130 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), nlflags); |
| 2130 | if (!nlh) | 2131 | if (!nlh) |
| 2131 | return -EMSGSIZE; | 2132 | return -EMSGSIZE; |
| 2132 | 2133 | ||
| @@ -2164,7 +2165,7 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type) | |||
| 2164 | if (!skb) | 2165 | if (!skb) |
| 2165 | goto errout; | 2166 | goto errout; |
| 2166 | 2167 | ||
| 2167 | err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF); | 2168 | err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF, 0); |
| 2168 | if (err < 0) { | 2169 | if (err < 0) { |
| 2169 | kfree_skb(skb); | 2170 | kfree_skb(skb); |
| 2170 | goto errout; | 2171 | goto errout; |
| @@ -2389,7 +2390,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb, | |||
| 2389 | 2390 | ||
| 2390 | err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, | 2391 | err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, |
| 2391 | portid, seq, | 2392 | portid, seq, |
| 2392 | RTM_NEWNEIGH, NTF_SELF); | 2393 | RTM_NEWNEIGH, NTF_SELF, |
| 2394 | NLM_F_MULTI); | ||
| 2393 | if (err < 0) | 2395 | if (err < 0) |
| 2394 | return err; | 2396 | return err; |
| 2395 | skip: | 2397 | skip: |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5976ef0846bd..90b96a11b974 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -707,9 +707,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
| 707 | new->mark = old->mark; | 707 | new->mark = old->mark; |
| 708 | new->skb_iif = old->skb_iif; | 708 | new->skb_iif = old->skb_iif; |
| 709 | __nf_copy(new, old); | 709 | __nf_copy(new, old); |
| 710 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
| 711 | new->nf_trace = old->nf_trace; | ||
| 712 | #endif | ||
| 713 | #ifdef CONFIG_NET_SCHED | 710 | #ifdef CONFIG_NET_SCHED |
| 714 | new->tc_index = old->tc_index; | 711 | new->tc_index = old->tc_index; |
| 715 | #ifdef CONFIG_NET_CLS_ACT | 712 | #ifdef CONFIG_NET_CLS_ACT |
| @@ -2130,25 +2127,31 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_headlen); | |||
| 2130 | * | 2127 | * |
| 2131 | * The `hlen` as calculated by skb_zerocopy_headlen() specifies the | 2128 | * The `hlen` as calculated by skb_zerocopy_headlen() specifies the |
| 2132 | * headroom in the `to` buffer. | 2129 | * headroom in the `to` buffer. |
| 2130 | * | ||
| 2131 | * Return value: | ||
| 2132 | * 0: everything is OK | ||
| 2133 | * -ENOMEM: couldn't orphan frags of @from due to lack of memory | ||
| 2134 | * -EFAULT: skb_copy_bits() found some problem with skb geometry | ||
| 2133 | */ | 2135 | */ |
| 2134 | void | 2136 | int |
| 2135 | skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | 2137 | skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen) |
| 2136 | { | 2138 | { |
| 2137 | int i, j = 0; | 2139 | int i, j = 0; |
| 2138 | int plen = 0; /* length of skb->head fragment */ | 2140 | int plen = 0; /* length of skb->head fragment */ |
| 2141 | int ret; | ||
| 2139 | struct page *page; | 2142 | struct page *page; |
| 2140 | unsigned int offset; | 2143 | unsigned int offset; |
| 2141 | 2144 | ||
| 2142 | BUG_ON(!from->head_frag && !hlen); | 2145 | BUG_ON(!from->head_frag && !hlen); |
| 2143 | 2146 | ||
| 2144 | /* dont bother with small payloads */ | 2147 | /* dont bother with small payloads */ |
| 2145 | if (len <= skb_tailroom(to)) { | 2148 | if (len <= skb_tailroom(to)) |
| 2146 | skb_copy_bits(from, 0, skb_put(to, len), len); | 2149 | return skb_copy_bits(from, 0, skb_put(to, len), len); |
| 2147 | return; | ||
| 2148 | } | ||
| 2149 | 2150 | ||
| 2150 | if (hlen) { | 2151 | if (hlen) { |
| 2151 | skb_copy_bits(from, 0, skb_put(to, hlen), hlen); | 2152 | ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen); |
| 2153 | if (unlikely(ret)) | ||
| 2154 | return ret; | ||
| 2152 | len -= hlen; | 2155 | len -= hlen; |
| 2153 | } else { | 2156 | } else { |
| 2154 | plen = min_t(int, skb_headlen(from), len); | 2157 | plen = min_t(int, skb_headlen(from), len); |
| @@ -2166,6 +2169,11 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
| 2166 | to->len += len + plen; | 2169 | to->len += len + plen; |
| 2167 | to->data_len += len + plen; | 2170 | to->data_len += len + plen; |
| 2168 | 2171 | ||
| 2172 | if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) { | ||
| 2173 | skb_tx_error(from); | ||
| 2174 | return -ENOMEM; | ||
| 2175 | } | ||
| 2176 | |||
| 2169 | for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { | 2177 | for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { |
| 2170 | if (!len) | 2178 | if (!len) |
| 2171 | break; | 2179 | break; |
| @@ -2176,6 +2184,8 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
| 2176 | j++; | 2184 | j++; |
| 2177 | } | 2185 | } |
| 2178 | skb_shinfo(to)->nr_frags = j; | 2186 | skb_shinfo(to)->nr_frags = j; |
| 2187 | |||
| 2188 | return 0; | ||
| 2179 | } | 2189 | } |
| 2180 | EXPORT_SYMBOL_GPL(skb_zerocopy); | 2190 | EXPORT_SYMBOL_GPL(skb_zerocopy); |
| 2181 | 2191 | ||
| @@ -2841,81 +2851,85 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum); | |||
| 2841 | 2851 | ||
| 2842 | /** | 2852 | /** |
| 2843 | * skb_segment - Perform protocol segmentation on skb. | 2853 | * skb_segment - Perform protocol segmentation on skb. |
| 2844 | * @skb: buffer to segment | 2854 | * @head_skb: buffer to segment |
| 2845 | * @features: features for the output path (see dev->features) | 2855 | * @features: features for the output path (see dev->features) |
| 2846 | * | 2856 | * |
| 2847 | * This function performs segmentation on the given skb. It returns | 2857 | * This function performs segmentation on the given skb. It returns |
| 2848 | * a pointer to the first in a list of new skbs for the segments. | 2858 | * a pointer to the first in a list of new skbs for the segments. |
| 2849 | * In case of error it returns ERR_PTR(err). | 2859 | * In case of error it returns ERR_PTR(err). |
| 2850 | */ | 2860 | */ |
| 2851 | struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | 2861 | struct sk_buff *skb_segment(struct sk_buff *head_skb, |
| 2862 | netdev_features_t features) | ||
| 2852 | { | 2863 | { |
| 2853 | struct sk_buff *segs = NULL; | 2864 | struct sk_buff *segs = NULL; |
| 2854 | struct sk_buff *tail = NULL; | 2865 | struct sk_buff *tail = NULL; |
| 2855 | struct sk_buff *fskb = skb_shinfo(skb)->frag_list; | 2866 | struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list; |
| 2856 | skb_frag_t *skb_frag = skb_shinfo(skb)->frags; | 2867 | skb_frag_t *frag = skb_shinfo(head_skb)->frags; |
| 2857 | unsigned int mss = skb_shinfo(skb)->gso_size; | 2868 | unsigned int mss = skb_shinfo(head_skb)->gso_size; |
| 2858 | unsigned int doffset = skb->data - skb_mac_header(skb); | 2869 | unsigned int doffset = head_skb->data - skb_mac_header(head_skb); |
| 2870 | struct sk_buff *frag_skb = head_skb; | ||
| 2859 | unsigned int offset = doffset; | 2871 | unsigned int offset = doffset; |
| 2860 | unsigned int tnl_hlen = skb_tnl_header_len(skb); | 2872 | unsigned int tnl_hlen = skb_tnl_header_len(head_skb); |
| 2861 | unsigned int headroom; | 2873 | unsigned int headroom; |
| 2862 | unsigned int len; | 2874 | unsigned int len; |
| 2863 | __be16 proto; | 2875 | __be16 proto; |
| 2864 | bool csum; | 2876 | bool csum; |
| 2865 | int sg = !!(features & NETIF_F_SG); | 2877 | int sg = !!(features & NETIF_F_SG); |
| 2866 | int nfrags = skb_shinfo(skb)->nr_frags; | 2878 | int nfrags = skb_shinfo(head_skb)->nr_frags; |
| 2867 | int err = -ENOMEM; | 2879 | int err = -ENOMEM; |
| 2868 | int i = 0; | 2880 | int i = 0; |
| 2869 | int pos; | 2881 | int pos; |
| 2882 | int dummy; | ||
| 2870 | 2883 | ||
| 2871 | proto = skb_network_protocol(skb); | 2884 | proto = skb_network_protocol(head_skb, &dummy); |
| 2872 | if (unlikely(!proto)) | 2885 | if (unlikely(!proto)) |
| 2873 | return ERR_PTR(-EINVAL); | 2886 | return ERR_PTR(-EINVAL); |
| 2874 | 2887 | ||
| 2875 | csum = !!can_checksum_protocol(features, proto); | 2888 | csum = !!can_checksum_protocol(features, proto); |
| 2876 | __skb_push(skb, doffset); | 2889 | __skb_push(head_skb, doffset); |
| 2877 | headroom = skb_headroom(skb); | 2890 | headroom = skb_headroom(head_skb); |
| 2878 | pos = skb_headlen(skb); | 2891 | pos = skb_headlen(head_skb); |
| 2879 | 2892 | ||
| 2880 | do { | 2893 | do { |
| 2881 | struct sk_buff *nskb; | 2894 | struct sk_buff *nskb; |
| 2882 | skb_frag_t *frag; | 2895 | skb_frag_t *nskb_frag; |
| 2883 | int hsize; | 2896 | int hsize; |
| 2884 | int size; | 2897 | int size; |
| 2885 | 2898 | ||
| 2886 | len = skb->len - offset; | 2899 | len = head_skb->len - offset; |
| 2887 | if (len > mss) | 2900 | if (len > mss) |
| 2888 | len = mss; | 2901 | len = mss; |
| 2889 | 2902 | ||
| 2890 | hsize = skb_headlen(skb) - offset; | 2903 | hsize = skb_headlen(head_skb) - offset; |
| 2891 | if (hsize < 0) | 2904 | if (hsize < 0) |
| 2892 | hsize = 0; | 2905 | hsize = 0; |
| 2893 | if (hsize > len || !sg) | 2906 | if (hsize > len || !sg) |
| 2894 | hsize = len; | 2907 | hsize = len; |
| 2895 | 2908 | ||
| 2896 | if (!hsize && i >= nfrags && skb_headlen(fskb) && | 2909 | if (!hsize && i >= nfrags && skb_headlen(list_skb) && |
| 2897 | (skb_headlen(fskb) == len || sg)) { | 2910 | (skb_headlen(list_skb) == len || sg)) { |
| 2898 | BUG_ON(skb_headlen(fskb) > len); | 2911 | BUG_ON(skb_headlen(list_skb) > len); |
| 2899 | 2912 | ||
| 2900 | i = 0; | 2913 | i = 0; |
| 2901 | nfrags = skb_shinfo(fskb)->nr_frags; | 2914 | nfrags = skb_shinfo(list_skb)->nr_frags; |
| 2902 | skb_frag = skb_shinfo(fskb)->frags; | 2915 | frag = skb_shinfo(list_skb)->frags; |
| 2903 | pos += skb_headlen(fskb); | 2916 | frag_skb = list_skb; |
| 2917 | pos += skb_headlen(list_skb); | ||
| 2904 | 2918 | ||
| 2905 | while (pos < offset + len) { | 2919 | while (pos < offset + len) { |
| 2906 | BUG_ON(i >= nfrags); | 2920 | BUG_ON(i >= nfrags); |
| 2907 | 2921 | ||
| 2908 | size = skb_frag_size(skb_frag); | 2922 | size = skb_frag_size(frag); |
| 2909 | if (pos + size > offset + len) | 2923 | if (pos + size > offset + len) |
| 2910 | break; | 2924 | break; |
| 2911 | 2925 | ||
| 2912 | i++; | 2926 | i++; |
| 2913 | pos += size; | 2927 | pos += size; |
| 2914 | skb_frag++; | 2928 | frag++; |
| 2915 | } | 2929 | } |
| 2916 | 2930 | ||
| 2917 | nskb = skb_clone(fskb, GFP_ATOMIC); | 2931 | nskb = skb_clone(list_skb, GFP_ATOMIC); |
| 2918 | fskb = fskb->next; | 2932 | list_skb = list_skb->next; |
| 2919 | 2933 | ||
| 2920 | if (unlikely(!nskb)) | 2934 | if (unlikely(!nskb)) |
| 2921 | goto err; | 2935 | goto err; |
| @@ -2936,7 +2950,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 2936 | __skb_push(nskb, doffset); | 2950 | __skb_push(nskb, doffset); |
| 2937 | } else { | 2951 | } else { |
| 2938 | nskb = __alloc_skb(hsize + doffset + headroom, | 2952 | nskb = __alloc_skb(hsize + doffset + headroom, |
| 2939 | GFP_ATOMIC, skb_alloc_rx_flag(skb), | 2953 | GFP_ATOMIC, skb_alloc_rx_flag(head_skb), |
| 2940 | NUMA_NO_NODE); | 2954 | NUMA_NO_NODE); |
| 2941 | 2955 | ||
| 2942 | if (unlikely(!nskb)) | 2956 | if (unlikely(!nskb)) |
| @@ -2952,12 +2966,12 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 2952 | segs = nskb; | 2966 | segs = nskb; |
| 2953 | tail = nskb; | 2967 | tail = nskb; |
| 2954 | 2968 | ||
| 2955 | __copy_skb_header(nskb, skb); | 2969 | __copy_skb_header(nskb, head_skb); |
| 2956 | nskb->mac_len = skb->mac_len; | 2970 | nskb->mac_len = head_skb->mac_len; |
| 2957 | 2971 | ||
| 2958 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); | 2972 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); |
| 2959 | 2973 | ||
| 2960 | skb_copy_from_linear_data_offset(skb, -tnl_hlen, | 2974 | skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, |
| 2961 | nskb->data - tnl_hlen, | 2975 | nskb->data - tnl_hlen, |
| 2962 | doffset + tnl_hlen); | 2976 | doffset + tnl_hlen); |
| 2963 | 2977 | ||
| @@ -2966,30 +2980,32 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 2966 | 2980 | ||
| 2967 | if (!sg) { | 2981 | if (!sg) { |
| 2968 | nskb->ip_summed = CHECKSUM_NONE; | 2982 | nskb->ip_summed = CHECKSUM_NONE; |
| 2969 | nskb->csum = skb_copy_and_csum_bits(skb, offset, | 2983 | nskb->csum = skb_copy_and_csum_bits(head_skb, offset, |
| 2970 | skb_put(nskb, len), | 2984 | skb_put(nskb, len), |
| 2971 | len, 0); | 2985 | len, 0); |
| 2972 | continue; | 2986 | continue; |
| 2973 | } | 2987 | } |
| 2974 | 2988 | ||
| 2975 | frag = skb_shinfo(nskb)->frags; | 2989 | nskb_frag = skb_shinfo(nskb)->frags; |
| 2976 | 2990 | ||
| 2977 | skb_copy_from_linear_data_offset(skb, offset, | 2991 | skb_copy_from_linear_data_offset(head_skb, offset, |
| 2978 | skb_put(nskb, hsize), hsize); | 2992 | skb_put(nskb, hsize), hsize); |
| 2979 | 2993 | ||
| 2980 | skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; | 2994 | skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags & |
| 2995 | SKBTX_SHARED_FRAG; | ||
| 2981 | 2996 | ||
| 2982 | while (pos < offset + len) { | 2997 | while (pos < offset + len) { |
| 2983 | if (i >= nfrags) { | 2998 | if (i >= nfrags) { |
| 2984 | BUG_ON(skb_headlen(fskb)); | 2999 | BUG_ON(skb_headlen(list_skb)); |
| 2985 | 3000 | ||
| 2986 | i = 0; | 3001 | i = 0; |
| 2987 | nfrags = skb_shinfo(fskb)->nr_frags; | 3002 | nfrags = skb_shinfo(list_skb)->nr_frags; |
| 2988 | skb_frag = skb_shinfo(fskb)->frags; | 3003 | frag = skb_shinfo(list_skb)->frags; |
| 3004 | frag_skb = list_skb; | ||
| 2989 | 3005 | ||
| 2990 | BUG_ON(!nfrags); | 3006 | BUG_ON(!nfrags); |
| 2991 | 3007 | ||
| 2992 | fskb = fskb->next; | 3008 | list_skb = list_skb->next; |
| 2993 | } | 3009 | } |
| 2994 | 3010 | ||
| 2995 | if (unlikely(skb_shinfo(nskb)->nr_frags >= | 3011 | if (unlikely(skb_shinfo(nskb)->nr_frags >= |
| @@ -3000,27 +3016,30 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 3000 | goto err; | 3016 | goto err; |
| 3001 | } | 3017 | } |
| 3002 | 3018 | ||
| 3003 | *frag = *skb_frag; | 3019 | if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC))) |
| 3004 | __skb_frag_ref(frag); | 3020 | goto err; |
| 3005 | size = skb_frag_size(frag); | 3021 | |
| 3022 | *nskb_frag = *frag; | ||
| 3023 | __skb_frag_ref(nskb_frag); | ||
| 3024 | size = skb_frag_size(nskb_frag); | ||
| 3006 | 3025 | ||
| 3007 | if (pos < offset) { | 3026 | if (pos < offset) { |
| 3008 | frag->page_offset += offset - pos; | 3027 | nskb_frag->page_offset += offset - pos; |
| 3009 | skb_frag_size_sub(frag, offset - pos); | 3028 | skb_frag_size_sub(nskb_frag, offset - pos); |
| 3010 | } | 3029 | } |
| 3011 | 3030 | ||
| 3012 | skb_shinfo(nskb)->nr_frags++; | 3031 | skb_shinfo(nskb)->nr_frags++; |
| 3013 | 3032 | ||
| 3014 | if (pos + size <= offset + len) { | 3033 | if (pos + size <= offset + len) { |
| 3015 | i++; | 3034 | i++; |
| 3016 | skb_frag++; | 3035 | frag++; |
| 3017 | pos += size; | 3036 | pos += size; |
| 3018 | } else { | 3037 | } else { |
| 3019 | skb_frag_size_sub(frag, pos + size - (offset + len)); | 3038 | skb_frag_size_sub(nskb_frag, pos + size - (offset + len)); |
| 3020 | goto skip_fraglist; | 3039 | goto skip_fraglist; |
| 3021 | } | 3040 | } |
| 3022 | 3041 | ||
| 3023 | frag++; | 3042 | nskb_frag++; |
| 3024 | } | 3043 | } |
| 3025 | 3044 | ||
| 3026 | skip_fraglist: | 3045 | skip_fraglist: |
| @@ -3034,7 +3053,7 @@ perform_csum_check: | |||
| 3034 | nskb->len - doffset, 0); | 3053 | nskb->len - doffset, 0); |
| 3035 | nskb->ip_summed = CHECKSUM_NONE; | 3054 | nskb->ip_summed = CHECKSUM_NONE; |
| 3036 | } | 3055 | } |
| 3037 | } while ((offset += len) < skb->len); | 3056 | } while ((offset += len) < head_skb->len); |
| 3038 | 3057 | ||
| 3039 | return segs; | 3058 | return segs; |
| 3040 | 3059 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 5b6a9431b017..c0fc6bdad1e3 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -2357,10 +2357,13 @@ void release_sock(struct sock *sk) | |||
| 2357 | if (sk->sk_backlog.tail) | 2357 | if (sk->sk_backlog.tail) |
| 2358 | __release_sock(sk); | 2358 | __release_sock(sk); |
| 2359 | 2359 | ||
| 2360 | /* Warning : release_cb() might need to release sk ownership, | ||
| 2361 | * ie call sock_release_ownership(sk) before us. | ||
| 2362 | */ | ||
| 2360 | if (sk->sk_prot->release_cb) | 2363 | if (sk->sk_prot->release_cb) |
| 2361 | sk->sk_prot->release_cb(sk); | 2364 | sk->sk_prot->release_cb(sk); |
| 2362 | 2365 | ||
| 2363 | sk->sk_lock.owned = 0; | 2366 | sock_release_ownership(sk); |
| 2364 | if (waitqueue_active(&sk->sk_lock.wq)) | 2367 | if (waitqueue_active(&sk->sk_lock.wq)) |
| 2365 | wake_up(&sk->sk_lock.wq); | 2368 | wake_up(&sk->sk_lock.wq); |
| 2366 | spin_unlock_bh(&sk->sk_lock.slock); | 2369 | spin_unlock_bh(&sk->sk_lock.slock); |
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 327060c6c874..7ae0d7f6dbd0 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c | |||
| @@ -297,7 +297,7 @@ static bool seq_nr_after(u16 a, u16 b) | |||
| 297 | 297 | ||
| 298 | void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) | 298 | void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) |
| 299 | { | 299 | { |
| 300 | if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) { | 300 | if ((dev_idx < 0) || (dev_idx >= HSR_MAX_SLAVE)) { |
| 301 | WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); | 301 | WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); |
| 302 | return; | 302 | return; |
| 303 | } | 303 | } |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index ecd2c3f245ce..19ab78aca547 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -1296,8 +1296,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, | |||
| 1296 | 1296 | ||
| 1297 | segs = ERR_PTR(-EPROTONOSUPPORT); | 1297 | segs = ERR_PTR(-EPROTONOSUPPORT); |
| 1298 | 1298 | ||
| 1299 | /* Note : following gso_segment() might change skb->encapsulation */ | 1299 | if (skb->encapsulation && |
| 1300 | udpfrag = !skb->encapsulation && proto == IPPROTO_UDP; | 1300 | skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) |
| 1301 | udpfrag = proto == IPPROTO_UDP && encap; | ||
| 1302 | else | ||
| 1303 | udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; | ||
| 1301 | 1304 | ||
| 1302 | ops = rcu_dereference(inet_offloads[proto]); | 1305 | ops = rcu_dereference(inet_offloads[proto]); |
| 1303 | if (likely(ops && ops->callbacks.gso_segment)) | 1306 | if (likely(ops && ops->callbacks.gso_segment)) |
diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index 1863422fb7d5..250be7421ab3 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c | |||
| @@ -182,6 +182,14 @@ static int gre_cisco_rcv(struct sk_buff *skb) | |||
| 182 | int i; | 182 | int i; |
| 183 | bool csum_err = false; | 183 | bool csum_err = false; |
| 184 | 184 | ||
| 185 | #ifdef CONFIG_NET_IPGRE_BROADCAST | ||
| 186 | if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { | ||
| 187 | /* Looped back packet, drop it! */ | ||
| 188 | if (rt_is_output_route(skb_rtable(skb))) | ||
| 189 | goto drop; | ||
| 190 | } | ||
| 191 | #endif | ||
| 192 | |||
| 185 | if (parse_gre_header(skb, &tpi, &csum_err) < 0) | 193 | if (parse_gre_header(skb, &tpi, &csum_err) < 0) |
| 186 | goto drop; | 194 | goto drop; |
| 187 | 195 | ||
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index bb075fc9a14f..3b01959bf4bb 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
| @@ -208,7 +208,7 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force) | |||
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | work = frag_mem_limit(nf) - nf->low_thresh; | 210 | work = frag_mem_limit(nf) - nf->low_thresh; |
| 211 | while (work > 0) { | 211 | while (work > 0 || force) { |
| 212 | spin_lock(&nf->lru_lock); | 212 | spin_lock(&nf->lru_lock); |
| 213 | 213 | ||
| 214 | if (list_empty(&nf->lru_list)) { | 214 | if (list_empty(&nf->lru_list)) { |
| @@ -278,9 +278,10 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, | |||
| 278 | 278 | ||
| 279 | atomic_inc(&qp->refcnt); | 279 | atomic_inc(&qp->refcnt); |
| 280 | hlist_add_head(&qp->list, &hb->chain); | 280 | hlist_add_head(&qp->list, &hb->chain); |
| 281 | inet_frag_lru_add(nf, qp); | ||
| 281 | spin_unlock(&hb->chain_lock); | 282 | spin_unlock(&hb->chain_lock); |
| 282 | read_unlock(&f->lock); | 283 | read_unlock(&f->lock); |
| 283 | inet_frag_lru_add(nf, qp); | 284 | |
| 284 | return qp; | 285 | return qp; |
| 285 | } | 286 | } |
| 286 | 287 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8971780aec7c..73c6b63bba74 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -422,9 +422,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
| 422 | to->tc_index = from->tc_index; | 422 | to->tc_index = from->tc_index; |
| 423 | #endif | 423 | #endif |
| 424 | nf_copy(to, from); | 424 | nf_copy(to, from); |
| 425 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
| 426 | to->nf_trace = from->nf_trace; | ||
| 427 | #endif | ||
| 428 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 425 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
| 429 | to->ipvs_property = from->ipvs_property; | 426 | to->ipvs_property = from->ipvs_property; |
| 430 | #endif | 427 | #endif |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 50228be5c17b..a82a22d8f77f 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
| @@ -93,13 +93,14 @@ static void tunnel_dst_reset(struct ip_tunnel *t) | |||
| 93 | tunnel_dst_set(t, NULL); | 93 | tunnel_dst_set(t, NULL); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static void tunnel_dst_reset_all(struct ip_tunnel *t) | 96 | void ip_tunnel_dst_reset_all(struct ip_tunnel *t) |
| 97 | { | 97 | { |
| 98 | int i; | 98 | int i; |
| 99 | 99 | ||
| 100 | for_each_possible_cpu(i) | 100 | for_each_possible_cpu(i) |
| 101 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); | 101 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); |
| 102 | } | 102 | } |
| 103 | EXPORT_SYMBOL(ip_tunnel_dst_reset_all); | ||
| 103 | 104 | ||
| 104 | static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) | 105 | static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) |
| 105 | { | 106 | { |
| @@ -119,52 +120,6 @@ static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) | |||
| 119 | return (struct rtable *)dst; | 120 | return (struct rtable *)dst; |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | /* Often modified stats are per cpu, other are shared (netdev->stats) */ | ||
| 123 | struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, | ||
| 124 | struct rtnl_link_stats64 *tot) | ||
| 125 | { | ||
| 126 | int i; | ||
| 127 | |||
| 128 | for_each_possible_cpu(i) { | ||
| 129 | const struct pcpu_sw_netstats *tstats = | ||
| 130 | per_cpu_ptr(dev->tstats, i); | ||
| 131 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
| 132 | unsigned int start; | ||
| 133 | |||
| 134 | do { | ||
| 135 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | ||
| 136 | rx_packets = tstats->rx_packets; | ||
| 137 | tx_packets = tstats->tx_packets; | ||
| 138 | rx_bytes = tstats->rx_bytes; | ||
| 139 | tx_bytes = tstats->tx_bytes; | ||
| 140 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
| 141 | |||
| 142 | tot->rx_packets += rx_packets; | ||
| 143 | tot->tx_packets += tx_packets; | ||
| 144 | tot->rx_bytes += rx_bytes; | ||
| 145 | tot->tx_bytes += tx_bytes; | ||
| 146 | } | ||
| 147 | |||
| 148 | tot->multicast = dev->stats.multicast; | ||
| 149 | |||
| 150 | tot->rx_crc_errors = dev->stats.rx_crc_errors; | ||
| 151 | tot->rx_fifo_errors = dev->stats.rx_fifo_errors; | ||
| 152 | tot->rx_length_errors = dev->stats.rx_length_errors; | ||
| 153 | tot->rx_frame_errors = dev->stats.rx_frame_errors; | ||
| 154 | tot->rx_errors = dev->stats.rx_errors; | ||
| 155 | |||
| 156 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
| 157 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
| 158 | tot->tx_dropped = dev->stats.tx_dropped; | ||
| 159 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
| 160 | tot->tx_errors = dev->stats.tx_errors; | ||
| 161 | |||
| 162 | tot->collisions = dev->stats.collisions; | ||
| 163 | |||
| 164 | return tot; | ||
| 165 | } | ||
| 166 | EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64); | ||
| 167 | |||
| 168 | static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, | 123 | static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, |
| 169 | __be16 flags, __be32 key) | 124 | __be16 flags, __be32 key) |
| 170 | { | 125 | { |
| @@ -461,9 +416,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, | |||
| 461 | 416 | ||
| 462 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 417 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
| 463 | if (ipv4_is_multicast(iph->daddr)) { | 418 | if (ipv4_is_multicast(iph->daddr)) { |
| 464 | /* Looped back packet, drop it! */ | ||
| 465 | if (rt_is_output_route(skb_rtable(skb))) | ||
| 466 | goto drop; | ||
| 467 | tunnel->dev->stats.multicast++; | 419 | tunnel->dev->stats.multicast++; |
| 468 | skb->pkt_type = PACKET_BROADCAST; | 420 | skb->pkt_type = PACKET_BROADCAST; |
| 469 | } | 421 | } |
| @@ -759,7 +711,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, | |||
| 759 | if (set_mtu) | 711 | if (set_mtu) |
| 760 | dev->mtu = mtu; | 712 | dev->mtu = mtu; |
| 761 | } | 713 | } |
| 762 | tunnel_dst_reset_all(t); | 714 | ip_tunnel_dst_reset_all(t); |
| 763 | netdev_state_change(dev); | 715 | netdev_state_change(dev); |
| 764 | } | 716 | } |
| 765 | 717 | ||
| @@ -1088,7 +1040,7 @@ void ip_tunnel_uninit(struct net_device *dev) | |||
| 1088 | if (itn->fb_tunnel_dev != dev) | 1040 | if (itn->fb_tunnel_dev != dev) |
| 1089 | ip_tunnel_del(netdev_priv(dev)); | 1041 | ip_tunnel_del(netdev_priv(dev)); |
| 1090 | 1042 | ||
| 1091 | tunnel_dst_reset_all(tunnel); | 1043 | ip_tunnel_dst_reset_all(tunnel); |
| 1092 | } | 1044 | } |
| 1093 | EXPORT_SYMBOL_GPL(ip_tunnel_uninit); | 1045 | EXPORT_SYMBOL_GPL(ip_tunnel_uninit); |
| 1094 | 1046 | ||
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 6156f4ef5e91..8d69626f2206 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c | |||
| @@ -148,3 +148,49 @@ error: | |||
| 148 | return ERR_PTR(err); | 148 | return ERR_PTR(err); |
| 149 | } | 149 | } |
| 150 | EXPORT_SYMBOL_GPL(iptunnel_handle_offloads); | 150 | EXPORT_SYMBOL_GPL(iptunnel_handle_offloads); |
| 151 | |||
| 152 | /* Often modified stats are per cpu, other are shared (netdev->stats) */ | ||
| 153 | struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, | ||
| 154 | struct rtnl_link_stats64 *tot) | ||
| 155 | { | ||
| 156 | int i; | ||
| 157 | |||
| 158 | for_each_possible_cpu(i) { | ||
| 159 | const struct pcpu_sw_netstats *tstats = | ||
| 160 | per_cpu_ptr(dev->tstats, i); | ||
| 161 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
| 162 | unsigned int start; | ||
| 163 | |||
| 164 | do { | ||
| 165 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | ||
| 166 | rx_packets = tstats->rx_packets; | ||
| 167 | tx_packets = tstats->tx_packets; | ||
| 168 | rx_bytes = tstats->rx_bytes; | ||
| 169 | tx_bytes = tstats->tx_bytes; | ||
| 170 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
| 171 | |||
| 172 | tot->rx_packets += rx_packets; | ||
| 173 | tot->tx_packets += tx_packets; | ||
| 174 | tot->rx_bytes += rx_bytes; | ||
| 175 | tot->tx_bytes += tx_bytes; | ||
| 176 | } | ||
| 177 | |||
| 178 | tot->multicast = dev->stats.multicast; | ||
| 179 | |||
| 180 | tot->rx_crc_errors = dev->stats.rx_crc_errors; | ||
| 181 | tot->rx_fifo_errors = dev->stats.rx_fifo_errors; | ||
| 182 | tot->rx_length_errors = dev->stats.rx_length_errors; | ||
| 183 | tot->rx_frame_errors = dev->stats.rx_frame_errors; | ||
| 184 | tot->rx_errors = dev->stats.rx_errors; | ||
| 185 | |||
| 186 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
| 187 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
| 188 | tot->tx_dropped = dev->stats.tx_dropped; | ||
| 189 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
| 190 | tot->tx_errors = dev->stats.tx_errors; | ||
| 191 | |||
| 192 | tot->collisions = dev->stats.collisions; | ||
| 193 | |||
| 194 | return tot; | ||
| 195 | } | ||
| 196 | EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64); | ||
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index b9b3472975ba..28863570dd60 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
| @@ -2255,13 +2255,14 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, | |||
| 2255 | } | 2255 | } |
| 2256 | 2256 | ||
| 2257 | static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, | 2257 | static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, |
| 2258 | u32 portid, u32 seq, struct mfc_cache *c, int cmd) | 2258 | u32 portid, u32 seq, struct mfc_cache *c, int cmd, |
| 2259 | int flags) | ||
| 2259 | { | 2260 | { |
| 2260 | struct nlmsghdr *nlh; | 2261 | struct nlmsghdr *nlh; |
| 2261 | struct rtmsg *rtm; | 2262 | struct rtmsg *rtm; |
| 2262 | int err; | 2263 | int err; |
| 2263 | 2264 | ||
| 2264 | nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI); | 2265 | nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags); |
| 2265 | if (nlh == NULL) | 2266 | if (nlh == NULL) |
| 2266 | return -EMSGSIZE; | 2267 | return -EMSGSIZE; |
| 2267 | 2268 | ||
| @@ -2329,7 +2330,7 @@ static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc, | |||
| 2329 | if (skb == NULL) | 2330 | if (skb == NULL) |
| 2330 | goto errout; | 2331 | goto errout; |
| 2331 | 2332 | ||
| 2332 | err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd); | 2333 | err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0); |
| 2333 | if (err < 0) | 2334 | if (err < 0) |
| 2334 | goto errout; | 2335 | goto errout; |
| 2335 | 2336 | ||
| @@ -2368,7 +2369,8 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2368 | if (ipmr_fill_mroute(mrt, skb, | 2369 | if (ipmr_fill_mroute(mrt, skb, |
| 2369 | NETLINK_CB(cb->skb).portid, | 2370 | NETLINK_CB(cb->skb).portid, |
| 2370 | cb->nlh->nlmsg_seq, | 2371 | cb->nlh->nlmsg_seq, |
| 2371 | mfc, RTM_NEWROUTE) < 0) | 2372 | mfc, RTM_NEWROUTE, |
| 2373 | NLM_F_MULTI) < 0) | ||
| 2372 | goto done; | 2374 | goto done; |
| 2373 | next_entry: | 2375 | next_entry: |
| 2374 | e++; | 2376 | e++; |
| @@ -2382,7 +2384,8 @@ next_entry: | |||
| 2382 | if (ipmr_fill_mroute(mrt, skb, | 2384 | if (ipmr_fill_mroute(mrt, skb, |
| 2383 | NETLINK_CB(cb->skb).portid, | 2385 | NETLINK_CB(cb->skb).portid, |
| 2384 | cb->nlh->nlmsg_seq, | 2386 | cb->nlh->nlmsg_seq, |
| 2385 | mfc, RTM_NEWROUTE) < 0) { | 2387 | mfc, RTM_NEWROUTE, |
| 2388 | NLM_F_MULTI) < 0) { | ||
| 2386 | spin_unlock_bh(&mfc_unres_lock); | 2389 | spin_unlock_bh(&mfc_unres_lock); |
| 2387 | goto done; | 2390 | goto done; |
| 2388 | } | 2391 | } |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index d551e31b416e..7c676671329d 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
| @@ -1198,8 +1198,8 @@ static int snmp_translate(struct nf_conn *ct, | |||
| 1198 | map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); | 1198 | map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); |
| 1199 | } else { | 1199 | } else { |
| 1200 | /* DNAT replies */ | 1200 | /* DNAT replies */ |
| 1201 | map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip); | 1201 | map.from = NOCT1(&ct->tuplehash[!dir].tuple.src.u3.ip); |
| 1202 | map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); | 1202 | map.to = NOCT1(&ct->tuplehash[dir].tuple.dst.u3.ip); |
| 1203 | } | 1203 | } |
| 1204 | 1204 | ||
| 1205 | if (map.from == map.to) | 1205 | if (map.from == map.to) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9f3a2db9109e..97c8f5620c43 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -1044,7 +1044,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp) | |||
| 1044 | } | 1044 | } |
| 1045 | } | 1045 | } |
| 1046 | 1046 | ||
| 1047 | static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size) | 1047 | static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, |
| 1048 | int *copied, size_t size) | ||
| 1048 | { | 1049 | { |
| 1049 | struct tcp_sock *tp = tcp_sk(sk); | 1050 | struct tcp_sock *tp = tcp_sk(sk); |
| 1050 | int err, flags; | 1051 | int err, flags; |
| @@ -1059,11 +1060,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size) | |||
| 1059 | if (unlikely(tp->fastopen_req == NULL)) | 1060 | if (unlikely(tp->fastopen_req == NULL)) |
| 1060 | return -ENOBUFS; | 1061 | return -ENOBUFS; |
| 1061 | tp->fastopen_req->data = msg; | 1062 | tp->fastopen_req->data = msg; |
| 1063 | tp->fastopen_req->size = size; | ||
| 1062 | 1064 | ||
| 1063 | flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; | 1065 | flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; |
| 1064 | err = __inet_stream_connect(sk->sk_socket, msg->msg_name, | 1066 | err = __inet_stream_connect(sk->sk_socket, msg->msg_name, |
| 1065 | msg->msg_namelen, flags); | 1067 | msg->msg_namelen, flags); |
| 1066 | *size = tp->fastopen_req->copied; | 1068 | *copied = tp->fastopen_req->copied; |
| 1067 | tcp_free_fastopen_req(tp); | 1069 | tcp_free_fastopen_req(tp); |
| 1068 | return err; | 1070 | return err; |
| 1069 | } | 1071 | } |
| @@ -1083,7 +1085,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 1083 | 1085 | ||
| 1084 | flags = msg->msg_flags; | 1086 | flags = msg->msg_flags; |
| 1085 | if (flags & MSG_FASTOPEN) { | 1087 | if (flags & MSG_FASTOPEN) { |
| 1086 | err = tcp_sendmsg_fastopen(sk, msg, &copied_syn); | 1088 | err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size); |
| 1087 | if (err == -EINPROGRESS && copied_syn > 0) | 1089 | if (err == -EINPROGRESS && copied_syn > 0) |
| 1088 | goto out; | 1090 | goto out; |
| 1089 | else if (err) | 1091 | else if (err) |
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index ad37bf18ae4b..2388275adb9b 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -290,8 +290,7 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) | |||
| 290 | left = tp->snd_cwnd - in_flight; | 290 | left = tp->snd_cwnd - in_flight; |
| 291 | if (sk_can_gso(sk) && | 291 | if (sk_can_gso(sk) && |
| 292 | left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && | 292 | left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && |
| 293 | left * tp->mss_cache < sk->sk_gso_max_size && | 293 | left < tp->xmit_size_goal_segs) |
| 294 | left < sk->sk_gso_max_segs) | ||
| 295 | return true; | 294 | return true; |
| 296 | return left <= tcp_max_tso_deferred_mss(tp); | 295 | return left <= tcp_max_tso_deferred_mss(tp); |
| 297 | } | 296 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 227cba79fa6b..eeaac399420d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -1945,8 +1945,9 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
| 1945 | if (skb == tcp_send_head(sk)) | 1945 | if (skb == tcp_send_head(sk)) |
| 1946 | break; | 1946 | break; |
| 1947 | 1947 | ||
| 1948 | if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS) | 1948 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) |
| 1949 | tp->undo_marker = 0; | 1949 | tp->undo_marker = 0; |
| 1950 | |||
| 1950 | TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; | 1951 | TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; |
| 1951 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) { | 1952 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) { |
| 1952 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; | 1953 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3cf976510497..1e4eac779f51 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -2628,7 +2628,7 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw, | |||
| 2628 | { | 2628 | { |
| 2629 | __be32 dest, src; | 2629 | __be32 dest, src; |
| 2630 | __u16 destp, srcp; | 2630 | __u16 destp, srcp; |
| 2631 | long delta = tw->tw_ttd - jiffies; | 2631 | s32 delta = tw->tw_ttd - inet_tw_time_stamp(); |
| 2632 | 2632 | ||
| 2633 | dest = tw->tw_daddr; | 2633 | dest = tw->tw_daddr; |
| 2634 | src = tw->tw_rcv_saddr; | 2634 | src = tw->tw_rcv_saddr; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3be16727f058..17a11e65e57f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -767,6 +767,17 @@ void tcp_release_cb(struct sock *sk) | |||
| 767 | if (flags & (1UL << TCP_TSQ_DEFERRED)) | 767 | if (flags & (1UL << TCP_TSQ_DEFERRED)) |
| 768 | tcp_tsq_handler(sk); | 768 | tcp_tsq_handler(sk); |
| 769 | 769 | ||
| 770 | /* Here begins the tricky part : | ||
| 771 | * We are called from release_sock() with : | ||
| 772 | * 1) BH disabled | ||
| 773 | * 2) sk_lock.slock spinlock held | ||
| 774 | * 3) socket owned by us (sk->sk_lock.owned == 1) | ||
| 775 | * | ||
| 776 | * But following code is meant to be called from BH handlers, | ||
| 777 | * so we should keep BH disabled, but early release socket ownership | ||
| 778 | */ | ||
| 779 | sock_release_ownership(sk); | ||
| 780 | |||
| 770 | if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { | 781 | if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { |
| 771 | tcp_write_timer_handler(sk); | 782 | tcp_write_timer_handler(sk); |
| 772 | __sock_put(sk); | 783 | __sock_put(sk); |
| @@ -864,8 +875,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 864 | 875 | ||
| 865 | if (unlikely(skb->fclone == SKB_FCLONE_ORIG && | 876 | if (unlikely(skb->fclone == SKB_FCLONE_ORIG && |
| 866 | fclone->fclone == SKB_FCLONE_CLONE)) | 877 | fclone->fclone == SKB_FCLONE_CLONE)) |
| 867 | NET_INC_STATS_BH(sock_net(sk), | 878 | NET_INC_STATS(sock_net(sk), |
| 868 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); | 879 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); |
| 869 | 880 | ||
| 870 | if (unlikely(skb_cloned(skb))) | 881 | if (unlikely(skb_cloned(skb))) |
| 871 | skb = pskb_copy(skb, gfp_mask); | 882 | skb = pskb_copy(skb, gfp_mask); |
| @@ -2337,6 +2348,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 2337 | struct tcp_sock *tp = tcp_sk(sk); | 2348 | struct tcp_sock *tp = tcp_sk(sk); |
| 2338 | struct inet_connection_sock *icsk = inet_csk(sk); | 2349 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 2339 | unsigned int cur_mss; | 2350 | unsigned int cur_mss; |
| 2351 | int err; | ||
| 2340 | 2352 | ||
| 2341 | /* Inconslusive MTU probe */ | 2353 | /* Inconslusive MTU probe */ |
| 2342 | if (icsk->icsk_mtup.probe_size) { | 2354 | if (icsk->icsk_mtup.probe_size) { |
| @@ -2400,11 +2412,15 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 2400 | skb_headroom(skb) >= 0xFFFF)) { | 2412 | skb_headroom(skb) >= 0xFFFF)) { |
| 2401 | struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, | 2413 | struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, |
| 2402 | GFP_ATOMIC); | 2414 | GFP_ATOMIC); |
| 2403 | return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : | 2415 | err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : |
| 2404 | -ENOBUFS; | 2416 | -ENOBUFS; |
| 2405 | } else { | 2417 | } else { |
| 2406 | return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); | 2418 | err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); |
| 2407 | } | 2419 | } |
| 2420 | |||
| 2421 | if (likely(!err)) | ||
| 2422 | TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS; | ||
| 2423 | return err; | ||
| 2408 | } | 2424 | } |
| 2409 | 2425 | ||
| 2410 | int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | 2426 | int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) |
| @@ -2908,7 +2924,12 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) | |||
| 2908 | space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) - | 2924 | space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) - |
| 2909 | MAX_TCP_OPTION_SPACE; | 2925 | MAX_TCP_OPTION_SPACE; |
| 2910 | 2926 | ||
| 2911 | syn_data = skb_copy_expand(syn, skb_headroom(syn), space, | 2927 | space = min_t(size_t, space, fo->size); |
| 2928 | |||
| 2929 | /* limit to order-0 allocations */ | ||
| 2930 | space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); | ||
| 2931 | |||
| 2932 | syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space, | ||
| 2912 | sk->sk_allocation); | 2933 | sk->sk_allocation); |
| 2913 | if (syn_data == NULL) | 2934 | if (syn_data == NULL) |
| 2914 | goto fallback; | 2935 | goto fallback; |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index d92e5586783e..438a73aa777c 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
| @@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION | |||
| 138 | config IPV6_VTI | 138 | config IPV6_VTI |
| 139 | tristate "Virtual (secure) IPv6: tunneling" | 139 | tristate "Virtual (secure) IPv6: tunneling" |
| 140 | select IPV6_TUNNEL | 140 | select IPV6_TUNNEL |
| 141 | select NET_IP_TUNNEL | ||
| 141 | depends on INET6_XFRM_MODE_TUNNEL | 142 | depends on INET6_XFRM_MODE_TUNNEL |
| 142 | ---help--- | 143 | ---help--- |
| 143 | Tunneling means encapsulating data of one protocol type within | 144 | Tunneling means encapsulating data of one protocol type within |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fdbfeca36d63..6c7fa0853fc7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -133,10 +133,12 @@ static int ipv6_count_addresses(struct inet6_dev *idev); | |||
| 133 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; | 133 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; |
| 134 | static DEFINE_SPINLOCK(addrconf_hash_lock); | 134 | static DEFINE_SPINLOCK(addrconf_hash_lock); |
| 135 | 135 | ||
| 136 | static void addrconf_verify(unsigned long); | 136 | static void addrconf_verify(void); |
| 137 | static void addrconf_verify_rtnl(void); | ||
| 138 | static void addrconf_verify_work(struct work_struct *); | ||
| 137 | 139 | ||
| 138 | static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); | 140 | static struct workqueue_struct *addrconf_wq; |
| 139 | static DEFINE_SPINLOCK(addrconf_verify_lock); | 141 | static DECLARE_DELAYED_WORK(addr_chk_work, addrconf_verify_work); |
| 140 | 142 | ||
| 141 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | 143 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); |
| 142 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | 144 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); |
| @@ -151,7 +153,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, | |||
| 151 | u32 flags, u32 noflags); | 153 | u32 flags, u32 noflags); |
| 152 | 154 | ||
| 153 | static void addrconf_dad_start(struct inet6_ifaddr *ifp); | 155 | static void addrconf_dad_start(struct inet6_ifaddr *ifp); |
| 154 | static void addrconf_dad_timer(unsigned long data); | 156 | static void addrconf_dad_work(struct work_struct *w); |
| 155 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); | 157 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); |
| 156 | static void addrconf_dad_run(struct inet6_dev *idev); | 158 | static void addrconf_dad_run(struct inet6_dev *idev); |
| 157 | static void addrconf_rs_timer(unsigned long data); | 159 | static void addrconf_rs_timer(unsigned long data); |
| @@ -247,9 +249,9 @@ static void addrconf_del_rs_timer(struct inet6_dev *idev) | |||
| 247 | __in6_dev_put(idev); | 249 | __in6_dev_put(idev); |
| 248 | } | 250 | } |
| 249 | 251 | ||
| 250 | static void addrconf_del_dad_timer(struct inet6_ifaddr *ifp) | 252 | static void addrconf_del_dad_work(struct inet6_ifaddr *ifp) |
| 251 | { | 253 | { |
| 252 | if (del_timer(&ifp->dad_timer)) | 254 | if (cancel_delayed_work(&ifp->dad_work)) |
| 253 | __in6_ifa_put(ifp); | 255 | __in6_ifa_put(ifp); |
| 254 | } | 256 | } |
| 255 | 257 | ||
| @@ -261,12 +263,12 @@ static void addrconf_mod_rs_timer(struct inet6_dev *idev, | |||
| 261 | mod_timer(&idev->rs_timer, jiffies + when); | 263 | mod_timer(&idev->rs_timer, jiffies + when); |
| 262 | } | 264 | } |
| 263 | 265 | ||
| 264 | static void addrconf_mod_dad_timer(struct inet6_ifaddr *ifp, | 266 | static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, |
| 265 | unsigned long when) | 267 | unsigned long delay) |
| 266 | { | 268 | { |
| 267 | if (!timer_pending(&ifp->dad_timer)) | 269 | if (!delayed_work_pending(&ifp->dad_work)) |
| 268 | in6_ifa_hold(ifp); | 270 | in6_ifa_hold(ifp); |
| 269 | mod_timer(&ifp->dad_timer, jiffies + when); | 271 | mod_delayed_work(addrconf_wq, &ifp->dad_work, delay); |
| 270 | } | 272 | } |
| 271 | 273 | ||
| 272 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 274 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
| @@ -751,8 +753,9 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
| 751 | 753 | ||
| 752 | in6_dev_put(ifp->idev); | 754 | in6_dev_put(ifp->idev); |
| 753 | 755 | ||
| 754 | if (del_timer(&ifp->dad_timer)) | 756 | if (cancel_delayed_work(&ifp->dad_work)) |
| 755 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); | 757 | pr_notice("delayed DAD work was pending while freeing ifa=%p\n", |
| 758 | ifp); | ||
| 756 | 759 | ||
| 757 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { | 760 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { |
| 758 | pr_warn("Freeing alive inet6 address %p\n", ifp); | 761 | pr_warn("Freeing alive inet6 address %p\n", ifp); |
| @@ -849,8 +852,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
| 849 | 852 | ||
| 850 | spin_lock_init(&ifa->lock); | 853 | spin_lock_init(&ifa->lock); |
| 851 | spin_lock_init(&ifa->state_lock); | 854 | spin_lock_init(&ifa->state_lock); |
| 852 | setup_timer(&ifa->dad_timer, addrconf_dad_timer, | 855 | INIT_DELAYED_WORK(&ifa->dad_work, addrconf_dad_work); |
| 853 | (unsigned long)ifa); | ||
| 854 | INIT_HLIST_NODE(&ifa->addr_lst); | 856 | INIT_HLIST_NODE(&ifa->addr_lst); |
| 855 | ifa->scope = scope; | 857 | ifa->scope = scope; |
| 856 | ifa->prefix_len = pfxlen; | 858 | ifa->prefix_len = pfxlen; |
| @@ -990,6 +992,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 990 | enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP; | 992 | enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP; |
| 991 | unsigned long expires; | 993 | unsigned long expires; |
| 992 | 994 | ||
| 995 | ASSERT_RTNL(); | ||
| 996 | |||
| 993 | spin_lock_bh(&ifp->state_lock); | 997 | spin_lock_bh(&ifp->state_lock); |
| 994 | state = ifp->state; | 998 | state = ifp->state; |
| 995 | ifp->state = INET6_IFADDR_STATE_DEAD; | 999 | ifp->state = INET6_IFADDR_STATE_DEAD; |
| @@ -1021,7 +1025,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 1021 | 1025 | ||
| 1022 | write_unlock_bh(&ifp->idev->lock); | 1026 | write_unlock_bh(&ifp->idev->lock); |
| 1023 | 1027 | ||
| 1024 | addrconf_del_dad_timer(ifp); | 1028 | addrconf_del_dad_work(ifp); |
| 1025 | 1029 | ||
| 1026 | ipv6_ifa_notify(RTM_DELADDR, ifp); | 1030 | ipv6_ifa_notify(RTM_DELADDR, ifp); |
| 1027 | 1031 | ||
| @@ -1103,8 +1107,11 @@ retry: | |||
| 1103 | * Lifetime is greater than REGEN_ADVANCE time units. In particular, | 1107 | * Lifetime is greater than REGEN_ADVANCE time units. In particular, |
| 1104 | * an implementation must not create a temporary address with a zero | 1108 | * an implementation must not create a temporary address with a zero |
| 1105 | * Preferred Lifetime. | 1109 | * Preferred Lifetime. |
| 1110 | * Use age calculation as in addrconf_verify to avoid unnecessary | ||
| 1111 | * temporary addresses being generated. | ||
| 1106 | */ | 1112 | */ |
| 1107 | if (tmp_prefered_lft <= regen_advance) { | 1113 | age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; |
| 1114 | if (tmp_prefered_lft <= regen_advance + age) { | ||
| 1108 | in6_ifa_put(ifp); | 1115 | in6_ifa_put(ifp); |
| 1109 | in6_dev_put(idev); | 1116 | in6_dev_put(idev); |
| 1110 | ret = -1; | 1117 | ret = -1; |
| @@ -1601,7 +1608,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
| 1601 | { | 1608 | { |
| 1602 | if (ifp->flags&IFA_F_PERMANENT) { | 1609 | if (ifp->flags&IFA_F_PERMANENT) { |
| 1603 | spin_lock_bh(&ifp->lock); | 1610 | spin_lock_bh(&ifp->lock); |
| 1604 | addrconf_del_dad_timer(ifp); | 1611 | addrconf_del_dad_work(ifp); |
| 1605 | ifp->flags |= IFA_F_TENTATIVE; | 1612 | ifp->flags |= IFA_F_TENTATIVE; |
| 1606 | if (dad_failed) | 1613 | if (dad_failed) |
| 1607 | ifp->flags |= IFA_F_DADFAILED; | 1614 | ifp->flags |= IFA_F_DADFAILED; |
| @@ -1622,20 +1629,21 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
| 1622 | spin_unlock_bh(&ifp->lock); | 1629 | spin_unlock_bh(&ifp->lock); |
| 1623 | } | 1630 | } |
| 1624 | ipv6_del_addr(ifp); | 1631 | ipv6_del_addr(ifp); |
| 1625 | } else | 1632 | } else { |
| 1626 | ipv6_del_addr(ifp); | 1633 | ipv6_del_addr(ifp); |
| 1634 | } | ||
| 1627 | } | 1635 | } |
| 1628 | 1636 | ||
| 1629 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) | 1637 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) |
| 1630 | { | 1638 | { |
| 1631 | int err = -ENOENT; | 1639 | int err = -ENOENT; |
| 1632 | 1640 | ||
| 1633 | spin_lock(&ifp->state_lock); | 1641 | spin_lock_bh(&ifp->state_lock); |
| 1634 | if (ifp->state == INET6_IFADDR_STATE_DAD) { | 1642 | if (ifp->state == INET6_IFADDR_STATE_DAD) { |
| 1635 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | 1643 | ifp->state = INET6_IFADDR_STATE_POSTDAD; |
| 1636 | err = 0; | 1644 | err = 0; |
| 1637 | } | 1645 | } |
| 1638 | spin_unlock(&ifp->state_lock); | 1646 | spin_unlock_bh(&ifp->state_lock); |
| 1639 | 1647 | ||
| 1640 | return err; | 1648 | return err; |
| 1641 | } | 1649 | } |
| @@ -1668,7 +1676,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
| 1668 | } | 1676 | } |
| 1669 | } | 1677 | } |
| 1670 | 1678 | ||
| 1671 | addrconf_dad_stop(ifp, 1); | 1679 | spin_lock_bh(&ifp->state_lock); |
| 1680 | /* transition from _POSTDAD to _ERRDAD */ | ||
| 1681 | ifp->state = INET6_IFADDR_STATE_ERRDAD; | ||
| 1682 | spin_unlock_bh(&ifp->state_lock); | ||
| 1683 | |||
| 1684 | addrconf_mod_dad_work(ifp, 0); | ||
| 1672 | } | 1685 | } |
| 1673 | 1686 | ||
| 1674 | /* Join to solicited addr multicast group. */ | 1687 | /* Join to solicited addr multicast group. */ |
| @@ -1677,6 +1690,8 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | |||
| 1677 | { | 1690 | { |
| 1678 | struct in6_addr maddr; | 1691 | struct in6_addr maddr; |
| 1679 | 1692 | ||
| 1693 | ASSERT_RTNL(); | ||
| 1694 | |||
| 1680 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1695 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
| 1681 | return; | 1696 | return; |
| 1682 | 1697 | ||
| @@ -1688,6 +1703,8 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
| 1688 | { | 1703 | { |
| 1689 | struct in6_addr maddr; | 1704 | struct in6_addr maddr; |
| 1690 | 1705 | ||
| 1706 | ASSERT_RTNL(); | ||
| 1707 | |||
| 1691 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1708 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
| 1692 | return; | 1709 | return; |
| 1693 | 1710 | ||
| @@ -1698,6 +1715,9 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
| 1698 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1715 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
| 1699 | { | 1716 | { |
| 1700 | struct in6_addr addr; | 1717 | struct in6_addr addr; |
| 1718 | |||
| 1719 | ASSERT_RTNL(); | ||
| 1720 | |||
| 1701 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1721 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
| 1702 | return; | 1722 | return; |
| 1703 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1723 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
| @@ -1709,6 +1729,9 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
| 1709 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1729 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
| 1710 | { | 1730 | { |
| 1711 | struct in6_addr addr; | 1731 | struct in6_addr addr; |
| 1732 | |||
| 1733 | ASSERT_RTNL(); | ||
| 1734 | |||
| 1712 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1735 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
| 1713 | return; | 1736 | return; |
| 1714 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1737 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
| @@ -2268,11 +2291,13 @@ ok: | |||
| 2268 | return; | 2291 | return; |
| 2269 | } | 2292 | } |
| 2270 | 2293 | ||
| 2271 | ifp->flags |= IFA_F_MANAGETEMPADDR; | ||
| 2272 | update_lft = 0; | 2294 | update_lft = 0; |
| 2273 | create = 1; | 2295 | create = 1; |
| 2296 | spin_lock_bh(&ifp->lock); | ||
| 2297 | ifp->flags |= IFA_F_MANAGETEMPADDR; | ||
| 2274 | ifp->cstamp = jiffies; | 2298 | ifp->cstamp = jiffies; |
| 2275 | ifp->tokenized = tokenized; | 2299 | ifp->tokenized = tokenized; |
| 2300 | spin_unlock_bh(&ifp->lock); | ||
| 2276 | addrconf_dad_start(ifp); | 2301 | addrconf_dad_start(ifp); |
| 2277 | } | 2302 | } |
| 2278 | 2303 | ||
| @@ -2323,7 +2348,7 @@ ok: | |||
| 2323 | create, now); | 2348 | create, now); |
| 2324 | 2349 | ||
| 2325 | in6_ifa_put(ifp); | 2350 | in6_ifa_put(ifp); |
| 2326 | addrconf_verify(0); | 2351 | addrconf_verify(); |
| 2327 | } | 2352 | } |
| 2328 | } | 2353 | } |
| 2329 | inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo); | 2354 | inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo); |
| @@ -2472,7 +2497,7 @@ static int inet6_addr_add(struct net *net, int ifindex, | |||
| 2472 | manage_tempaddrs(idev, ifp, valid_lft, prefered_lft, | 2497 | manage_tempaddrs(idev, ifp, valid_lft, prefered_lft, |
| 2473 | true, jiffies); | 2498 | true, jiffies); |
| 2474 | in6_ifa_put(ifp); | 2499 | in6_ifa_put(ifp); |
| 2475 | addrconf_verify(0); | 2500 | addrconf_verify_rtnl(); |
| 2476 | return 0; | 2501 | return 0; |
| 2477 | } | 2502 | } |
| 2478 | 2503 | ||
| @@ -3008,7 +3033,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 3008 | hlist_for_each_entry_rcu(ifa, h, addr_lst) { | 3033 | hlist_for_each_entry_rcu(ifa, h, addr_lst) { |
| 3009 | if (ifa->idev == idev) { | 3034 | if (ifa->idev == idev) { |
| 3010 | hlist_del_init_rcu(&ifa->addr_lst); | 3035 | hlist_del_init_rcu(&ifa->addr_lst); |
| 3011 | addrconf_del_dad_timer(ifa); | 3036 | addrconf_del_dad_work(ifa); |
| 3012 | goto restart; | 3037 | goto restart; |
| 3013 | } | 3038 | } |
| 3014 | } | 3039 | } |
| @@ -3046,7 +3071,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 3046 | while (!list_empty(&idev->addr_list)) { | 3071 | while (!list_empty(&idev->addr_list)) { |
| 3047 | ifa = list_first_entry(&idev->addr_list, | 3072 | ifa = list_first_entry(&idev->addr_list, |
| 3048 | struct inet6_ifaddr, if_list); | 3073 | struct inet6_ifaddr, if_list); |
| 3049 | addrconf_del_dad_timer(ifa); | 3074 | addrconf_del_dad_work(ifa); |
| 3050 | 3075 | ||
| 3051 | list_del(&ifa->if_list); | 3076 | list_del(&ifa->if_list); |
| 3052 | 3077 | ||
| @@ -3145,10 +3170,10 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp) | |||
| 3145 | rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1); | 3170 | rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1); |
| 3146 | 3171 | ||
| 3147 | ifp->dad_probes = idev->cnf.dad_transmits; | 3172 | ifp->dad_probes = idev->cnf.dad_transmits; |
| 3148 | addrconf_mod_dad_timer(ifp, rand_num); | 3173 | addrconf_mod_dad_work(ifp, rand_num); |
| 3149 | } | 3174 | } |
| 3150 | 3175 | ||
| 3151 | static void addrconf_dad_start(struct inet6_ifaddr *ifp) | 3176 | static void addrconf_dad_begin(struct inet6_ifaddr *ifp) |
| 3152 | { | 3177 | { |
| 3153 | struct inet6_dev *idev = ifp->idev; | 3178 | struct inet6_dev *idev = ifp->idev; |
| 3154 | struct net_device *dev = idev->dev; | 3179 | struct net_device *dev = idev->dev; |
| @@ -3200,25 +3225,68 @@ out: | |||
| 3200 | read_unlock_bh(&idev->lock); | 3225 | read_unlock_bh(&idev->lock); |
| 3201 | } | 3226 | } |
| 3202 | 3227 | ||
| 3203 | static void addrconf_dad_timer(unsigned long data) | 3228 | static void addrconf_dad_start(struct inet6_ifaddr *ifp) |
| 3204 | { | 3229 | { |
| 3205 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 3230 | bool begin_dad = false; |
| 3231 | |||
| 3232 | spin_lock_bh(&ifp->state_lock); | ||
| 3233 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { | ||
| 3234 | ifp->state = INET6_IFADDR_STATE_PREDAD; | ||
| 3235 | begin_dad = true; | ||
| 3236 | } | ||
| 3237 | spin_unlock_bh(&ifp->state_lock); | ||
| 3238 | |||
| 3239 | if (begin_dad) | ||
| 3240 | addrconf_mod_dad_work(ifp, 0); | ||
| 3241 | } | ||
| 3242 | |||
| 3243 | static void addrconf_dad_work(struct work_struct *w) | ||
| 3244 | { | ||
| 3245 | struct inet6_ifaddr *ifp = container_of(to_delayed_work(w), | ||
| 3246 | struct inet6_ifaddr, | ||
| 3247 | dad_work); | ||
| 3206 | struct inet6_dev *idev = ifp->idev; | 3248 | struct inet6_dev *idev = ifp->idev; |
| 3207 | struct in6_addr mcaddr; | 3249 | struct in6_addr mcaddr; |
| 3208 | 3250 | ||
| 3251 | enum { | ||
| 3252 | DAD_PROCESS, | ||
| 3253 | DAD_BEGIN, | ||
| 3254 | DAD_ABORT, | ||
| 3255 | } action = DAD_PROCESS; | ||
| 3256 | |||
| 3257 | rtnl_lock(); | ||
| 3258 | |||
| 3259 | spin_lock_bh(&ifp->state_lock); | ||
| 3260 | if (ifp->state == INET6_IFADDR_STATE_PREDAD) { | ||
| 3261 | action = DAD_BEGIN; | ||
| 3262 | ifp->state = INET6_IFADDR_STATE_DAD; | ||
| 3263 | } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) { | ||
| 3264 | action = DAD_ABORT; | ||
| 3265 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | ||
| 3266 | } | ||
| 3267 | spin_unlock_bh(&ifp->state_lock); | ||
| 3268 | |||
| 3269 | if (action == DAD_BEGIN) { | ||
| 3270 | addrconf_dad_begin(ifp); | ||
| 3271 | goto out; | ||
| 3272 | } else if (action == DAD_ABORT) { | ||
| 3273 | addrconf_dad_stop(ifp, 1); | ||
| 3274 | goto out; | ||
| 3275 | } | ||
| 3276 | |||
| 3209 | if (!ifp->dad_probes && addrconf_dad_end(ifp)) | 3277 | if (!ifp->dad_probes && addrconf_dad_end(ifp)) |
| 3210 | goto out; | 3278 | goto out; |
| 3211 | 3279 | ||
| 3212 | write_lock(&idev->lock); | 3280 | write_lock_bh(&idev->lock); |
| 3213 | if (idev->dead || !(idev->if_flags & IF_READY)) { | 3281 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
| 3214 | write_unlock(&idev->lock); | 3282 | write_unlock_bh(&idev->lock); |
| 3215 | goto out; | 3283 | goto out; |
| 3216 | } | 3284 | } |
| 3217 | 3285 | ||
| 3218 | spin_lock(&ifp->lock); | 3286 | spin_lock(&ifp->lock); |
| 3219 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | 3287 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { |
| 3220 | spin_unlock(&ifp->lock); | 3288 | spin_unlock(&ifp->lock); |
| 3221 | write_unlock(&idev->lock); | 3289 | write_unlock_bh(&idev->lock); |
| 3222 | goto out; | 3290 | goto out; |
| 3223 | } | 3291 | } |
| 3224 | 3292 | ||
| @@ -3229,7 +3297,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 3229 | 3297 | ||
| 3230 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 3298 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
| 3231 | spin_unlock(&ifp->lock); | 3299 | spin_unlock(&ifp->lock); |
| 3232 | write_unlock(&idev->lock); | 3300 | write_unlock_bh(&idev->lock); |
| 3233 | 3301 | ||
| 3234 | addrconf_dad_completed(ifp); | 3302 | addrconf_dad_completed(ifp); |
| 3235 | 3303 | ||
| @@ -3237,16 +3305,17 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 3237 | } | 3305 | } |
| 3238 | 3306 | ||
| 3239 | ifp->dad_probes--; | 3307 | ifp->dad_probes--; |
| 3240 | addrconf_mod_dad_timer(ifp, | 3308 | addrconf_mod_dad_work(ifp, |
| 3241 | NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME)); | 3309 | NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME)); |
| 3242 | spin_unlock(&ifp->lock); | 3310 | spin_unlock(&ifp->lock); |
| 3243 | write_unlock(&idev->lock); | 3311 | write_unlock_bh(&idev->lock); |
| 3244 | 3312 | ||
| 3245 | /* send a neighbour solicitation for our addr */ | 3313 | /* send a neighbour solicitation for our addr */ |
| 3246 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 3314 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
| 3247 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any); | 3315 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any); |
| 3248 | out: | 3316 | out: |
| 3249 | in6_ifa_put(ifp); | 3317 | in6_ifa_put(ifp); |
| 3318 | rtnl_unlock(); | ||
| 3250 | } | 3319 | } |
| 3251 | 3320 | ||
| 3252 | /* ifp->idev must be at least read locked */ | 3321 | /* ifp->idev must be at least read locked */ |
| @@ -3273,7 +3342,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
| 3273 | struct in6_addr lladdr; | 3342 | struct in6_addr lladdr; |
| 3274 | bool send_rs, send_mld; | 3343 | bool send_rs, send_mld; |
| 3275 | 3344 | ||
| 3276 | addrconf_del_dad_timer(ifp); | 3345 | addrconf_del_dad_work(ifp); |
| 3277 | 3346 | ||
| 3278 | /* | 3347 | /* |
| 3279 | * Configure the address for reception. Now it is valid. | 3348 | * Configure the address for reception. Now it is valid. |
| @@ -3514,23 +3583,23 @@ int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr) | |||
| 3514 | * Periodic address status verification | 3583 | * Periodic address status verification |
| 3515 | */ | 3584 | */ |
| 3516 | 3585 | ||
| 3517 | static void addrconf_verify(unsigned long foo) | 3586 | static void addrconf_verify_rtnl(void) |
| 3518 | { | 3587 | { |
| 3519 | unsigned long now, next, next_sec, next_sched; | 3588 | unsigned long now, next, next_sec, next_sched; |
| 3520 | struct inet6_ifaddr *ifp; | 3589 | struct inet6_ifaddr *ifp; |
| 3521 | int i; | 3590 | int i; |
| 3522 | 3591 | ||
| 3592 | ASSERT_RTNL(); | ||
| 3593 | |||
| 3523 | rcu_read_lock_bh(); | 3594 | rcu_read_lock_bh(); |
| 3524 | spin_lock(&addrconf_verify_lock); | ||
| 3525 | now = jiffies; | 3595 | now = jiffies; |
| 3526 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); | 3596 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
| 3527 | 3597 | ||
| 3528 | del_timer(&addr_chk_timer); | 3598 | cancel_delayed_work(&addr_chk_work); |
| 3529 | 3599 | ||
| 3530 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { | 3600 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
| 3531 | restart: | 3601 | restart: |
| 3532 | hlist_for_each_entry_rcu_bh(ifp, | 3602 | hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[i], addr_lst) { |
| 3533 | &inet6_addr_lst[i], addr_lst) { | ||
| 3534 | unsigned long age; | 3603 | unsigned long age; |
| 3535 | 3604 | ||
| 3536 | /* When setting preferred_lft to a value not zero or | 3605 | /* When setting preferred_lft to a value not zero or |
| @@ -3625,13 +3694,22 @@ restart: | |||
| 3625 | 3694 | ||
| 3626 | ADBG(KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", | 3695 | ADBG(KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", |
| 3627 | now, next, next_sec, next_sched); | 3696 | now, next, next_sec, next_sched); |
| 3628 | 3697 | mod_delayed_work(addrconf_wq, &addr_chk_work, next_sched - now); | |
| 3629 | addr_chk_timer.expires = next_sched; | ||
| 3630 | add_timer(&addr_chk_timer); | ||
| 3631 | spin_unlock(&addrconf_verify_lock); | ||
| 3632 | rcu_read_unlock_bh(); | 3698 | rcu_read_unlock_bh(); |
| 3633 | } | 3699 | } |
| 3634 | 3700 | ||
| 3701 | static void addrconf_verify_work(struct work_struct *w) | ||
| 3702 | { | ||
| 3703 | rtnl_lock(); | ||
| 3704 | addrconf_verify_rtnl(); | ||
| 3705 | rtnl_unlock(); | ||
| 3706 | } | ||
| 3707 | |||
| 3708 | static void addrconf_verify(void) | ||
| 3709 | { | ||
| 3710 | mod_delayed_work(addrconf_wq, &addr_chk_work, 0); | ||
| 3711 | } | ||
| 3712 | |||
| 3635 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local, | 3713 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local, |
| 3636 | struct in6_addr **peer_pfx) | 3714 | struct in6_addr **peer_pfx) |
| 3637 | { | 3715 | { |
| @@ -3688,6 +3766,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags, | |||
| 3688 | bool was_managetempaddr; | 3766 | bool was_managetempaddr; |
| 3689 | bool had_prefixroute; | 3767 | bool had_prefixroute; |
| 3690 | 3768 | ||
| 3769 | ASSERT_RTNL(); | ||
| 3770 | |||
| 3691 | if (!valid_lft || (prefered_lft > valid_lft)) | 3771 | if (!valid_lft || (prefered_lft > valid_lft)) |
| 3692 | return -EINVAL; | 3772 | return -EINVAL; |
| 3693 | 3773 | ||
| @@ -3753,7 +3833,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags, | |||
| 3753 | !was_managetempaddr, jiffies); | 3833 | !was_managetempaddr, jiffies); |
| 3754 | } | 3834 | } |
| 3755 | 3835 | ||
| 3756 | addrconf_verify(0); | 3836 | addrconf_verify_rtnl(); |
| 3757 | 3837 | ||
| 3758 | return 0; | 3838 | return 0; |
| 3759 | } | 3839 | } |
| @@ -4383,6 +4463,8 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
| 4383 | bool update_rs = false; | 4463 | bool update_rs = false; |
| 4384 | struct in6_addr ll_addr; | 4464 | struct in6_addr ll_addr; |
| 4385 | 4465 | ||
| 4466 | ASSERT_RTNL(); | ||
| 4467 | |||
| 4386 | if (token == NULL) | 4468 | if (token == NULL) |
| 4387 | return -EINVAL; | 4469 | return -EINVAL; |
| 4388 | if (ipv6_addr_any(token)) | 4470 | if (ipv6_addr_any(token)) |
| @@ -4431,7 +4513,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
| 4431 | } | 4513 | } |
| 4432 | 4514 | ||
| 4433 | write_unlock_bh(&idev->lock); | 4515 | write_unlock_bh(&idev->lock); |
| 4434 | addrconf_verify(0); | 4516 | addrconf_verify_rtnl(); |
| 4435 | return 0; | 4517 | return 0; |
| 4436 | } | 4518 | } |
| 4437 | 4519 | ||
| @@ -4633,6 +4715,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
| 4633 | { | 4715 | { |
| 4634 | struct net *net = dev_net(ifp->idev->dev); | 4716 | struct net *net = dev_net(ifp->idev->dev); |
| 4635 | 4717 | ||
| 4718 | if (event) | ||
| 4719 | ASSERT_RTNL(); | ||
| 4720 | |||
| 4636 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); | 4721 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); |
| 4637 | 4722 | ||
| 4638 | switch (event) { | 4723 | switch (event) { |
| @@ -5241,6 +5326,12 @@ int __init addrconf_init(void) | |||
| 5241 | if (err < 0) | 5326 | if (err < 0) |
| 5242 | goto out_addrlabel; | 5327 | goto out_addrlabel; |
| 5243 | 5328 | ||
| 5329 | addrconf_wq = create_workqueue("ipv6_addrconf"); | ||
| 5330 | if (!addrconf_wq) { | ||
| 5331 | err = -ENOMEM; | ||
| 5332 | goto out_nowq; | ||
| 5333 | } | ||
| 5334 | |||
| 5244 | /* The addrconf netdev notifier requires that loopback_dev | 5335 | /* The addrconf netdev notifier requires that loopback_dev |
| 5245 | * has it's ipv6 private information allocated and setup | 5336 | * has it's ipv6 private information allocated and setup |
| 5246 | * before it can bring up and give link-local addresses | 5337 | * before it can bring up and give link-local addresses |
| @@ -5271,7 +5362,7 @@ int __init addrconf_init(void) | |||
| 5271 | 5362 | ||
| 5272 | register_netdevice_notifier(&ipv6_dev_notf); | 5363 | register_netdevice_notifier(&ipv6_dev_notf); |
| 5273 | 5364 | ||
| 5274 | addrconf_verify(0); | 5365 | addrconf_verify(); |
| 5275 | 5366 | ||
| 5276 | rtnl_af_register(&inet6_ops); | 5367 | rtnl_af_register(&inet6_ops); |
| 5277 | 5368 | ||
| @@ -5299,6 +5390,8 @@ errout: | |||
| 5299 | rtnl_af_unregister(&inet6_ops); | 5390 | rtnl_af_unregister(&inet6_ops); |
| 5300 | unregister_netdevice_notifier(&ipv6_dev_notf); | 5391 | unregister_netdevice_notifier(&ipv6_dev_notf); |
| 5301 | errlo: | 5392 | errlo: |
| 5393 | destroy_workqueue(addrconf_wq); | ||
| 5394 | out_nowq: | ||
| 5302 | unregister_pernet_subsys(&addrconf_ops); | 5395 | unregister_pernet_subsys(&addrconf_ops); |
| 5303 | out_addrlabel: | 5396 | out_addrlabel: |
| 5304 | ipv6_addr_label_cleanup(); | 5397 | ipv6_addr_label_cleanup(); |
| @@ -5334,7 +5427,8 @@ void addrconf_cleanup(void) | |||
| 5334 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | 5427 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
| 5335 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); | 5428 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); |
| 5336 | spin_unlock_bh(&addrconf_hash_lock); | 5429 | spin_unlock_bh(&addrconf_hash_lock); |
| 5337 | 5430 | cancel_delayed_work(&addr_chk_work); | |
| 5338 | del_timer(&addr_chk_timer); | ||
| 5339 | rtnl_unlock(); | 5431 | rtnl_unlock(); |
| 5432 | |||
| 5433 | destroy_workqueue(addrconf_wq); | ||
| 5340 | } | 5434 | } |
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 140748debc4a..8af3eb57f438 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
| @@ -212,7 +212,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | |||
| 212 | found = (nexthdr == target); | 212 | found = (nexthdr == target); |
| 213 | 213 | ||
| 214 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { | 214 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { |
| 215 | if (target < 0) | 215 | if (target < 0 || found) |
| 216 | break; | 216 | break; |
| 217 | return -ENOENT; | 217 | return -ENOENT; |
| 218 | } | 218 | } |
diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c index cf77f3abfd06..447a7fbd1bb6 100644 --- a/net/ipv6/exthdrs_offload.c +++ b/net/ipv6/exthdrs_offload.c | |||
| @@ -25,11 +25,11 @@ int __init ipv6_exthdrs_offload_init(void) | |||
| 25 | int ret; | 25 | int ret; |
| 26 | 26 | ||
| 27 | ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); | 27 | ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); |
| 28 | if (!ret) | 28 | if (ret) |
| 29 | goto out; | 29 | goto out; |
| 30 | 30 | ||
| 31 | ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); | 31 | ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); |
| 32 | if (!ret) | 32 | if (ret) |
| 33 | goto out_rt; | 33 | goto out_rt; |
| 34 | 34 | ||
| 35 | out: | 35 | out: |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 1e8683b135bb..59f95affceb0 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
| @@ -89,7 +89,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 89 | unsigned int unfrag_ip6hlen; | 89 | unsigned int unfrag_ip6hlen; |
| 90 | u8 *prevhdr; | 90 | u8 *prevhdr; |
| 91 | int offset = 0; | 91 | int offset = 0; |
| 92 | bool tunnel; | 92 | bool encap, udpfrag; |
| 93 | int nhoff; | 93 | int nhoff; |
| 94 | 94 | ||
| 95 | if (unlikely(skb_shinfo(skb)->gso_type & | 95 | if (unlikely(skb_shinfo(skb)->gso_type & |
| @@ -110,8 +110,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 110 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | 110 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) |
| 111 | goto out; | 111 | goto out; |
| 112 | 112 | ||
| 113 | tunnel = SKB_GSO_CB(skb)->encap_level > 0; | 113 | encap = SKB_GSO_CB(skb)->encap_level > 0; |
| 114 | if (tunnel) | 114 | if (encap) |
| 115 | features = skb->dev->hw_enc_features & netif_skb_features(skb); | 115 | features = skb->dev->hw_enc_features & netif_skb_features(skb); |
| 116 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); | 116 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); |
| 117 | 117 | ||
| @@ -121,6 +121,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 121 | 121 | ||
| 122 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | 122 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); |
| 123 | 123 | ||
| 124 | if (skb->encapsulation && | ||
| 125 | skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) | ||
| 126 | udpfrag = proto == IPPROTO_UDP && encap; | ||
| 127 | else | ||
| 128 | udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; | ||
| 129 | |||
| 124 | ops = rcu_dereference(inet6_offloads[proto]); | 130 | ops = rcu_dereference(inet6_offloads[proto]); |
| 125 | if (likely(ops && ops->callbacks.gso_segment)) { | 131 | if (likely(ops && ops->callbacks.gso_segment)) { |
| 126 | skb_reset_transport_header(skb); | 132 | skb_reset_transport_header(skb); |
| @@ -133,13 +139,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 133 | for (skb = segs; skb; skb = skb->next) { | 139 | for (skb = segs; skb; skb = skb->next) { |
| 134 | ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); | 140 | ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); |
| 135 | ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); | 141 | ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); |
| 136 | if (tunnel) { | ||
| 137 | skb_reset_inner_headers(skb); | ||
| 138 | skb->encapsulation = 1; | ||
| 139 | } | ||
| 140 | skb->network_header = (u8 *)ipv6h - skb->head; | 142 | skb->network_header = (u8 *)ipv6h - skb->head; |
| 141 | 143 | ||
| 142 | if (!tunnel && proto == IPPROTO_UDP) { | 144 | if (udpfrag) { |
| 143 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); | 145 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); |
| 144 | fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); | 146 | fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); |
| 145 | fptr->frag_off = htons(offset); | 147 | fptr->frag_off = htons(offset); |
| @@ -148,6 +150,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 148 | offset += (ntohs(ipv6h->payload_len) - | 150 | offset += (ntohs(ipv6h->payload_len) - |
| 149 | sizeof(struct frag_hdr)); | 151 | sizeof(struct frag_hdr)); |
| 150 | } | 152 | } |
| 153 | if (encap) | ||
| 154 | skb_reset_inner_headers(skb); | ||
| 151 | } | 155 | } |
| 152 | 156 | ||
| 153 | out: | 157 | out: |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 070a2fae2375..64d6073731d3 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -530,9 +530,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
| 530 | to->tc_index = from->tc_index; | 530 | to->tc_index = from->tc_index; |
| 531 | #endif | 531 | #endif |
| 532 | nf_copy(to, from); | 532 | nf_copy(to, from); |
| 533 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
| 534 | to->nf_trace = from->nf_trace; | ||
| 535 | #endif | ||
| 536 | skb_copy_secmark(to, from); | 533 | skb_copy_secmark(to, from); |
| 537 | } | 534 | } |
| 538 | 535 | ||
| @@ -1104,21 +1101,19 @@ static void ip6_append_data_mtu(unsigned int *mtu, | |||
| 1104 | unsigned int fragheaderlen, | 1101 | unsigned int fragheaderlen, |
| 1105 | struct sk_buff *skb, | 1102 | struct sk_buff *skb, |
| 1106 | struct rt6_info *rt, | 1103 | struct rt6_info *rt, |
| 1107 | bool pmtuprobe) | 1104 | unsigned int orig_mtu) |
| 1108 | { | 1105 | { |
| 1109 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { | 1106 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { |
| 1110 | if (skb == NULL) { | 1107 | if (skb == NULL) { |
| 1111 | /* first fragment, reserve header_len */ | 1108 | /* first fragment, reserve header_len */ |
| 1112 | *mtu = *mtu - rt->dst.header_len; | 1109 | *mtu = orig_mtu - rt->dst.header_len; |
| 1113 | 1110 | ||
| 1114 | } else { | 1111 | } else { |
| 1115 | /* | 1112 | /* |
| 1116 | * this fragment is not first, the headers | 1113 | * this fragment is not first, the headers |
| 1117 | * space is regarded as data space. | 1114 | * space is regarded as data space. |
| 1118 | */ | 1115 | */ |
| 1119 | *mtu = min(*mtu, pmtuprobe ? | 1116 | *mtu = orig_mtu; |
| 1120 | rt->dst.dev->mtu : | ||
| 1121 | dst_mtu(rt->dst.path)); | ||
| 1122 | } | 1117 | } |
| 1123 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) | 1118 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) |
| 1124 | + fragheaderlen - sizeof(struct frag_hdr); | 1119 | + fragheaderlen - sizeof(struct frag_hdr); |
| @@ -1135,7 +1130,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1135 | struct ipv6_pinfo *np = inet6_sk(sk); | 1130 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 1136 | struct inet_cork *cork; | 1131 | struct inet_cork *cork; |
| 1137 | struct sk_buff *skb, *skb_prev = NULL; | 1132 | struct sk_buff *skb, *skb_prev = NULL; |
| 1138 | unsigned int maxfraglen, fragheaderlen, mtu; | 1133 | unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu; |
| 1139 | int exthdrlen; | 1134 | int exthdrlen; |
| 1140 | int dst_exthdrlen; | 1135 | int dst_exthdrlen; |
| 1141 | int hh_len; | 1136 | int hh_len; |
| @@ -1217,6 +1212,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1217 | dst_exthdrlen = 0; | 1212 | dst_exthdrlen = 0; |
| 1218 | mtu = cork->fragsize; | 1213 | mtu = cork->fragsize; |
| 1219 | } | 1214 | } |
| 1215 | orig_mtu = mtu; | ||
| 1220 | 1216 | ||
| 1221 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 1217 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
| 1222 | 1218 | ||
| @@ -1314,8 +1310,7 @@ alloc_new_skb: | |||
| 1314 | if (skb == NULL || skb_prev == NULL) | 1310 | if (skb == NULL || skb_prev == NULL) |
| 1315 | ip6_append_data_mtu(&mtu, &maxfraglen, | 1311 | ip6_append_data_mtu(&mtu, &maxfraglen, |
| 1316 | fragheaderlen, skb, rt, | 1312 | fragheaderlen, skb, rt, |
| 1317 | np->pmtudisc >= | 1313 | orig_mtu); |
| 1318 | IPV6_PMTUDISC_PROBE); | ||
| 1319 | 1314 | ||
| 1320 | skb_prev = skb; | 1315 | skb_prev = skb; |
| 1321 | 1316 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 0eb4038a4d63..8737400af0a0 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -2349,13 +2349,14 @@ int ip6mr_get_route(struct net *net, | |||
| 2349 | } | 2349 | } |
| 2350 | 2350 | ||
| 2351 | static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, | 2351 | static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, |
| 2352 | u32 portid, u32 seq, struct mfc6_cache *c, int cmd) | 2352 | u32 portid, u32 seq, struct mfc6_cache *c, int cmd, |
| 2353 | int flags) | ||
| 2353 | { | 2354 | { |
| 2354 | struct nlmsghdr *nlh; | 2355 | struct nlmsghdr *nlh; |
| 2355 | struct rtmsg *rtm; | 2356 | struct rtmsg *rtm; |
| 2356 | int err; | 2357 | int err; |
| 2357 | 2358 | ||
| 2358 | nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI); | 2359 | nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags); |
| 2359 | if (nlh == NULL) | 2360 | if (nlh == NULL) |
| 2360 | return -EMSGSIZE; | 2361 | return -EMSGSIZE; |
| 2361 | 2362 | ||
| @@ -2423,7 +2424,7 @@ static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc, | |||
| 2423 | if (skb == NULL) | 2424 | if (skb == NULL) |
| 2424 | goto errout; | 2425 | goto errout; |
| 2425 | 2426 | ||
| 2426 | err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd); | 2427 | err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0); |
| 2427 | if (err < 0) | 2428 | if (err < 0) |
| 2428 | goto errout; | 2429 | goto errout; |
| 2429 | 2430 | ||
| @@ -2462,7 +2463,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2462 | if (ip6mr_fill_mroute(mrt, skb, | 2463 | if (ip6mr_fill_mroute(mrt, skb, |
| 2463 | NETLINK_CB(cb->skb).portid, | 2464 | NETLINK_CB(cb->skb).portid, |
| 2464 | cb->nlh->nlmsg_seq, | 2465 | cb->nlh->nlmsg_seq, |
| 2465 | mfc, RTM_NEWROUTE) < 0) | 2466 | mfc, RTM_NEWROUTE, |
| 2467 | NLM_F_MULTI) < 0) | ||
| 2466 | goto done; | 2468 | goto done; |
| 2467 | next_entry: | 2469 | next_entry: |
| 2468 | e++; | 2470 | e++; |
| @@ -2476,7 +2478,8 @@ next_entry: | |||
| 2476 | if (ip6mr_fill_mroute(mrt, skb, | 2478 | if (ip6mr_fill_mroute(mrt, skb, |
| 2477 | NETLINK_CB(cb->skb).portid, | 2479 | NETLINK_CB(cb->skb).portid, |
| 2478 | cb->nlh->nlmsg_seq, | 2480 | cb->nlh->nlmsg_seq, |
| 2479 | mfc, RTM_NEWROUTE) < 0) { | 2481 | mfc, RTM_NEWROUTE, |
| 2482 | NLM_F_MULTI) < 0) { | ||
| 2480 | spin_unlock_bh(&mfc_unres_lock); | 2483 | spin_unlock_bh(&mfc_unres_lock); |
| 2481 | goto done; | 2484 | goto done; |
| 2482 | } | 2485 | } |
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index fb9beb78f00b..587bbdcb22b4 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
| @@ -135,6 +135,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 135 | fl6.flowi6_proto = IPPROTO_ICMPV6; | 135 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
| 136 | fl6.saddr = np->saddr; | 136 | fl6.saddr = np->saddr; |
| 137 | fl6.daddr = *daddr; | 137 | fl6.daddr = *daddr; |
| 138 | fl6.flowi6_mark = sk->sk_mark; | ||
| 138 | fl6.fl6_icmp_type = user_icmph.icmp6_type; | 139 | fl6.fl6_icmp_type = user_icmph.icmp6_type; |
| 139 | fl6.fl6_icmp_code = user_icmph.icmp6_code; | 140 | fl6.fl6_icmp_code = user_icmph.icmp6_code; |
| 140 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 141 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 11dac21e6586..fba54a407bb2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1513,7 +1513,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1513 | if (!table) | 1513 | if (!table) |
| 1514 | goto out; | 1514 | goto out; |
| 1515 | 1515 | ||
| 1516 | rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table); | 1516 | rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table); |
| 1517 | 1517 | ||
| 1518 | if (!rt) { | 1518 | if (!rt) { |
| 1519 | err = -ENOMEM; | 1519 | err = -ENOMEM; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3dfbcf1dcb1c..b4d74c86586c 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -475,6 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
| 475 | ipip6_tunnel_unlink(sitn, tunnel); | 475 | ipip6_tunnel_unlink(sitn, tunnel); |
| 476 | ipip6_tunnel_del_prl(tunnel, NULL); | 476 | ipip6_tunnel_del_prl(tunnel, NULL); |
| 477 | } | 477 | } |
| 478 | ip_tunnel_dst_reset_all(tunnel); | ||
| 478 | dev_put(dev); | 479 | dev_put(dev); |
| 479 | } | 480 | } |
| 480 | 481 | ||
| @@ -1082,6 +1083,7 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) | |||
| 1082 | t->parms.link = p->link; | 1083 | t->parms.link = p->link; |
| 1083 | ipip6_tunnel_bind_dev(t->dev); | 1084 | ipip6_tunnel_bind_dev(t->dev); |
| 1084 | } | 1085 | } |
| 1086 | ip_tunnel_dst_reset_all(t); | ||
| 1085 | netdev_state_change(t->dev); | 1087 | netdev_state_change(t->dev); |
| 1086 | } | 1088 | } |
| 1087 | 1089 | ||
| @@ -1112,6 +1114,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t, | |||
| 1112 | t->ip6rd.relay_prefix = relay_prefix; | 1114 | t->ip6rd.relay_prefix = relay_prefix; |
| 1113 | t->ip6rd.prefixlen = ip6rd->prefixlen; | 1115 | t->ip6rd.prefixlen = ip6rd->prefixlen; |
| 1114 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; | 1116 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; |
| 1117 | ip_tunnel_dst_reset_all(t); | ||
| 1115 | netdev_state_change(t->dev); | 1118 | netdev_state_change(t->dev); |
| 1116 | return 0; | 1119 | return 0; |
| 1117 | } | 1120 | } |
| @@ -1271,6 +1274,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1271 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | 1274 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); |
| 1272 | break; | 1275 | break; |
| 1273 | } | 1276 | } |
| 1277 | ip_tunnel_dst_reset_all(t); | ||
| 1274 | netdev_state_change(dev); | 1278 | netdev_state_change(dev); |
| 1275 | break; | 1279 | break; |
| 1276 | 1280 | ||
| @@ -1326,6 +1330,9 @@ static const struct net_device_ops ipip6_netdev_ops = { | |||
| 1326 | 1330 | ||
| 1327 | static void ipip6_dev_free(struct net_device *dev) | 1331 | static void ipip6_dev_free(struct net_device *dev) |
| 1328 | { | 1332 | { |
| 1333 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
| 1334 | |||
| 1335 | free_percpu(tunnel->dst_cache); | ||
| 1329 | free_percpu(dev->tstats); | 1336 | free_percpu(dev->tstats); |
| 1330 | free_netdev(dev); | 1337 | free_netdev(dev); |
| 1331 | } | 1338 | } |
| @@ -1375,6 +1382,12 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
| 1375 | u64_stats_init(&ipip6_tunnel_stats->syncp); | 1382 | u64_stats_init(&ipip6_tunnel_stats->syncp); |
| 1376 | } | 1383 | } |
| 1377 | 1384 | ||
| 1385 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
| 1386 | if (!tunnel->dst_cache) { | ||
| 1387 | free_percpu(dev->tstats); | ||
| 1388 | return -ENOMEM; | ||
| 1389 | } | ||
| 1390 | |||
| 1378 | return 0; | 1391 | return 0; |
| 1379 | } | 1392 | } |
| 1380 | 1393 | ||
| @@ -1405,6 +1418,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
| 1405 | u64_stats_init(&ipip6_fb_stats->syncp); | 1418 | u64_stats_init(&ipip6_fb_stats->syncp); |
| 1406 | } | 1419 | } |
| 1407 | 1420 | ||
| 1421 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
| 1422 | if (!tunnel->dst_cache) { | ||
| 1423 | free_percpu(dev->tstats); | ||
| 1424 | return -ENOMEM; | ||
| 1425 | } | ||
| 1426 | |||
| 1408 | dev_hold(dev); | 1427 | dev_hold(dev); |
| 1409 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); | 1428 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
| 1410 | return 0; | 1429 | return 0; |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index e7359f9eaa8d..b261ee8b83fc 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
| @@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
| 113 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); | 113 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); |
| 114 | fptr->nexthdr = nexthdr; | 114 | fptr->nexthdr = nexthdr; |
| 115 | fptr->reserved = 0; | 115 | fptr->reserved = 0; |
| 116 | ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb)); | 116 | fptr->identification = skb_shinfo(skb)->ip6_frag_id; |
| 117 | 117 | ||
| 118 | /* Fragment the skb. ipv6 header and the remaining fields of the | 118 | /* Fragment the skb. ipv6 header and the remaining fields of the |
| 119 | * fragment header are updated in ipv6_gso_segment() | 119 | * fragment header are updated in ipv6_gso_segment() |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 1a04c1329362..79326978517a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -433,12 +433,13 @@ static inline int verify_sec_ctx_len(const void *p) | |||
| 433 | return 0; | 433 | return 0; |
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx) | 436 | static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx, |
| 437 | gfp_t gfp) | ||
| 437 | { | 438 | { |
| 438 | struct xfrm_user_sec_ctx *uctx = NULL; | 439 | struct xfrm_user_sec_ctx *uctx = NULL; |
| 439 | int ctx_size = sec_ctx->sadb_x_ctx_len; | 440 | int ctx_size = sec_ctx->sadb_x_ctx_len; |
| 440 | 441 | ||
| 441 | uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL); | 442 | uctx = kmalloc((sizeof(*uctx)+ctx_size), gfp); |
| 442 | 443 | ||
| 443 | if (!uctx) | 444 | if (!uctx) |
| 444 | return NULL; | 445 | return NULL; |
| @@ -1124,7 +1125,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, | |||
| 1124 | 1125 | ||
| 1125 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; | 1126 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; |
| 1126 | if (sec_ctx != NULL) { | 1127 | if (sec_ctx != NULL) { |
| 1127 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 1128 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL); |
| 1128 | 1129 | ||
| 1129 | if (!uctx) | 1130 | if (!uctx) |
| 1130 | goto out; | 1131 | goto out; |
| @@ -2231,14 +2232,14 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_ | |||
| 2231 | 2232 | ||
| 2232 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; | 2233 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; |
| 2233 | if (sec_ctx != NULL) { | 2234 | if (sec_ctx != NULL) { |
| 2234 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 2235 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL); |
| 2235 | 2236 | ||
| 2236 | if (!uctx) { | 2237 | if (!uctx) { |
| 2237 | err = -ENOBUFS; | 2238 | err = -ENOBUFS; |
| 2238 | goto out; | 2239 | goto out; |
| 2239 | } | 2240 | } |
| 2240 | 2241 | ||
| 2241 | err = security_xfrm_policy_alloc(&xp->security, uctx); | 2242 | err = security_xfrm_policy_alloc(&xp->security, uctx, GFP_KERNEL); |
| 2242 | kfree(uctx); | 2243 | kfree(uctx); |
| 2243 | 2244 | ||
| 2244 | if (err) | 2245 | if (err) |
| @@ -2335,12 +2336,12 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa | |||
| 2335 | 2336 | ||
| 2336 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; | 2337 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; |
| 2337 | if (sec_ctx != NULL) { | 2338 | if (sec_ctx != NULL) { |
| 2338 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 2339 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL); |
| 2339 | 2340 | ||
| 2340 | if (!uctx) | 2341 | if (!uctx) |
| 2341 | return -ENOMEM; | 2342 | return -ENOMEM; |
| 2342 | 2343 | ||
| 2343 | err = security_xfrm_policy_alloc(&pol_ctx, uctx); | 2344 | err = security_xfrm_policy_alloc(&pol_ctx, uctx, GFP_KERNEL); |
| 2344 | kfree(uctx); | 2345 | kfree(uctx); |
| 2345 | if (err) | 2346 | if (err) |
| 2346 | return err; | 2347 | return err; |
| @@ -3239,8 +3240,8 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, | |||
| 3239 | } | 3240 | } |
| 3240 | if ((*dir = verify_sec_ctx_len(p))) | 3241 | if ((*dir = verify_sec_ctx_len(p))) |
| 3241 | goto out; | 3242 | goto out; |
| 3242 | uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 3243 | uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_ATOMIC); |
| 3243 | *dir = security_xfrm_policy_alloc(&xp->security, uctx); | 3244 | *dir = security_xfrm_policy_alloc(&xp->security, uctx, GFP_ATOMIC); |
| 3244 | kfree(uctx); | 3245 | kfree(uctx); |
| 3245 | 3246 | ||
| 3246 | if (*dir) | 3247 | if (*dir) |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 735d0f60c83a..c83827e7c324 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -112,7 +112,6 @@ struct l2tp_net { | |||
| 112 | spinlock_t l2tp_session_hlist_lock; | 112 | spinlock_t l2tp_session_hlist_lock; |
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | static void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
| 116 | static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); | 115 | static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); |
| 117 | 116 | ||
| 118 | static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) | 117 | static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) |
| @@ -1863,7 +1862,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_delete); | |||
| 1863 | /* We come here whenever a session's send_seq, cookie_len or | 1862 | /* We come here whenever a session's send_seq, cookie_len or |
| 1864 | * l2specific_len parameters are set. | 1863 | * l2specific_len parameters are set. |
| 1865 | */ | 1864 | */ |
| 1866 | static void l2tp_session_set_header_len(struct l2tp_session *session, int version) | 1865 | void l2tp_session_set_header_len(struct l2tp_session *session, int version) |
| 1867 | { | 1866 | { |
| 1868 | if (version == L2TP_HDR_VER_2) { | 1867 | if (version == L2TP_HDR_VER_2) { |
| 1869 | session->hdr_len = 6; | 1868 | session->hdr_len = 6; |
| @@ -1876,6 +1875,7 @@ static void l2tp_session_set_header_len(struct l2tp_session *session, int versio | |||
| 1876 | } | 1875 | } |
| 1877 | 1876 | ||
| 1878 | } | 1877 | } |
| 1878 | EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); | ||
| 1879 | 1879 | ||
| 1880 | struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) | 1880 | struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) |
| 1881 | { | 1881 | { |
| @@ -2016,7 +2016,7 @@ static int __init l2tp_init(void) | |||
| 2016 | if (rc) | 2016 | if (rc) |
| 2017 | goto out; | 2017 | goto out; |
| 2018 | 2018 | ||
| 2019 | l2tp_wq = alloc_workqueue("l2tp", WQ_NON_REENTRANT | WQ_UNBOUND, 0); | 2019 | l2tp_wq = alloc_workqueue("l2tp", WQ_UNBOUND, 0); |
| 2020 | if (!l2tp_wq) { | 2020 | if (!l2tp_wq) { |
| 2021 | pr_err("alloc_workqueue failed\n"); | 2021 | pr_err("alloc_workqueue failed\n"); |
| 2022 | rc = -ENOMEM; | 2022 | rc = -ENOMEM; |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 1f01ba3435bc..3f93ccd6ba97 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
| @@ -263,6 +263,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, | |||
| 263 | int length, int (*payload_hook)(struct sk_buff *skb)); | 263 | int length, int (*payload_hook)(struct sk_buff *skb)); |
| 264 | int l2tp_session_queue_purge(struct l2tp_session *session); | 264 | int l2tp_session_queue_purge(struct l2tp_session *session); |
| 265 | int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); | 265 | int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); |
| 266 | void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
| 266 | 267 | ||
| 267 | int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, | 268 | int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, |
| 268 | int hdr_len); | 269 | int hdr_len); |
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 4cfd722e9153..bd7387adea9e 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c | |||
| @@ -578,8 +578,10 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf | |||
| 578 | if (info->attrs[L2TP_ATTR_RECV_SEQ]) | 578 | if (info->attrs[L2TP_ATTR_RECV_SEQ]) |
| 579 | session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]); | 579 | session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]); |
| 580 | 580 | ||
| 581 | if (info->attrs[L2TP_ATTR_SEND_SEQ]) | 581 | if (info->attrs[L2TP_ATTR_SEND_SEQ]) { |
| 582 | session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]); | 582 | session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]); |
| 583 | l2tp_session_set_header_len(session, session->tunnel->version); | ||
| 584 | } | ||
| 583 | 585 | ||
| 584 | if (info->attrs[L2TP_ATTR_LNS_MODE]) | 586 | if (info->attrs[L2TP_ATTR_LNS_MODE]) |
| 585 | session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]); | 587 | session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]); |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index be5fadf34739..5990919356a5 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
| @@ -254,12 +254,14 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int | |||
| 254 | po = pppox_sk(sk); | 254 | po = pppox_sk(sk); |
| 255 | ppp_input(&po->chan, skb); | 255 | ppp_input(&po->chan, skb); |
| 256 | } else { | 256 | } else { |
| 257 | l2tp_info(session, PPPOL2TP_MSG_DATA, "%s: socket not bound\n", | 257 | l2tp_dbg(session, PPPOL2TP_MSG_DATA, |
| 258 | session->name); | 258 | "%s: recv %d byte data frame, passing to L2TP socket\n", |
| 259 | session->name, data_len); | ||
| 259 | 260 | ||
| 260 | /* Not bound. Nothing we can do, so discard. */ | 261 | if (sock_queue_rcv_skb(sk, skb) < 0) { |
| 261 | atomic_long_inc(&session->stats.rx_errors); | 262 | atomic_long_inc(&session->stats.rx_errors); |
| 262 | kfree_skb(skb); | 263 | kfree_skb(skb); |
| 264 | } | ||
| 263 | } | 265 | } |
| 264 | 266 | ||
| 265 | return; | 267 | return; |
| @@ -1312,6 +1314,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk, | |||
| 1312 | po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : | 1314 | po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : |
| 1313 | PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; | 1315 | PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; |
| 1314 | } | 1316 | } |
| 1317 | l2tp_session_set_header_len(session, session->tunnel->version); | ||
| 1315 | l2tp_info(session, PPPOL2TP_MSG_CONTROL, | 1318 | l2tp_info(session, PPPOL2TP_MSG_CONTROL, |
| 1316 | "%s: set send_seq=%d\n", | 1319 | "%s: set send_seq=%d\n", |
| 1317 | session->name, session->send_seq); | 1320 | session->name, session->send_seq); |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f43613a97dd6..0c1ecfdf9a12 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -100,6 +100,12 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, | |||
| 100 | } | 100 | } |
| 101 | max_bw = max(max_bw, width); | 101 | max_bw = max(max_bw, width); |
| 102 | } | 102 | } |
| 103 | |||
| 104 | /* use the configured bandwidth in case of monitor interface */ | ||
| 105 | sdata = rcu_dereference(local->monitor_sdata); | ||
| 106 | if (sdata && rcu_access_pointer(sdata->vif.chanctx_conf) == conf) | ||
| 107 | max_bw = max(max_bw, conf->def.width); | ||
| 108 | |||
| 103 | rcu_read_unlock(); | 109 | rcu_read_unlock(); |
| 104 | 110 | ||
| 105 | return max_bw; | 111 | return max_bw; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3701930c6649..5e44e3179e02 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -1692,14 +1692,8 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | |||
| 1692 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); | 1692 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); |
| 1693 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | 1693 | void ieee80211_add_pending_skb(struct ieee80211_local *local, |
| 1694 | struct sk_buff *skb); | 1694 | struct sk_buff *skb); |
| 1695 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | 1695 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, |
| 1696 | struct sk_buff_head *skbs, | 1696 | struct sk_buff_head *skbs); |
| 1697 | void (*fn)(void *data), void *data); | ||
| 1698 | static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
| 1699 | struct sk_buff_head *skbs) | ||
| 1700 | { | ||
| 1701 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | ||
| 1702 | } | ||
| 1703 | void ieee80211_flush_queues(struct ieee80211_local *local, | 1697 | void ieee80211_flush_queues(struct ieee80211_local *local, |
| 1704 | struct ieee80211_sub_if_data *sdata); | 1698 | struct ieee80211_sub_if_data *sdata); |
| 1705 | 1699 | ||
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c index 2802f9d9279d..ad8b377b4b9f 100644 --- a/net/mac80211/mesh_ps.c +++ b/net/mac80211/mesh_ps.c | |||
| @@ -36,6 +36,7 @@ static struct sk_buff *mps_qos_null_get(struct sta_info *sta) | |||
| 36 | sdata->vif.addr); | 36 | sdata->vif.addr); |
| 37 | nullfunc->frame_control = fc; | 37 | nullfunc->frame_control = fc; |
| 38 | nullfunc->duration_id = 0; | 38 | nullfunc->duration_id = 0; |
| 39 | nullfunc->seq_ctrl = 0; | ||
| 39 | /* no address resolution for this frame -> set addr 1 immediately */ | 40 | /* no address resolution for this frame -> set addr 1 immediately */ |
| 40 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); | 41 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); |
| 41 | memset(skb_put(skb, 2), 0, 2); /* append QoS control field */ | 42 | memset(skb_put(skb, 2), 0, 2); /* append QoS control field */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fc1d82465b3c..245dce969b31 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 222 | switch (vht_oper->chan_width) { | 222 | switch (vht_oper->chan_width) { |
| 223 | case IEEE80211_VHT_CHANWIDTH_USE_HT: | 223 | case IEEE80211_VHT_CHANWIDTH_USE_HT: |
| 224 | vht_chandef.width = chandef->width; | 224 | vht_chandef.width = chandef->width; |
| 225 | vht_chandef.center_freq1 = chandef->center_freq1; | ||
| 225 | break; | 226 | break; |
| 226 | case IEEE80211_VHT_CHANWIDTH_80MHZ: | 227 | case IEEE80211_VHT_CHANWIDTH_80MHZ: |
| 227 | vht_chandef.width = NL80211_CHAN_WIDTH_80; | 228 | vht_chandef.width = NL80211_CHAN_WIDTH_80; |
| @@ -271,6 +272,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 271 | ret = 0; | 272 | ret = 0; |
| 272 | 273 | ||
| 273 | out: | 274 | out: |
| 275 | /* | ||
| 276 | * When tracking the current AP, don't do any further checks if the | ||
| 277 | * new chandef is identical to the one we're currently using for the | ||
| 278 | * connection. This keeps us from playing ping-pong with regulatory, | ||
| 279 | * without it the following can happen (for example): | ||
| 280 | * - connect to an AP with 80 MHz, world regdom allows 80 MHz | ||
| 281 | * - AP advertises regdom US | ||
| 282 | * - CRDA loads regdom US with 80 MHz prohibited (old database) | ||
| 283 | * - the code below detects an unsupported channel, downgrades, and | ||
| 284 | * we disconnect from the AP in the caller | ||
| 285 | * - disconnect causes CRDA to reload world regdomain and the game | ||
| 286 | * starts anew. | ||
| 287 | * (see https://bugzilla.kernel.org/show_bug.cgi?id=70881) | ||
| 288 | * | ||
| 289 | * It seems possible that there are still scenarios with CSA or real | ||
| 290 | * bandwidth changes where a this could happen, but those cases are | ||
| 291 | * less common and wouldn't completely prevent using the AP. | ||
| 292 | */ | ||
| 293 | if (tracking && | ||
| 294 | cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) | ||
| 295 | return ret; | ||
| 296 | |||
| 274 | /* don't print the message below for VHT mismatch if VHT is disabled */ | 297 | /* don't print the message below for VHT mismatch if VHT is disabled */ |
| 275 | if (ret & IEEE80211_STA_DISABLE_VHT) | 298 | if (ret & IEEE80211_STA_DISABLE_VHT) |
| 276 | vht_chandef = *chandef; | 299 | vht_chandef = *chandef; |
| @@ -3753,6 +3776,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
| 3753 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3776 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
| 3754 | if (WARN_ON(!chanctx_conf)) { | 3777 | if (WARN_ON(!chanctx_conf)) { |
| 3755 | rcu_read_unlock(); | 3778 | rcu_read_unlock(); |
| 3779 | sta_info_free(local, new_sta); | ||
| 3756 | return -EINVAL; | 3780 | return -EINVAL; |
| 3757 | } | 3781 | } |
| 3758 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | 3782 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c24ca0d0f469..3e57f96c9666 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *sta) | |||
| 1128 | sta->sta.addr, sta->sta.aid); | 1128 | sta->sta.addr, sta->sta.aid); |
| 1129 | 1129 | ||
| 1130 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 1130 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
| 1131 | /* | ||
| 1132 | * Clear the flag only if the other one is still set | ||
| 1133 | * so that the TX path won't start TX'ing new frames | ||
| 1134 | * directly ... In the case that the driver flag isn't | ||
| 1135 | * set ieee80211_sta_ps_deliver_wakeup() will clear it. | ||
| 1136 | */ | ||
| 1137 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
| 1131 | ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", | 1138 | ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", |
| 1132 | sta->sta.addr, sta->sta.aid); | 1139 | sta->sta.addr, sta->sta.aid); |
| 1133 | return; | 1140 | return; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index decd30c1e290..137a192e64bc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
| 91 | return -ENOENT; | 91 | return -ENOENT; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static void cleanup_single_sta(struct sta_info *sta) | 94 | static void __cleanup_single_sta(struct sta_info *sta) |
| 95 | { | 95 | { |
| 96 | int ac, i; | 96 | int ac, i; |
| 97 | struct tid_ampdu_tx *tid_tx; | 97 | struct tid_ampdu_tx *tid_tx; |
| @@ -99,7 +99,8 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
| 99 | struct ieee80211_local *local = sdata->local; | 99 | struct ieee80211_local *local = sdata->local; |
| 100 | struct ps_data *ps; | 100 | struct ps_data *ps; |
| 101 | 101 | ||
| 102 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 102 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || |
| 103 | test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | ||
| 103 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || | 104 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
| 104 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 105 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 105 | ps = &sdata->bss->ps; | 106 | ps = &sdata->bss->ps; |
| @@ -109,6 +110,7 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
| 109 | return; | 110 | return; |
| 110 | 111 | ||
| 111 | clear_sta_flag(sta, WLAN_STA_PS_STA); | 112 | clear_sta_flag(sta, WLAN_STA_PS_STA); |
| 113 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
| 112 | 114 | ||
| 113 | atomic_dec(&ps->num_sta_ps); | 115 | atomic_dec(&ps->num_sta_ps); |
| 114 | sta_info_recalc_tim(sta); | 116 | sta_info_recalc_tim(sta); |
| @@ -139,7 +141,14 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
| 139 | ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); | 141 | ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); |
| 140 | kfree(tid_tx); | 142 | kfree(tid_tx); |
| 141 | } | 143 | } |
| 144 | } | ||
| 142 | 145 | ||
| 146 | static void cleanup_single_sta(struct sta_info *sta) | ||
| 147 | { | ||
| 148 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
| 149 | struct ieee80211_local *local = sdata->local; | ||
| 150 | |||
| 151 | __cleanup_single_sta(sta); | ||
| 143 | sta_info_free(local, sta); | 152 | sta_info_free(local, sta); |
| 144 | } | 153 | } |
| 145 | 154 | ||
| @@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
| 330 | rcu_read_unlock(); | 339 | rcu_read_unlock(); |
| 331 | 340 | ||
| 332 | spin_lock_init(&sta->lock); | 341 | spin_lock_init(&sta->lock); |
| 342 | spin_lock_init(&sta->ps_lock); | ||
| 333 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 343 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
| 334 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 344 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
| 335 | mutex_init(&sta->ampdu_mlme.mtx); | 345 | mutex_init(&sta->ampdu_mlme.mtx); |
| @@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
| 487 | goto out_err; | 497 | goto out_err; |
| 488 | } | 498 | } |
| 489 | 499 | ||
| 490 | /* notify driver */ | ||
| 491 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
| 492 | if (err) | ||
| 493 | goto out_err; | ||
| 494 | |||
| 495 | local->num_sta++; | 500 | local->num_sta++; |
| 496 | local->sta_generation++; | 501 | local->sta_generation++; |
| 497 | smp_mb(); | 502 | smp_mb(); |
| 498 | 503 | ||
| 504 | /* simplify things and don't accept BA sessions yet */ | ||
| 505 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | ||
| 506 | |||
| 499 | /* make the station visible */ | 507 | /* make the station visible */ |
| 500 | sta_info_hash_add(local, sta); | 508 | sta_info_hash_add(local, sta); |
| 501 | 509 | ||
| 502 | list_add_rcu(&sta->list, &local->sta_list); | 510 | list_add_rcu(&sta->list, &local->sta_list); |
| 503 | 511 | ||
| 512 | /* notify driver */ | ||
| 513 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
| 514 | if (err) | ||
| 515 | goto out_remove; | ||
| 516 | |||
| 504 | set_sta_flag(sta, WLAN_STA_INSERTED); | 517 | set_sta_flag(sta, WLAN_STA_INSERTED); |
| 518 | /* accept BA sessions now */ | ||
| 519 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); | ||
| 505 | 520 | ||
| 506 | ieee80211_recalc_min_chandef(sdata); | 521 | ieee80211_recalc_min_chandef(sdata); |
| 507 | ieee80211_sta_debugfs_add(sta); | 522 | ieee80211_sta_debugfs_add(sta); |
| @@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
| 522 | mesh_accept_plinks_update(sdata); | 537 | mesh_accept_plinks_update(sdata); |
| 523 | 538 | ||
| 524 | return 0; | 539 | return 0; |
| 540 | out_remove: | ||
| 541 | sta_info_hash_del(local, sta); | ||
| 542 | list_del_rcu(&sta->list); | ||
| 543 | local->num_sta--; | ||
| 544 | synchronize_net(); | ||
| 545 | __cleanup_single_sta(sta); | ||
| 525 | out_err: | 546 | out_err: |
| 526 | mutex_unlock(&local->sta_mtx); | 547 | mutex_unlock(&local->sta_mtx); |
| 527 | rcu_read_lock(); | 548 | rcu_read_lock(); |
| @@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | |||
| 1071 | } | 1092 | } |
| 1072 | EXPORT_SYMBOL(ieee80211_find_sta); | 1093 | EXPORT_SYMBOL(ieee80211_find_sta); |
| 1073 | 1094 | ||
| 1074 | static void clear_sta_ps_flags(void *_sta) | 1095 | /* powersave support code */ |
| 1096 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | ||
| 1075 | { | 1097 | { |
| 1076 | struct sta_info *sta = _sta; | ||
| 1077 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1098 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
| 1099 | struct ieee80211_local *local = sdata->local; | ||
| 1100 | struct sk_buff_head pending; | ||
| 1101 | int filtered = 0, buffered = 0, ac; | ||
| 1102 | unsigned long flags; | ||
| 1078 | struct ps_data *ps; | 1103 | struct ps_data *ps; |
| 1079 | 1104 | ||
| 1080 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 1105 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
| @@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_sta) | |||
| 1085 | else | 1110 | else |
| 1086 | return; | 1111 | return; |
| 1087 | 1112 | ||
| 1088 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
| 1089 | if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA)) | ||
| 1090 | atomic_dec(&ps->num_sta_ps); | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | /* powersave support code */ | ||
| 1094 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | ||
| 1095 | { | ||
| 1096 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
| 1097 | struct ieee80211_local *local = sdata->local; | ||
| 1098 | struct sk_buff_head pending; | ||
| 1099 | int filtered = 0, buffered = 0, ac; | ||
| 1100 | unsigned long flags; | ||
| 1101 | |||
| 1102 | clear_sta_flag(sta, WLAN_STA_SP); | 1113 | clear_sta_flag(sta, WLAN_STA_SP); |
| 1103 | 1114 | ||
| 1104 | BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); | 1115 | BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); |
| @@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
| 1109 | 1120 | ||
| 1110 | skb_queue_head_init(&pending); | 1121 | skb_queue_head_init(&pending); |
| 1111 | 1122 | ||
| 1123 | /* sync with ieee80211_tx_h_unicast_ps_buf */ | ||
| 1124 | spin_lock(&sta->ps_lock); | ||
| 1112 | /* Send all buffered frames to the station */ | 1125 | /* Send all buffered frames to the station */ |
| 1113 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1126 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 1114 | int count = skb_queue_len(&pending), tmp; | 1127 | int count = skb_queue_len(&pending), tmp; |
| @@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
| 1127 | buffered += tmp - count; | 1140 | buffered += tmp - count; |
| 1128 | } | 1141 | } |
| 1129 | 1142 | ||
| 1130 | ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); | 1143 | ieee80211_add_pending_skbs(local, &pending); |
| 1144 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
| 1145 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
| 1146 | spin_unlock(&sta->ps_lock); | ||
| 1147 | |||
| 1148 | atomic_dec(&ps->num_sta_ps); | ||
| 1131 | 1149 | ||
| 1132 | /* This station just woke up and isn't aware of our SMPS state */ | 1150 | /* This station just woke up and isn't aware of our SMPS state */ |
| 1133 | if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, | 1151 | if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, |
| @@ -1188,6 +1206,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
| 1188 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); | 1206 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); |
| 1189 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); | 1207 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); |
| 1190 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); | 1208 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); |
| 1209 | nullfunc->seq_ctrl = 0; | ||
| 1191 | 1210 | ||
| 1192 | skb->priority = tid; | 1211 | skb->priority = tid; |
| 1193 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); | 1212 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d77ff7090630..d3a6d8208f2f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
| @@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat { | |||
| 267 | * @drv_unblock_wk: used for driver PS unblocking | 267 | * @drv_unblock_wk: used for driver PS unblocking |
| 268 | * @listen_interval: listen interval of this station, when we're acting as AP | 268 | * @listen_interval: listen interval of this station, when we're acting as AP |
| 269 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly | 269 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly |
| 270 | * @ps_lock: used for powersave (when mac80211 is the AP) related locking | ||
| 270 | * @ps_tx_buf: buffers (per AC) of frames to transmit to this station | 271 | * @ps_tx_buf: buffers (per AC) of frames to transmit to this station |
| 271 | * when it leaves power saving state or polls | 272 | * when it leaves power saving state or polls |
| 272 | * @tx_filtered: buffers (per AC) of frames we already tried to | 273 | * @tx_filtered: buffers (per AC) of frames we already tried to |
| @@ -356,10 +357,8 @@ struct sta_info { | |||
| 356 | /* use the accessors defined below */ | 357 | /* use the accessors defined below */ |
| 357 | unsigned long _flags; | 358 | unsigned long _flags; |
| 358 | 359 | ||
| 359 | /* | 360 | /* STA powersave lock and frame queues */ |
| 360 | * STA powersave frame queues, no more than the internal | 361 | spinlock_t ps_lock; |
| 361 | * locking required. | ||
| 362 | */ | ||
| 363 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; | 362 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; |
| 364 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; | 363 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; |
| 365 | unsigned long driver_buffered_tids; | 364 | unsigned long driver_buffered_tids; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 97a02d3f7d87..4080c615636f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -478,6 +478,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 478 | sta->sta.addr, sta->sta.aid, ac); | 478 | sta->sta.addr, sta->sta.aid, ac); |
| 479 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 479 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
| 480 | purge_old_ps_buffers(tx->local); | 480 | purge_old_ps_buffers(tx->local); |
| 481 | |||
| 482 | /* sync with ieee80211_sta_ps_deliver_wakeup */ | ||
| 483 | spin_lock(&sta->ps_lock); | ||
| 484 | /* | ||
| 485 | * STA woke up the meantime and all the frames on ps_tx_buf have | ||
| 486 | * been queued to pending queue. No reordering can happen, go | ||
| 487 | * ahead and Tx the packet. | ||
| 488 | */ | ||
| 489 | if (!test_sta_flag(sta, WLAN_STA_PS_STA) && | ||
| 490 | !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | ||
| 491 | spin_unlock(&sta->ps_lock); | ||
| 492 | return TX_CONTINUE; | ||
| 493 | } | ||
| 494 | |||
| 481 | if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { | 495 | if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { |
| 482 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); | 496 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); |
| 483 | ps_dbg(tx->sdata, | 497 | ps_dbg(tx->sdata, |
| @@ -492,6 +506,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 492 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 506 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
| 493 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; | 507 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; |
| 494 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); | 508 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); |
| 509 | spin_unlock(&sta->ps_lock); | ||
| 495 | 510 | ||
| 496 | if (!timer_pending(&local->sta_cleanup)) | 511 | if (!timer_pending(&local->sta_cleanup)) |
| 497 | mod_timer(&local->sta_cleanup, | 512 | mod_timer(&local->sta_cleanup, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 676dc0967f37..b8700d417a9c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
| 435 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 435 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | 438 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, |
| 439 | struct sk_buff_head *skbs, | 439 | struct sk_buff_head *skbs) |
| 440 | void (*fn)(void *data), void *data) | ||
| 441 | { | 440 | { |
| 442 | struct ieee80211_hw *hw = &local->hw; | 441 | struct ieee80211_hw *hw = &local->hw; |
| 443 | struct sk_buff *skb; | 442 | struct sk_buff *skb; |
| @@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
| 461 | __skb_queue_tail(&local->pending[queue], skb); | 460 | __skb_queue_tail(&local->pending[queue], skb); |
| 462 | } | 461 | } |
| 463 | 462 | ||
| 464 | if (fn) | ||
| 465 | fn(data); | ||
| 466 | |||
| 467 | for (i = 0; i < hw->queues; i++) | 463 | for (i = 0; i < hw->queues; i++) |
| 468 | __ieee80211_wake_queue(hw, i, | 464 | __ieee80211_wake_queue(hw, i, |
| 469 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 465 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
| @@ -1741,6 +1737,26 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1741 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1737 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
| 1742 | 1738 | ||
| 1743 | /* | 1739 | /* |
| 1740 | * Reconfigure sched scan if it was interrupted by FW restart or | ||
| 1741 | * suspend. | ||
| 1742 | */ | ||
| 1743 | mutex_lock(&local->mtx); | ||
| 1744 | sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, | ||
| 1745 | lockdep_is_held(&local->mtx)); | ||
| 1746 | if (sched_scan_sdata && local->sched_scan_req) | ||
| 1747 | /* | ||
| 1748 | * Sched scan stopped, but we don't want to report it. Instead, | ||
| 1749 | * we're trying to reschedule. | ||
| 1750 | */ | ||
| 1751 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, | ||
| 1752 | local->sched_scan_req)) | ||
| 1753 | sched_scan_stopped = true; | ||
| 1754 | mutex_unlock(&local->mtx); | ||
| 1755 | |||
| 1756 | if (sched_scan_stopped) | ||
| 1757 | cfg80211_sched_scan_stopped(local->hw.wiphy); | ||
| 1758 | |||
| 1759 | /* | ||
| 1744 | * If this is for hw restart things are still running. | 1760 | * If this is for hw restart things are still running. |
| 1745 | * We may want to change that later, however. | 1761 | * We may want to change that later, however. |
| 1746 | */ | 1762 | */ |
| @@ -1768,26 +1784,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1768 | WARN_ON(1); | 1784 | WARN_ON(1); |
| 1769 | #endif | 1785 | #endif |
| 1770 | 1786 | ||
| 1771 | /* | ||
| 1772 | * Reconfigure sched scan if it was interrupted by FW restart or | ||
| 1773 | * suspend. | ||
| 1774 | */ | ||
| 1775 | mutex_lock(&local->mtx); | ||
| 1776 | sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, | ||
| 1777 | lockdep_is_held(&local->mtx)); | ||
| 1778 | if (sched_scan_sdata && local->sched_scan_req) | ||
| 1779 | /* | ||
| 1780 | * Sched scan stopped, but we don't want to report it. Instead, | ||
| 1781 | * we're trying to reschedule. | ||
| 1782 | */ | ||
| 1783 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, | ||
| 1784 | local->sched_scan_req)) | ||
| 1785 | sched_scan_stopped = true; | ||
| 1786 | mutex_unlock(&local->mtx); | ||
| 1787 | |||
| 1788 | if (sched_scan_stopped) | ||
| 1789 | cfg80211_sched_scan_stopped(local->hw.wiphy); | ||
| 1790 | |||
| 1791 | return 0; | 1787 | return 0; |
| 1792 | } | 1788 | } |
| 1793 | 1789 | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 21211c60ca98..d51422c778de 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
| @@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
| 154 | return IEEE80211_AC_BE; | 154 | return IEEE80211_AC_BE; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | if (skb->protocol == sdata->control_port_protocol) { | ||
| 158 | skb->priority = 7; | ||
| 159 | return ieee80211_downgrade_queue(sdata, skb); | ||
| 160 | } | ||
| 161 | |||
| 157 | /* use the data classifier to determine what 802.1d tag the | 162 | /* use the data classifier to determine what 802.1d tag the |
| 158 | * data frame has */ | 163 | * data frame has */ |
| 159 | rcu_read_lock(); | 164 | rcu_read_lock(); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index bb322d0beb48..b9f0e0374322 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -1310,27 +1310,22 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) | |||
| 1310 | } | 1310 | } |
| 1311 | 1311 | ||
| 1312 | static int | 1312 | static int |
| 1313 | ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[]) | 1313 | ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[]) |
| 1314 | { | 1314 | { |
| 1315 | #ifdef CONFIG_NF_NAT_NEEDED | 1315 | #ifdef CONFIG_NF_NAT_NEEDED |
| 1316 | int ret; | 1316 | int ret; |
| 1317 | 1317 | ||
| 1318 | if (cda[CTA_NAT_DST]) { | 1318 | ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST, |
| 1319 | ret = ctnetlink_parse_nat_setup(ct, | 1319 | cda[CTA_NAT_DST]); |
| 1320 | NF_NAT_MANIP_DST, | 1320 | if (ret < 0) |
| 1321 | cda[CTA_NAT_DST]); | 1321 | return ret; |
| 1322 | if (ret < 0) | 1322 | |
| 1323 | return ret; | 1323 | ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC, |
| 1324 | } | 1324 | cda[CTA_NAT_SRC]); |
| 1325 | if (cda[CTA_NAT_SRC]) { | 1325 | return ret; |
| 1326 | ret = ctnetlink_parse_nat_setup(ct, | ||
| 1327 | NF_NAT_MANIP_SRC, | ||
| 1328 | cda[CTA_NAT_SRC]); | ||
| 1329 | if (ret < 0) | ||
| 1330 | return ret; | ||
| 1331 | } | ||
| 1332 | return 0; | ||
| 1333 | #else | 1326 | #else |
| 1327 | if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC]) | ||
| 1328 | return 0; | ||
| 1334 | return -EOPNOTSUPP; | 1329 | return -EOPNOTSUPP; |
| 1335 | #endif | 1330 | #endif |
| 1336 | } | 1331 | } |
| @@ -1659,11 +1654,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
| 1659 | goto err2; | 1654 | goto err2; |
| 1660 | } | 1655 | } |
| 1661 | 1656 | ||
| 1662 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { | 1657 | err = ctnetlink_setup_nat(ct, cda); |
| 1663 | err = ctnetlink_change_nat(ct, cda); | 1658 | if (err < 0) |
| 1664 | if (err < 0) | 1659 | goto err2; |
| 1665 | goto err2; | ||
| 1666 | } | ||
| 1667 | 1660 | ||
| 1668 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); | 1661 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); |
| 1669 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); | 1662 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); |
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index d3f5cd6dd962..52ca952b802c 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c | |||
| @@ -432,15 +432,15 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
| 432 | } | 432 | } |
| 433 | EXPORT_SYMBOL(nf_nat_setup_info); | 433 | EXPORT_SYMBOL(nf_nat_setup_info); |
| 434 | 434 | ||
| 435 | unsigned int | 435 | static unsigned int |
| 436 | nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | 436 | __nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip) |
| 437 | { | 437 | { |
| 438 | /* Force range to this IP; let proto decide mapping for | 438 | /* Force range to this IP; let proto decide mapping for |
| 439 | * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). | 439 | * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). |
| 440 | * Use reply in case it's already been mangled (eg local packet). | 440 | * Use reply in case it's already been mangled (eg local packet). |
| 441 | */ | 441 | */ |
| 442 | union nf_inet_addr ip = | 442 | union nf_inet_addr ip = |
| 443 | (HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ? | 443 | (manip == NF_NAT_MANIP_SRC ? |
| 444 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 : | 444 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 : |
| 445 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3); | 445 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3); |
| 446 | struct nf_nat_range range = { | 446 | struct nf_nat_range range = { |
| @@ -448,7 +448,13 @@ nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | |||
| 448 | .min_addr = ip, | 448 | .min_addr = ip, |
| 449 | .max_addr = ip, | 449 | .max_addr = ip, |
| 450 | }; | 450 | }; |
| 451 | return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); | 451 | return nf_nat_setup_info(ct, &range, manip); |
| 452 | } | ||
| 453 | |||
| 454 | unsigned int | ||
| 455 | nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | ||
| 456 | { | ||
| 457 | return __nf_nat_alloc_null_binding(ct, HOOK2MANIP(hooknum)); | ||
| 452 | } | 458 | } |
| 453 | EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding); | 459 | EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding); |
| 454 | 460 | ||
| @@ -702,9 +708,9 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { | |||
| 702 | 708 | ||
| 703 | static int | 709 | static int |
| 704 | nfnetlink_parse_nat(const struct nlattr *nat, | 710 | nfnetlink_parse_nat(const struct nlattr *nat, |
| 705 | const struct nf_conn *ct, struct nf_nat_range *range) | 711 | const struct nf_conn *ct, struct nf_nat_range *range, |
| 712 | const struct nf_nat_l3proto *l3proto) | ||
| 706 | { | 713 | { |
| 707 | const struct nf_nat_l3proto *l3proto; | ||
| 708 | struct nlattr *tb[CTA_NAT_MAX+1]; | 714 | struct nlattr *tb[CTA_NAT_MAX+1]; |
| 709 | int err; | 715 | int err; |
| 710 | 716 | ||
| @@ -714,38 +720,46 @@ nfnetlink_parse_nat(const struct nlattr *nat, | |||
| 714 | if (err < 0) | 720 | if (err < 0) |
| 715 | return err; | 721 | return err; |
| 716 | 722 | ||
| 717 | rcu_read_lock(); | ||
| 718 | l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); | ||
| 719 | if (l3proto == NULL) { | ||
| 720 | err = -EAGAIN; | ||
| 721 | goto out; | ||
| 722 | } | ||
| 723 | err = l3proto->nlattr_to_range(tb, range); | 723 | err = l3proto->nlattr_to_range(tb, range); |
| 724 | if (err < 0) | 724 | if (err < 0) |
| 725 | goto out; | 725 | return err; |
| 726 | 726 | ||
| 727 | if (!tb[CTA_NAT_PROTO]) | 727 | if (!tb[CTA_NAT_PROTO]) |
| 728 | goto out; | 728 | return 0; |
| 729 | 729 | ||
| 730 | err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); | 730 | return nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); |
| 731 | out: | ||
| 732 | rcu_read_unlock(); | ||
| 733 | return err; | ||
| 734 | } | 731 | } |
| 735 | 732 | ||
| 733 | /* This function is called under rcu_read_lock() */ | ||
| 736 | static int | 734 | static int |
| 737 | nfnetlink_parse_nat_setup(struct nf_conn *ct, | 735 | nfnetlink_parse_nat_setup(struct nf_conn *ct, |
| 738 | enum nf_nat_manip_type manip, | 736 | enum nf_nat_manip_type manip, |
| 739 | const struct nlattr *attr) | 737 | const struct nlattr *attr) |
| 740 | { | 738 | { |
| 741 | struct nf_nat_range range; | 739 | struct nf_nat_range range; |
| 740 | const struct nf_nat_l3proto *l3proto; | ||
| 742 | int err; | 741 | int err; |
| 743 | 742 | ||
| 744 | err = nfnetlink_parse_nat(attr, ct, &range); | 743 | /* Should not happen, restricted to creating new conntracks |
| 744 | * via ctnetlink. | ||
| 745 | */ | ||
| 746 | if (WARN_ON_ONCE(nf_nat_initialized(ct, manip))) | ||
| 747 | return -EEXIST; | ||
| 748 | |||
| 749 | /* Make sure that L3 NAT is there by when we call nf_nat_setup_info to | ||
| 750 | * attach the null binding, otherwise this may oops. | ||
| 751 | */ | ||
| 752 | l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); | ||
| 753 | if (l3proto == NULL) | ||
| 754 | return -EAGAIN; | ||
| 755 | |||
| 756 | /* No NAT information has been passed, allocate the null-binding */ | ||
| 757 | if (attr == NULL) | ||
| 758 | return __nf_nat_alloc_null_binding(ct, manip); | ||
| 759 | |||
| 760 | err = nfnetlink_parse_nat(attr, ct, &range, l3proto); | ||
| 745 | if (err < 0) | 761 | if (err < 0) |
| 746 | return err; | 762 | return err; |
| 747 | if (nf_nat_initialized(ct, manip)) | ||
| 748 | return -EEXIST; | ||
| 749 | 763 | ||
| 750 | return nf_nat_setup_info(ct, &range, manip); | 764 | return nf_nat_setup_info(ct, &range, manip); |
| 751 | } | 765 | } |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index f072fe803510..108120f216b1 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
| @@ -354,13 +354,16 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
| 354 | 354 | ||
| 355 | skb = nfnetlink_alloc_skb(net, size, queue->peer_portid, | 355 | skb = nfnetlink_alloc_skb(net, size, queue->peer_portid, |
| 356 | GFP_ATOMIC); | 356 | GFP_ATOMIC); |
| 357 | if (!skb) | 357 | if (!skb) { |
| 358 | skb_tx_error(entskb); | ||
| 358 | return NULL; | 359 | return NULL; |
| 360 | } | ||
| 359 | 361 | ||
| 360 | nlh = nlmsg_put(skb, 0, 0, | 362 | nlh = nlmsg_put(skb, 0, 0, |
| 361 | NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET, | 363 | NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET, |
| 362 | sizeof(struct nfgenmsg), 0); | 364 | sizeof(struct nfgenmsg), 0); |
| 363 | if (!nlh) { | 365 | if (!nlh) { |
| 366 | skb_tx_error(entskb); | ||
| 364 | kfree_skb(skb); | 367 | kfree_skb(skb); |
| 365 | return NULL; | 368 | return NULL; |
| 366 | } | 369 | } |
| @@ -488,13 +491,15 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
| 488 | nla->nla_type = NFQA_PAYLOAD; | 491 | nla->nla_type = NFQA_PAYLOAD; |
| 489 | nla->nla_len = nla_attr_size(data_len); | 492 | nla->nla_len = nla_attr_size(data_len); |
| 490 | 493 | ||
| 491 | skb_zerocopy(skb, entskb, data_len, hlen); | 494 | if (skb_zerocopy(skb, entskb, data_len, hlen)) |
| 495 | goto nla_put_failure; | ||
| 492 | } | 496 | } |
| 493 | 497 | ||
| 494 | nlh->nlmsg_len = skb->len; | 498 | nlh->nlmsg_len = skb->len; |
| 495 | return skb; | 499 | return skb; |
| 496 | 500 | ||
| 497 | nla_put_failure: | 501 | nla_put_failure: |
| 502 | skb_tx_error(entskb); | ||
| 498 | kfree_skb(skb); | 503 | kfree_skb(skb); |
| 499 | net_err_ratelimited("nf_queue: error creating packet message\n"); | 504 | net_err_ratelimited("nf_queue: error creating packet message\n"); |
| 500 | return NULL; | 505 | return NULL; |
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index e8254ad2e5a9..425cf39af890 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
| @@ -116,7 +116,7 @@ static void nft_meta_get_eval(const struct nft_expr *expr, | |||
| 116 | skb->sk->sk_socket->file->f_cred->fsgid); | 116 | skb->sk->sk_socket->file->f_cred->fsgid); |
| 117 | read_unlock_bh(&skb->sk->sk_callback_lock); | 117 | read_unlock_bh(&skb->sk->sk_callback_lock); |
| 118 | break; | 118 | break; |
| 119 | #ifdef CONFIG_NET_CLS_ROUTE | 119 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 120 | case NFT_META_RTCLASSID: { | 120 | case NFT_META_RTCLASSID: { |
| 121 | const struct dst_entry *dst = skb_dst(skb); | 121 | const struct dst_entry *dst = skb_dst(skb); |
| 122 | 122 | ||
| @@ -199,7 +199,7 @@ static int nft_meta_init_validate_get(uint32_t key) | |||
| 199 | case NFT_META_OIFTYPE: | 199 | case NFT_META_OIFTYPE: |
| 200 | case NFT_META_SKUID: | 200 | case NFT_META_SKUID: |
| 201 | case NFT_META_SKGID: | 201 | case NFT_META_SKGID: |
| 202 | #ifdef CONFIG_NET_CLS_ROUTE | 202 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 203 | case NFT_META_RTCLASSID: | 203 | case NFT_META_RTCLASSID: |
| 204 | #endif | 204 | #endif |
| 205 | #ifdef CONFIG_NETWORK_SECMARK | 205 | #ifdef CONFIG_NETWORK_SECMARK |
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index a2aeb318678f..85daa84bfdfe 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c | |||
| @@ -135,7 +135,8 @@ nft_payload_select_ops(const struct nft_ctx *ctx, | |||
| 135 | if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data)) | 135 | if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data)) |
| 136 | return ERR_PTR(-EINVAL); | 136 | return ERR_PTR(-EINVAL); |
| 137 | 137 | ||
| 138 | if (len <= 4 && IS_ALIGNED(offset, len) && base != NFT_PAYLOAD_LL_HEADER) | 138 | if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && |
| 139 | base != NFT_PAYLOAD_LL_HEADER) | ||
| 139 | return &nft_payload_fast_ops; | 140 | return &nft_payload_fast_ops; |
| 140 | else | 141 | else |
| 141 | return &nft_payload_ops; | 142 | return &nft_payload_ops; |
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index 8a310f239c93..b718a52a4654 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c | |||
| @@ -21,9 +21,9 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, | |||
| 21 | { | 21 | { |
| 22 | switch (pkt->ops->pf) { | 22 | switch (pkt->ops->pf) { |
| 23 | case NFPROTO_IPV4: | 23 | case NFPROTO_IPV4: |
| 24 | nft_reject_ipv4_eval(expr, data, pkt); | 24 | return nft_reject_ipv4_eval(expr, data, pkt); |
| 25 | case NFPROTO_IPV6: | 25 | case NFPROTO_IPV6: |
| 26 | nft_reject_ipv6_eval(expr, data, pkt); | 26 | return nft_reject_ipv6_eval(expr, data, pkt); |
| 27 | } | 27 | } |
| 28 | } | 28 | } |
| 29 | 29 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index fdf51353cf78..04748ab649c2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1489,8 +1489,8 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, | |||
| 1489 | if (addr->sa_family != AF_NETLINK) | 1489 | if (addr->sa_family != AF_NETLINK) |
| 1490 | return -EINVAL; | 1490 | return -EINVAL; |
| 1491 | 1491 | ||
| 1492 | /* Only superuser is allowed to send multicasts */ | 1492 | if ((nladdr->nl_groups || nladdr->nl_pid) && |
| 1493 | if (nladdr->nl_groups && !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) | 1493 | !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) |
| 1494 | return -EPERM; | 1494 | return -EPERM; |
| 1495 | 1495 | ||
| 1496 | if (!nlk->portid) | 1496 | if (!nlk->portid) |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 46bda010bf11..56db888b1cd5 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
| @@ -301,7 +301,7 @@ static int nci_open_device(struct nci_dev *ndev) | |||
| 301 | rc = __nci_request(ndev, nci_reset_req, 0, | 301 | rc = __nci_request(ndev, nci_reset_req, 0, |
| 302 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); | 302 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); |
| 303 | 303 | ||
| 304 | if (ndev->ops->setup(ndev)) | 304 | if (ndev->ops->setup) |
| 305 | ndev->ops->setup(ndev); | 305 | ndev->ops->setup(ndev); |
| 306 | 306 | ||
| 307 | if (!rc) { | 307 | if (!rc) { |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index e9a48baf8551..270b77dfac30 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -464,7 +464,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
| 464 | } | 464 | } |
| 465 | nla->nla_len = nla_attr_size(skb->len); | 465 | nla->nla_len = nla_attr_size(skb->len); |
| 466 | 466 | ||
| 467 | skb_zerocopy(user_skb, skb, skb->len, hlen); | 467 | err = skb_zerocopy(user_skb, skb, skb->len, hlen); |
| 468 | if (err) | ||
| 469 | goto out; | ||
| 468 | 470 | ||
| 469 | /* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */ | 471 | /* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */ |
| 470 | if (!(dp->user_features & OVS_DP_F_UNALIGNED)) { | 472 | if (!(dp->user_features & OVS_DP_F_UNALIGNED)) { |
| @@ -478,6 +480,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
| 478 | 480 | ||
| 479 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); | 481 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); |
| 480 | out: | 482 | out: |
| 483 | if (err) | ||
| 484 | skb_tx_error(skb); | ||
| 481 | kfree_skb(nskb); | 485 | kfree_skb(nskb); |
| 482 | return err; | 486 | return err; |
| 483 | } | 487 | } |
| @@ -1174,7 +1178,7 @@ static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *in | |||
| 1174 | struct datapath *dp; | 1178 | struct datapath *dp; |
| 1175 | 1179 | ||
| 1176 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); | 1180 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); |
| 1177 | if (!dp) | 1181 | if (IS_ERR(dp)) |
| 1178 | return; | 1182 | return; |
| 1179 | 1183 | ||
| 1180 | WARN(dp->user_features, "Dropping previously announced user features\n"); | 1184 | WARN(dp->user_features, "Dropping previously announced user features\n"); |
| @@ -1762,11 +1766,12 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1762 | int bucket = cb->args[0], skip = cb->args[1]; | 1766 | int bucket = cb->args[0], skip = cb->args[1]; |
| 1763 | int i, j = 0; | 1767 | int i, j = 0; |
| 1764 | 1768 | ||
| 1769 | rcu_read_lock(); | ||
| 1765 | dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); | 1770 | dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); |
| 1766 | if (!dp) | 1771 | if (!dp) { |
| 1772 | rcu_read_unlock(); | ||
| 1767 | return -ENODEV; | 1773 | return -ENODEV; |
| 1768 | 1774 | } | |
| 1769 | rcu_read_lock(); | ||
| 1770 | for (i = bucket; i < DP_VPORT_HASH_BUCKETS; i++) { | 1775 | for (i = bucket; i < DP_VPORT_HASH_BUCKETS; i++) { |
| 1771 | struct vport *vport; | 1776 | struct vport *vport; |
| 1772 | 1777 | ||
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 16f4b46161d4..2998989e76db 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
| @@ -73,6 +73,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb) | |||
| 73 | 73 | ||
| 74 | if ((flow->key.eth.type == htons(ETH_P_IP) || | 74 | if ((flow->key.eth.type == htons(ETH_P_IP) || |
| 75 | flow->key.eth.type == htons(ETH_P_IPV6)) && | 75 | flow->key.eth.type == htons(ETH_P_IPV6)) && |
| 76 | flow->key.ip.frag != OVS_FRAG_TYPE_LATER && | ||
| 76 | flow->key.ip.proto == IPPROTO_TCP && | 77 | flow->key.ip.proto == IPPROTO_TCP && |
| 77 | likely(skb->len >= skb_transport_offset(skb) + sizeof(struct tcphdr))) { | 78 | likely(skb->len >= skb_transport_offset(skb) + sizeof(struct tcphdr))) { |
| 78 | tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb)); | 79 | tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb)); |
| @@ -91,7 +92,7 @@ static void stats_read(struct flow_stats *stats, | |||
| 91 | unsigned long *used, __be16 *tcp_flags) | 92 | unsigned long *used, __be16 *tcp_flags) |
| 92 | { | 93 | { |
| 93 | spin_lock(&stats->lock); | 94 | spin_lock(&stats->lock); |
| 94 | if (time_after(stats->used, *used)) | 95 | if (!*used || time_after(stats->used, *used)) |
| 95 | *used = stats->used; | 96 | *used = stats->used; |
| 96 | *tcp_flags |= stats->tcp_flags; | 97 | *tcp_flags |= stats->tcp_flags; |
| 97 | ovs_stats->n_packets += stats->packet_count; | 98 | ovs_stats->n_packets += stats->packet_count; |
| @@ -102,30 +103,24 @@ static void stats_read(struct flow_stats *stats, | |||
| 102 | void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, | 103 | void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, |
| 103 | unsigned long *used, __be16 *tcp_flags) | 104 | unsigned long *used, __be16 *tcp_flags) |
| 104 | { | 105 | { |
| 105 | int cpu, cur_cpu; | 106 | int cpu; |
| 106 | 107 | ||
| 107 | *used = 0; | 108 | *used = 0; |
| 108 | *tcp_flags = 0; | 109 | *tcp_flags = 0; |
| 109 | memset(ovs_stats, 0, sizeof(*ovs_stats)); | 110 | memset(ovs_stats, 0, sizeof(*ovs_stats)); |
| 110 | 111 | ||
| 112 | local_bh_disable(); | ||
| 111 | if (!flow->stats.is_percpu) { | 113 | if (!flow->stats.is_percpu) { |
| 112 | stats_read(flow->stats.stat, ovs_stats, used, tcp_flags); | 114 | stats_read(flow->stats.stat, ovs_stats, used, tcp_flags); |
| 113 | } else { | 115 | } else { |
| 114 | cur_cpu = get_cpu(); | ||
| 115 | for_each_possible_cpu(cpu) { | 116 | for_each_possible_cpu(cpu) { |
| 116 | struct flow_stats *stats; | 117 | struct flow_stats *stats; |
| 117 | 118 | ||
| 118 | if (cpu == cur_cpu) | ||
| 119 | local_bh_disable(); | ||
| 120 | |||
| 121 | stats = per_cpu_ptr(flow->stats.cpu_stats, cpu); | 119 | stats = per_cpu_ptr(flow->stats.cpu_stats, cpu); |
| 122 | stats_read(stats, ovs_stats, used, tcp_flags); | 120 | stats_read(stats, ovs_stats, used, tcp_flags); |
| 123 | |||
| 124 | if (cpu == cur_cpu) | ||
| 125 | local_bh_enable(); | ||
| 126 | } | 121 | } |
| 127 | put_cpu(); | ||
| 128 | } | 122 | } |
| 123 | local_bh_enable(); | ||
| 129 | } | 124 | } |
| 130 | 125 | ||
| 131 | static void stats_reset(struct flow_stats *stats) | 126 | static void stats_reset(struct flow_stats *stats) |
| @@ -140,25 +135,17 @@ static void stats_reset(struct flow_stats *stats) | |||
| 140 | 135 | ||
| 141 | void ovs_flow_stats_clear(struct sw_flow *flow) | 136 | void ovs_flow_stats_clear(struct sw_flow *flow) |
| 142 | { | 137 | { |
| 143 | int cpu, cur_cpu; | 138 | int cpu; |
| 144 | 139 | ||
| 140 | local_bh_disable(); | ||
| 145 | if (!flow->stats.is_percpu) { | 141 | if (!flow->stats.is_percpu) { |
| 146 | stats_reset(flow->stats.stat); | 142 | stats_reset(flow->stats.stat); |
| 147 | } else { | 143 | } else { |
| 148 | cur_cpu = get_cpu(); | ||
| 149 | |||
| 150 | for_each_possible_cpu(cpu) { | 144 | for_each_possible_cpu(cpu) { |
| 151 | |||
| 152 | if (cpu == cur_cpu) | ||
| 153 | local_bh_disable(); | ||
| 154 | |||
| 155 | stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu)); | 145 | stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu)); |
| 156 | |||
| 157 | if (cpu == cur_cpu) | ||
| 158 | local_bh_enable(); | ||
| 159 | } | 146 | } |
| 160 | put_cpu(); | ||
| 161 | } | 147 | } |
| 148 | local_bh_enable(); | ||
| 162 | } | 149 | } |
| 163 | 150 | ||
| 164 | static int check_header(struct sk_buff *skb, int len) | 151 | static int check_header(struct sk_buff *skb, int len) |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 1313145e3b86..a07d55e75698 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -273,11 +273,12 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) | |||
| 273 | 273 | ||
| 274 | void qdisc_list_add(struct Qdisc *q) | 274 | void qdisc_list_add(struct Qdisc *q) |
| 275 | { | 275 | { |
| 276 | struct Qdisc *root = qdisc_dev(q)->qdisc; | 276 | if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) { |
| 277 | struct Qdisc *root = qdisc_dev(q)->qdisc; | ||
| 277 | 278 | ||
| 278 | WARN_ON_ONCE(root == &noop_qdisc); | 279 | WARN_ON_ONCE(root == &noop_qdisc); |
| 279 | if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) | ||
| 280 | list_add_tail(&q->list, &root->list); | 280 | list_add_tail(&q->list, &root->list); |
| 281 | } | ||
| 281 | } | 282 | } |
| 282 | EXPORT_SYMBOL(qdisc_list_add); | 283 | EXPORT_SYMBOL(qdisc_list_add); |
| 283 | 284 | ||
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 08ef7a42c0e4..21e251766eb1 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
| @@ -601,6 +601,7 @@ static int fq_resize(struct Qdisc *sch, u32 log) | |||
| 601 | { | 601 | { |
| 602 | struct fq_sched_data *q = qdisc_priv(sch); | 602 | struct fq_sched_data *q = qdisc_priv(sch); |
| 603 | struct rb_root *array; | 603 | struct rb_root *array; |
| 604 | void *old_fq_root; | ||
| 604 | u32 idx; | 605 | u32 idx; |
| 605 | 606 | ||
| 606 | if (q->fq_root && log == q->fq_trees_log) | 607 | if (q->fq_root && log == q->fq_trees_log) |
| @@ -615,13 +616,19 @@ static int fq_resize(struct Qdisc *sch, u32 log) | |||
| 615 | for (idx = 0; idx < (1U << log); idx++) | 616 | for (idx = 0; idx < (1U << log); idx++) |
| 616 | array[idx] = RB_ROOT; | 617 | array[idx] = RB_ROOT; |
| 617 | 618 | ||
| 618 | if (q->fq_root) { | 619 | sch_tree_lock(sch); |
| 619 | fq_rehash(q, q->fq_root, q->fq_trees_log, array, log); | 620 | |
| 620 | fq_free(q->fq_root); | 621 | old_fq_root = q->fq_root; |
| 621 | } | 622 | if (old_fq_root) |
| 623 | fq_rehash(q, old_fq_root, q->fq_trees_log, array, log); | ||
| 624 | |||
| 622 | q->fq_root = array; | 625 | q->fq_root = array; |
| 623 | q->fq_trees_log = log; | 626 | q->fq_trees_log = log; |
| 624 | 627 | ||
| 628 | sch_tree_unlock(sch); | ||
| 629 | |||
| 630 | fq_free(old_fq_root); | ||
| 631 | |||
| 625 | return 0; | 632 | return 0; |
| 626 | } | 633 | } |
| 627 | 634 | ||
| @@ -697,9 +704,11 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 697 | q->flow_refill_delay = usecs_to_jiffies(usecs_delay); | 704 | q->flow_refill_delay = usecs_to_jiffies(usecs_delay); |
| 698 | } | 705 | } |
| 699 | 706 | ||
| 700 | if (!err) | 707 | if (!err) { |
| 708 | sch_tree_unlock(sch); | ||
| 701 | err = fq_resize(sch, fq_log); | 709 | err = fq_resize(sch, fq_log); |
| 702 | 710 | sch_tree_lock(sch); | |
| 711 | } | ||
| 703 | while (sch->q.qlen > sch->limit) { | 712 | while (sch->q.qlen > sch->limit) { |
| 704 | struct sk_buff *skb = fq_dequeue(sch); | 713 | struct sk_buff *skb = fq_dequeue(sch); |
| 705 | 714 | ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 1cb413fead89..4f505a006896 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
| @@ -334,18 +334,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 334 | qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, | 334 | qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, |
| 335 | tb[TCA_TBF_PTAB])); | 335 | tb[TCA_TBF_PTAB])); |
| 336 | 336 | ||
| 337 | if (q->qdisc != &noop_qdisc) { | ||
| 338 | err = fifo_set_limit(q->qdisc, qopt->limit); | ||
| 339 | if (err) | ||
| 340 | goto done; | ||
| 341 | } else if (qopt->limit > 0) { | ||
| 342 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); | ||
| 343 | if (IS_ERR(child)) { | ||
| 344 | err = PTR_ERR(child); | ||
| 345 | goto done; | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); | 337 | buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); |
| 350 | mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); | 338 | mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); |
| 351 | 339 | ||
| @@ -390,6 +378,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 390 | goto done; | 378 | goto done; |
| 391 | } | 379 | } |
| 392 | 380 | ||
| 381 | if (q->qdisc != &noop_qdisc) { | ||
| 382 | err = fifo_set_limit(q->qdisc, qopt->limit); | ||
| 383 | if (err) | ||
| 384 | goto done; | ||
| 385 | } else if (qopt->limit > 0) { | ||
| 386 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); | ||
| 387 | if (IS_ERR(child)) { | ||
| 388 | err = PTR_ERR(child); | ||
| 389 | goto done; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | sch_tree_lock(sch); | 393 | sch_tree_lock(sch); |
| 394 | if (child) { | 394 | if (child) { |
| 395 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); | 395 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f558433537b8..ee13d28d39d1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -1239,78 +1239,107 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 1239 | } | 1239 | } |
| 1240 | 1240 | ||
| 1241 | /* Update the retran path for sending a retransmitted packet. | 1241 | /* Update the retran path for sending a retransmitted packet. |
| 1242 | * Round-robin through the active transports, else round-robin | 1242 | * See also RFC4960, 6.4. Multi-Homed SCTP Endpoints: |
| 1243 | * through the inactive transports as this is the next best thing | 1243 | * |
| 1244 | * we can try. | 1244 | * When there is outbound data to send and the primary path |
| 1245 | * becomes inactive (e.g., due to failures), or where the | ||
| 1246 | * SCTP user explicitly requests to send data to an | ||
| 1247 | * inactive destination transport address, before reporting | ||
| 1248 | * an error to its ULP, the SCTP endpoint should try to send | ||
| 1249 | * the data to an alternate active destination transport | ||
| 1250 | * address if one exists. | ||
| 1251 | * | ||
| 1252 | * When retransmitting data that timed out, if the endpoint | ||
| 1253 | * is multihomed, it should consider each source-destination | ||
| 1254 | * address pair in its retransmission selection policy. | ||
| 1255 | * When retransmitting timed-out data, the endpoint should | ||
| 1256 | * attempt to pick the most divergent source-destination | ||
| 1257 | * pair from the original source-destination pair to which | ||
| 1258 | * the packet was transmitted. | ||
| 1259 | * | ||
| 1260 | * Note: Rules for picking the most divergent source-destination | ||
| 1261 | * pair are an implementation decision and are not specified | ||
| 1262 | * within this document. | ||
| 1263 | * | ||
| 1264 | * Our basic strategy is to round-robin transports in priorities | ||
| 1265 | * according to sctp_state_prio_map[] e.g., if no such | ||
| 1266 | * transport with state SCTP_ACTIVE exists, round-robin through | ||
| 1267 | * SCTP_UNKNOWN, etc. You get the picture. | ||
| 1245 | */ | 1268 | */ |
| 1246 | void sctp_assoc_update_retran_path(struct sctp_association *asoc) | 1269 | static const u8 sctp_trans_state_to_prio_map[] = { |
| 1270 | [SCTP_ACTIVE] = 3, /* best case */ | ||
| 1271 | [SCTP_UNKNOWN] = 2, | ||
| 1272 | [SCTP_PF] = 1, | ||
| 1273 | [SCTP_INACTIVE] = 0, /* worst case */ | ||
| 1274 | }; | ||
| 1275 | |||
| 1276 | static u8 sctp_trans_score(const struct sctp_transport *trans) | ||
| 1247 | { | 1277 | { |
| 1248 | struct sctp_transport *t, *next; | 1278 | return sctp_trans_state_to_prio_map[trans->state]; |
| 1249 | struct list_head *head = &asoc->peer.transport_addr_list; | 1279 | } |
| 1250 | struct list_head *pos; | ||
| 1251 | 1280 | ||
| 1252 | if (asoc->peer.transport_count == 1) | 1281 | static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr, |
| 1253 | return; | 1282 | struct sctp_transport *best) |
| 1283 | { | ||
| 1284 | if (best == NULL) | ||
| 1285 | return curr; | ||
| 1254 | 1286 | ||
| 1255 | /* Find the next transport in a round-robin fashion. */ | 1287 | return sctp_trans_score(curr) > sctp_trans_score(best) ? curr : best; |
| 1256 | t = asoc->peer.retran_path; | 1288 | } |
| 1257 | pos = &t->transports; | ||
| 1258 | next = NULL; | ||
| 1259 | 1289 | ||
| 1260 | while (1) { | 1290 | void sctp_assoc_update_retran_path(struct sctp_association *asoc) |
| 1261 | /* Skip the head. */ | 1291 | { |
| 1262 | if (pos->next == head) | 1292 | struct sctp_transport *trans = asoc->peer.retran_path; |
| 1263 | pos = head->next; | 1293 | struct sctp_transport *trans_next = NULL; |
| 1264 | else | ||
| 1265 | pos = pos->next; | ||
| 1266 | 1294 | ||
| 1267 | t = list_entry(pos, struct sctp_transport, transports); | 1295 | /* We're done as we only have the one and only path. */ |
| 1296 | if (asoc->peer.transport_count == 1) | ||
| 1297 | return; | ||
| 1298 | /* If active_path and retran_path are the same and active, | ||
| 1299 | * then this is the only active path. Use it. | ||
| 1300 | */ | ||
| 1301 | if (asoc->peer.active_path == asoc->peer.retran_path && | ||
| 1302 | asoc->peer.active_path->state == SCTP_ACTIVE) | ||
| 1303 | return; | ||
| 1268 | 1304 | ||
| 1269 | /* We have exhausted the list, but didn't find any | 1305 | /* Iterate from retran_path's successor back to retran_path. */ |
| 1270 | * other active transports. If so, use the next | 1306 | for (trans = list_next_entry(trans, transports); 1; |
| 1271 | * transport. | 1307 | trans = list_next_entry(trans, transports)) { |
| 1272 | */ | 1308 | /* Manually skip the head element. */ |
| 1273 | if (t == asoc->peer.retran_path) { | 1309 | if (&trans->transports == &asoc->peer.transport_addr_list) |
| 1274 | t = next; | 1310 | continue; |
| 1311 | if (trans->state == SCTP_UNCONFIRMED) | ||
| 1312 | continue; | ||
| 1313 | trans_next = sctp_trans_elect_best(trans, trans_next); | ||
| 1314 | /* Active is good enough for immediate return. */ | ||
| 1315 | if (trans_next->state == SCTP_ACTIVE) | ||
| 1275 | break; | 1316 | break; |
| 1276 | } | 1317 | /* We've reached the end, time to update path. */ |
| 1277 | 1318 | if (trans == asoc->peer.retran_path) | |
| 1278 | /* Try to find an active transport. */ | ||
| 1279 | |||
| 1280 | if ((t->state == SCTP_ACTIVE) || | ||
| 1281 | (t->state == SCTP_UNKNOWN)) { | ||
| 1282 | break; | 1319 | break; |
| 1283 | } else { | ||
| 1284 | /* Keep track of the next transport in case | ||
| 1285 | * we don't find any active transport. | ||
| 1286 | */ | ||
| 1287 | if (t->state != SCTP_UNCONFIRMED && !next) | ||
| 1288 | next = t; | ||
| 1289 | } | ||
| 1290 | } | 1320 | } |
| 1291 | 1321 | ||
| 1292 | if (t) | 1322 | if (trans_next != NULL) |
| 1293 | asoc->peer.retran_path = t; | 1323 | asoc->peer.retran_path = trans_next; |
| 1294 | else | ||
| 1295 | t = asoc->peer.retran_path; | ||
| 1296 | 1324 | ||
| 1297 | pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc, | 1325 | pr_debug("%s: association:%p updated new path to addr:%pISpc\n", |
| 1298 | &t->ipaddr.sa); | 1326 | __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); |
| 1299 | } | 1327 | } |
| 1300 | 1328 | ||
| 1301 | /* Choose the transport for sending retransmit packet. */ | 1329 | struct sctp_transport * |
| 1302 | struct sctp_transport *sctp_assoc_choose_alter_transport( | 1330 | sctp_assoc_choose_alter_transport(struct sctp_association *asoc, |
| 1303 | struct sctp_association *asoc, struct sctp_transport *last_sent_to) | 1331 | struct sctp_transport *last_sent_to) |
| 1304 | { | 1332 | { |
| 1305 | /* If this is the first time packet is sent, use the active path, | 1333 | /* If this is the first time packet is sent, use the active path, |
| 1306 | * else use the retran path. If the last packet was sent over the | 1334 | * else use the retran path. If the last packet was sent over the |
| 1307 | * retran path, update the retran path and use it. | 1335 | * retran path, update the retran path and use it. |
| 1308 | */ | 1336 | */ |
| 1309 | if (!last_sent_to) | 1337 | if (last_sent_to == NULL) { |
| 1310 | return asoc->peer.active_path; | 1338 | return asoc->peer.active_path; |
| 1311 | else { | 1339 | } else { |
| 1312 | if (last_sent_to == asoc->peer.retran_path) | 1340 | if (last_sent_to == asoc->peer.retran_path) |
| 1313 | sctp_assoc_update_retran_path(asoc); | 1341 | sctp_assoc_update_retran_path(asoc); |
| 1342 | |||
| 1314 | return asoc->peer.retran_path; | 1343 | return asoc->peer.retran_path; |
| 1315 | } | 1344 | } |
| 1316 | } | 1345 | } |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 632090b961c3..3a1767ef3201 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -1421,8 +1421,8 @@ static void sctp_chunk_destroy(struct sctp_chunk *chunk) | |||
| 1421 | BUG_ON(!list_empty(&chunk->list)); | 1421 | BUG_ON(!list_empty(&chunk->list)); |
| 1422 | list_del_init(&chunk->transmitted_list); | 1422 | list_del_init(&chunk->transmitted_list); |
| 1423 | 1423 | ||
| 1424 | /* Free the chunk skb data and the SCTP_chunk stub itself. */ | 1424 | consume_skb(chunk->skb); |
| 1425 | dev_kfree_skb(chunk->skb); | 1425 | consume_skb(chunk->auth_chunk); |
| 1426 | 1426 | ||
| 1427 | SCTP_DBG_OBJCNT_DEC(chunk); | 1427 | SCTP_DBG_OBJCNT_DEC(chunk); |
| 1428 | kmem_cache_free(sctp_chunk_cachep, chunk); | 1428 | kmem_cache_free(sctp_chunk_cachep, chunk); |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bd859154000e..5d6883ff00c3 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -495,11 +495,12 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, | |||
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | /* If the transport error count is greater than the pf_retrans | 497 | /* If the transport error count is greater than the pf_retrans |
| 498 | * threshold, and less than pathmaxrtx, then mark this transport | 498 | * threshold, and less than pathmaxrtx, and if the current state |
| 499 | * as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1, | 499 | * is not SCTP_UNCONFIRMED, then mark this transport as Partially |
| 500 | * point 1 | 500 | * Failed, see SCTP Quick Failover Draft, section 5.1 |
| 501 | */ | 501 | */ |
| 502 | if ((transport->state != SCTP_PF) && | 502 | if ((transport->state != SCTP_PF) && |
| 503 | (transport->state != SCTP_UNCONFIRMED) && | ||
| 503 | (asoc->pf_retrans < transport->pathmaxrxt) && | 504 | (asoc->pf_retrans < transport->pathmaxrxt) && |
| 504 | (transport->error_count > asoc->pf_retrans)) { | 505 | (transport->error_count > asoc->pf_retrans)) { |
| 505 | 506 | ||
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 591b44d3b7de..01e002430c85 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -758,6 +758,12 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, | |||
| 758 | struct sctp_chunk auth; | 758 | struct sctp_chunk auth; |
| 759 | sctp_ierror_t ret; | 759 | sctp_ierror_t ret; |
| 760 | 760 | ||
| 761 | /* Make sure that we and the peer are AUTH capable */ | ||
| 762 | if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { | ||
| 763 | sctp_association_free(new_asoc); | ||
| 764 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
| 765 | } | ||
| 766 | |||
| 761 | /* set-up our fake chunk so that we can process it */ | 767 | /* set-up our fake chunk so that we can process it */ |
| 762 | auth.skb = chunk->auth_chunk; | 768 | auth.skb = chunk->auth_chunk; |
| 763 | auth.asoc = chunk->asoc; | 769 | auth.asoc = chunk->asoc; |
| @@ -768,10 +774,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, | |||
| 768 | auth.transport = chunk->transport; | 774 | auth.transport = chunk->transport; |
| 769 | 775 | ||
| 770 | ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); | 776 | ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); |
| 771 | |||
| 772 | /* We can now safely free the auth_chunk clone */ | ||
| 773 | kfree_skb(chunk->auth_chunk); | ||
| 774 | |||
| 775 | if (ret != SCTP_IERROR_NO_ERROR) { | 777 | if (ret != SCTP_IERROR_NO_ERROR) { |
| 776 | sctp_association_free(new_asoc); | 778 | sctp_association_free(new_asoc); |
| 777 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | 779 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
diff --git a/net/socket.c b/net/socket.c index 879933aaed4c..a19ae1968d37 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -450,16 +450,17 @@ EXPORT_SYMBOL(sockfd_lookup); | |||
| 450 | 450 | ||
| 451 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) | 451 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) |
| 452 | { | 452 | { |
| 453 | struct file *file; | 453 | struct fd f = fdget(fd); |
| 454 | struct socket *sock; | 454 | struct socket *sock; |
| 455 | 455 | ||
| 456 | *err = -EBADF; | 456 | *err = -EBADF; |
| 457 | file = fget_light(fd, fput_needed); | 457 | if (f.file) { |
| 458 | if (file) { | 458 | sock = sock_from_file(f.file, err); |
| 459 | sock = sock_from_file(file, err); | 459 | if (likely(sock)) { |
| 460 | if (sock) | 460 | *fput_needed = f.flags; |
| 461 | return sock; | 461 | return sock; |
| 462 | fput_light(file, *fput_needed); | 462 | } |
| 463 | fdput(f); | ||
| 463 | } | 464 | } |
| 464 | return NULL; | 465 | return NULL; |
| 465 | } | 466 | } |
| @@ -1985,6 +1986,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, | |||
| 1985 | { | 1986 | { |
| 1986 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) | 1987 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) |
| 1987 | return -EFAULT; | 1988 | return -EFAULT; |
| 1989 | |||
| 1990 | if (kmsg->msg_namelen < 0) | ||
| 1991 | return -EINVAL; | ||
| 1992 | |||
| 1988 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) | 1993 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) |
| 1989 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); | 1994 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
| 1990 | return 0; | 1995 | return 0; |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a38c89969c68..574b86193b15 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -610,8 +610,13 @@ static struct notifier_block notifier = { | |||
| 610 | 610 | ||
| 611 | int tipc_bearer_setup(void) | 611 | int tipc_bearer_setup(void) |
| 612 | { | 612 | { |
| 613 | int err; | ||
| 614 | |||
| 615 | err = register_netdevice_notifier(¬ifier); | ||
| 616 | if (err) | ||
| 617 | return err; | ||
| 613 | dev_add_pack(&tipc_packet_type); | 618 | dev_add_pack(&tipc_packet_type); |
| 614 | return register_netdevice_notifier(¬ifier); | 619 | return 0; |
| 615 | } | 620 | } |
| 616 | 621 | ||
| 617 | void tipc_bearer_cleanup(void) | 622 | void tipc_bearer_cleanup(void) |
diff --git a/net/tipc/config.c b/net/tipc/config.c index c301a9a592d8..e6d721692ae0 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
| @@ -181,7 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
| 181 | if (tipc_own_addr) | 181 | if (tipc_own_addr) |
| 182 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 182 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 183 | " (cannot change node address once assigned)"); | 183 | " (cannot change node address once assigned)"); |
| 184 | tipc_core_start_net(addr); | 184 | tipc_net_start(addr); |
| 185 | return tipc_cfg_reply_none(); | 185 | return tipc_cfg_reply_none(); |
| 186 | } | 186 | } |
| 187 | 187 | ||
| @@ -376,7 +376,6 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, | |||
| 376 | struct tipc_cfg_msg_hdr *req_hdr; | 376 | struct tipc_cfg_msg_hdr *req_hdr; |
| 377 | struct tipc_cfg_msg_hdr *rep_hdr; | 377 | struct tipc_cfg_msg_hdr *rep_hdr; |
| 378 | struct sk_buff *rep_buf; | 378 | struct sk_buff *rep_buf; |
| 379 | int ret; | ||
| 380 | 379 | ||
| 381 | /* Validate configuration message header (ignore invalid message) */ | 380 | /* Validate configuration message header (ignore invalid message) */ |
| 382 | req_hdr = (struct tipc_cfg_msg_hdr *)buf; | 381 | req_hdr = (struct tipc_cfg_msg_hdr *)buf; |
| @@ -398,12 +397,8 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, | |||
| 398 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); | 397 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); |
| 399 | rep_hdr->tcm_len = htonl(rep_buf->len); | 398 | rep_hdr->tcm_len = htonl(rep_buf->len); |
| 400 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); | 399 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); |
| 401 | 400 | tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, | |
| 402 | ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, | 401 | rep_buf->len); |
| 403 | rep_buf->len); | ||
| 404 | if (ret < 0) | ||
| 405 | pr_err("Sending cfg reply message failed, no memory\n"); | ||
| 406 | |||
| 407 | kfree_skb(rep_buf); | 402 | kfree_skb(rep_buf); |
| 408 | } | 403 | } |
| 409 | } | 404 | } |
diff --git a/net/tipc/core.c b/net/tipc/core.c index f9e88d8b04ca..80c20647b3d2 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
| @@ -77,37 +77,13 @@ struct sk_buff *tipc_buf_acquire(u32 size) | |||
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | /** | 79 | /** |
| 80 | * tipc_core_stop_net - shut down TIPC networking sub-systems | ||
| 81 | */ | ||
| 82 | static void tipc_core_stop_net(void) | ||
| 83 | { | ||
| 84 | tipc_net_stop(); | ||
| 85 | tipc_bearer_cleanup(); | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * start_net - start TIPC networking sub-systems | ||
| 90 | */ | ||
| 91 | int tipc_core_start_net(unsigned long addr) | ||
| 92 | { | ||
| 93 | int res; | ||
| 94 | |||
| 95 | tipc_net_start(addr); | ||
| 96 | res = tipc_bearer_setup(); | ||
| 97 | if (res < 0) | ||
| 98 | goto err; | ||
| 99 | return res; | ||
| 100 | |||
| 101 | err: | ||
| 102 | tipc_core_stop_net(); | ||
| 103 | return res; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode | 80 | * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode |
| 108 | */ | 81 | */ |
| 109 | static void tipc_core_stop(void) | 82 | static void tipc_core_stop(void) |
| 110 | { | 83 | { |
| 84 | tipc_handler_stop(); | ||
| 85 | tipc_net_stop(); | ||
| 86 | tipc_bearer_cleanup(); | ||
| 111 | tipc_netlink_stop(); | 87 | tipc_netlink_stop(); |
| 112 | tipc_cfg_stop(); | 88 | tipc_cfg_stop(); |
| 113 | tipc_subscr_stop(); | 89 | tipc_subscr_stop(); |
| @@ -122,30 +98,65 @@ static void tipc_core_stop(void) | |||
| 122 | */ | 98 | */ |
| 123 | static int tipc_core_start(void) | 99 | static int tipc_core_start(void) |
| 124 | { | 100 | { |
| 125 | int res; | 101 | int err; |
| 126 | 102 | ||
| 127 | get_random_bytes(&tipc_random, sizeof(tipc_random)); | 103 | get_random_bytes(&tipc_random, sizeof(tipc_random)); |
| 128 | 104 | ||
| 129 | res = tipc_handler_start(); | 105 | err = tipc_handler_start(); |
| 130 | if (!res) | 106 | if (err) |
| 131 | res = tipc_ref_table_init(tipc_max_ports, tipc_random); | 107 | goto out_handler; |
| 132 | if (!res) | 108 | |
| 133 | res = tipc_nametbl_init(); | 109 | err = tipc_ref_table_init(tipc_max_ports, tipc_random); |
| 134 | if (!res) | 110 | if (err) |
| 135 | res = tipc_netlink_start(); | 111 | goto out_reftbl; |
| 136 | if (!res) | 112 | |
| 137 | res = tipc_socket_init(); | 113 | err = tipc_nametbl_init(); |
| 138 | if (!res) | 114 | if (err) |
| 139 | res = tipc_register_sysctl(); | 115 | goto out_nametbl; |
| 140 | if (!res) | 116 | |
| 141 | res = tipc_subscr_start(); | 117 | err = tipc_netlink_start(); |
| 142 | if (!res) | 118 | if (err) |
| 143 | res = tipc_cfg_init(); | 119 | goto out_netlink; |
| 144 | if (res) { | 120 | |
| 145 | tipc_handler_stop(); | 121 | err = tipc_socket_init(); |
| 146 | tipc_core_stop(); | 122 | if (err) |
| 147 | } | 123 | goto out_socket; |
| 148 | return res; | 124 | |
| 125 | err = tipc_register_sysctl(); | ||
| 126 | if (err) | ||
| 127 | goto out_sysctl; | ||
| 128 | |||
| 129 | err = tipc_subscr_start(); | ||
| 130 | if (err) | ||
| 131 | goto out_subscr; | ||
| 132 | |||
| 133 | err = tipc_cfg_init(); | ||
| 134 | if (err) | ||
| 135 | goto out_cfg; | ||
| 136 | |||
| 137 | err = tipc_bearer_setup(); | ||
| 138 | if (err) | ||
| 139 | goto out_bearer; | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | out_bearer: | ||
| 143 | tipc_cfg_stop(); | ||
| 144 | out_cfg: | ||
| 145 | tipc_subscr_stop(); | ||
| 146 | out_subscr: | ||
| 147 | tipc_unregister_sysctl(); | ||
| 148 | out_sysctl: | ||
| 149 | tipc_socket_stop(); | ||
| 150 | out_socket: | ||
| 151 | tipc_netlink_stop(); | ||
| 152 | out_netlink: | ||
| 153 | tipc_nametbl_stop(); | ||
| 154 | out_nametbl: | ||
| 155 | tipc_ref_table_stop(); | ||
| 156 | out_reftbl: | ||
| 157 | tipc_handler_stop(); | ||
| 158 | out_handler: | ||
| 159 | return err; | ||
| 149 | } | 160 | } |
| 150 | 161 | ||
| 151 | static int __init tipc_init(void) | 162 | static int __init tipc_init(void) |
| @@ -174,8 +185,6 @@ static int __init tipc_init(void) | |||
| 174 | 185 | ||
| 175 | static void __exit tipc_exit(void) | 186 | static void __exit tipc_exit(void) |
| 176 | { | 187 | { |
| 177 | tipc_handler_stop(); | ||
| 178 | tipc_core_stop_net(); | ||
| 179 | tipc_core_stop(); | 188 | tipc_core_stop(); |
| 180 | pr_info("Deactivated\n"); | 189 | pr_info("Deactivated\n"); |
| 181 | } | 190 | } |
diff --git a/net/tipc/core.h b/net/tipc/core.h index 5569d96b4da3..4dfe137587bb 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
| @@ -90,7 +90,6 @@ extern int tipc_random __read_mostly; | |||
| 90 | /* | 90 | /* |
| 91 | * Routines available to privileged subsystems | 91 | * Routines available to privileged subsystems |
| 92 | */ | 92 | */ |
| 93 | int tipc_core_start_net(unsigned long); | ||
| 94 | int tipc_handler_start(void); | 93 | int tipc_handler_start(void); |
| 95 | void tipc_handler_stop(void); | 94 | void tipc_handler_stop(void); |
| 96 | int tipc_netlink_start(void); | 95 | int tipc_netlink_start(void); |
diff --git a/net/tipc/handler.c b/net/tipc/handler.c index e4bc8a296744..1fabf160501f 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c | |||
| @@ -58,7 +58,6 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument) | |||
| 58 | 58 | ||
| 59 | spin_lock_bh(&qitem_lock); | 59 | spin_lock_bh(&qitem_lock); |
| 60 | if (!handler_enabled) { | 60 | if (!handler_enabled) { |
| 61 | pr_err("Signal request ignored by handler\n"); | ||
| 62 | spin_unlock_bh(&qitem_lock); | 61 | spin_unlock_bh(&qitem_lock); |
| 63 | return -ENOPROTOOPT; | 62 | return -ENOPROTOOPT; |
| 64 | } | 63 | } |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 92a1533af4e0..042e8e3cabc0 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
| @@ -941,20 +941,48 @@ int tipc_nametbl_init(void) | |||
| 941 | return 0; | 941 | return 0; |
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | void tipc_nametbl_stop(void) | 944 | /** |
| 945 | * tipc_purge_publications - remove all publications for a given type | ||
| 946 | * | ||
| 947 | * tipc_nametbl_lock must be held when calling this function | ||
| 948 | */ | ||
| 949 | static void tipc_purge_publications(struct name_seq *seq) | ||
| 945 | { | 950 | { |
| 946 | u32 i; | 951 | struct publication *publ, *safe; |
| 952 | struct sub_seq *sseq; | ||
| 953 | struct name_info *info; | ||
| 947 | 954 | ||
| 948 | if (!table.types) | 955 | if (!seq->sseqs) { |
| 956 | nameseq_delete_empty(seq); | ||
| 949 | return; | 957 | return; |
| 958 | } | ||
| 959 | sseq = seq->sseqs; | ||
| 960 | info = sseq->info; | ||
| 961 | list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) { | ||
| 962 | tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, | ||
| 963 | publ->ref, publ->key); | ||
| 964 | } | ||
| 965 | } | ||
| 966 | |||
| 967 | void tipc_nametbl_stop(void) | ||
| 968 | { | ||
| 969 | u32 i; | ||
| 970 | struct name_seq *seq; | ||
| 971 | struct hlist_head *seq_head; | ||
| 972 | struct hlist_node *safe; | ||
| 950 | 973 | ||
| 951 | /* Verify name table is empty, then release it */ | 974 | /* Verify name table is empty and purge any lingering |
| 975 | * publications, then release the name table | ||
| 976 | */ | ||
| 952 | write_lock_bh(&tipc_nametbl_lock); | 977 | write_lock_bh(&tipc_nametbl_lock); |
| 953 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { | 978 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
| 954 | if (hlist_empty(&table.types[i])) | 979 | if (hlist_empty(&table.types[i])) |
| 955 | continue; | 980 | continue; |
| 956 | pr_err("nametbl_stop(): orphaned hash chain detected\n"); | 981 | seq_head = &table.types[i]; |
| 957 | break; | 982 | hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { |
| 983 | tipc_purge_publications(seq); | ||
| 984 | } | ||
| 985 | continue; | ||
| 958 | } | 986 | } |
| 959 | kfree(table.types); | 987 | kfree(table.types); |
| 960 | table.types = NULL; | 988 | table.types = NULL; |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 9f72a6376362..3aaf73de9e2d 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
| @@ -83,8 +83,6 @@ static struct genl_ops tipc_genl_ops[] = { | |||
| 83 | }, | 83 | }, |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | static int tipc_genl_family_registered; | ||
| 87 | |||
| 88 | int tipc_netlink_start(void) | 86 | int tipc_netlink_start(void) |
| 89 | { | 87 | { |
| 90 | int res; | 88 | int res; |
| @@ -94,16 +92,10 @@ int tipc_netlink_start(void) | |||
| 94 | pr_err("Failed to register netlink interface\n"); | 92 | pr_err("Failed to register netlink interface\n"); |
| 95 | return res; | 93 | return res; |
| 96 | } | 94 | } |
| 97 | |||
| 98 | tipc_genl_family_registered = 1; | ||
| 99 | return 0; | 95 | return 0; |
| 100 | } | 96 | } |
| 101 | 97 | ||
| 102 | void tipc_netlink_stop(void) | 98 | void tipc_netlink_stop(void) |
| 103 | { | 99 | { |
| 104 | if (!tipc_genl_family_registered) | ||
| 105 | return; | ||
| 106 | |||
| 107 | genl_unregister_family(&tipc_genl_family); | 100 | genl_unregister_family(&tipc_genl_family); |
| 108 | tipc_genl_family_registered = 0; | ||
| 109 | } | 101 | } |
diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 2a2a938dc22c..de3d593e2fee 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c | |||
| @@ -126,9 +126,6 @@ int tipc_ref_table_init(u32 requested_size, u32 start) | |||
| 126 | */ | 126 | */ |
| 127 | void tipc_ref_table_stop(void) | 127 | void tipc_ref_table_stop(void) |
| 128 | { | 128 | { |
| 129 | if (!tipc_ref_table.entries) | ||
| 130 | return; | ||
| 131 | |||
| 132 | vfree(tipc_ref_table.entries); | 129 | vfree(tipc_ref_table.entries); |
| 133 | tipc_ref_table.entries = NULL; | 130 | tipc_ref_table.entries = NULL; |
| 134 | } | 131 | } |
diff --git a/net/tipc/server.c b/net/tipc/server.c index b635ca347a87..646a930eefbf 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
| @@ -87,7 +87,6 @@ static void tipc_clean_outqueues(struct tipc_conn *con); | |||
| 87 | static void tipc_conn_kref_release(struct kref *kref) | 87 | static void tipc_conn_kref_release(struct kref *kref) |
| 88 | { | 88 | { |
| 89 | struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); | 89 | struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); |
| 90 | struct tipc_server *s = con->server; | ||
| 91 | 90 | ||
| 92 | if (con->sock) { | 91 | if (con->sock) { |
| 93 | tipc_sock_release_local(con->sock); | 92 | tipc_sock_release_local(con->sock); |
| @@ -95,10 +94,6 @@ static void tipc_conn_kref_release(struct kref *kref) | |||
| 95 | } | 94 | } |
| 96 | 95 | ||
| 97 | tipc_clean_outqueues(con); | 96 | tipc_clean_outqueues(con); |
| 98 | |||
| 99 | if (con->conid) | ||
| 100 | s->tipc_conn_shutdown(con->conid, con->usr_data); | ||
| 101 | |||
| 102 | kfree(con); | 97 | kfree(con); |
| 103 | } | 98 | } |
| 104 | 99 | ||
| @@ -181,6 +176,9 @@ static void tipc_close_conn(struct tipc_conn *con) | |||
| 181 | struct tipc_server *s = con->server; | 176 | struct tipc_server *s = con->server; |
| 182 | 177 | ||
| 183 | if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { | 178 | if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { |
| 179 | if (con->conid) | ||
| 180 | s->tipc_conn_shutdown(con->conid, con->usr_data); | ||
| 181 | |||
| 184 | spin_lock_bh(&s->idr_lock); | 182 | spin_lock_bh(&s->idr_lock); |
| 185 | idr_remove(&s->conn_idr, con->conid); | 183 | idr_remove(&s->conn_idr, con->conid); |
| 186 | s->idr_in_use--; | 184 | s->idr_in_use--; |
| @@ -429,10 +427,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid, | |||
| 429 | list_add_tail(&e->list, &con->outqueue); | 427 | list_add_tail(&e->list, &con->outqueue); |
| 430 | spin_unlock_bh(&con->outqueue_lock); | 428 | spin_unlock_bh(&con->outqueue_lock); |
| 431 | 429 | ||
| 432 | if (test_bit(CF_CONNECTED, &con->flags)) | 430 | if (test_bit(CF_CONNECTED, &con->flags)) { |
| 433 | if (!queue_work(s->send_wq, &con->swork)) | 431 | if (!queue_work(s->send_wq, &con->swork)) |
| 434 | conn_put(con); | 432 | conn_put(con); |
| 435 | 433 | } else { | |
| 434 | conn_put(con); | ||
| 435 | } | ||
| 436 | return 0; | 436 | return 0; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| @@ -573,7 +573,6 @@ int tipc_server_start(struct tipc_server *s) | |||
| 573 | kmem_cache_destroy(s->rcvbuf_cache); | 573 | kmem_cache_destroy(s->rcvbuf_cache); |
| 574 | return ret; | 574 | return ret; |
| 575 | } | 575 | } |
| 576 | s->enabled = 1; | ||
| 577 | return ret; | 576 | return ret; |
| 578 | } | 577 | } |
| 579 | 578 | ||
| @@ -583,10 +582,6 @@ void tipc_server_stop(struct tipc_server *s) | |||
| 583 | int total = 0; | 582 | int total = 0; |
| 584 | int id; | 583 | int id; |
| 585 | 584 | ||
| 586 | if (!s->enabled) | ||
| 587 | return; | ||
| 588 | |||
| 589 | s->enabled = 0; | ||
| 590 | spin_lock_bh(&s->idr_lock); | 585 | spin_lock_bh(&s->idr_lock); |
| 591 | for (id = 0; total < s->idr_in_use; id++) { | 586 | for (id = 0; total < s->idr_in_use; id++) { |
| 592 | con = idr_find(&s->conn_idr, id); | 587 | con = idr_find(&s->conn_idr, id); |
diff --git a/net/tipc/server.h b/net/tipc/server.h index 98b23f20bc0f..be817b0b547e 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h | |||
| @@ -56,7 +56,6 @@ | |||
| 56 | * @name: server name | 56 | * @name: server name |
| 57 | * @imp: message importance | 57 | * @imp: message importance |
| 58 | * @type: socket type | 58 | * @type: socket type |
| 59 | * @enabled: identify whether server is launched or not | ||
| 60 | */ | 59 | */ |
| 61 | struct tipc_server { | 60 | struct tipc_server { |
| 62 | struct idr conn_idr; | 61 | struct idr conn_idr; |
| @@ -74,7 +73,6 @@ struct tipc_server { | |||
| 74 | const char name[TIPC_SERVER_NAME_LEN]; | 73 | const char name[TIPC_SERVER_NAME_LEN]; |
| 75 | int imp; | 74 | int imp; |
| 76 | int type; | 75 | int type; |
| 77 | int enabled; | ||
| 78 | }; | 76 | }; |
| 79 | 77 | ||
| 80 | int tipc_conn_sendmsg(struct tipc_server *s, int conid, | 78 | int tipc_conn_sendmsg(struct tipc_server *s, int conid, |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index aab4948f0aff..0ed0eaa62f29 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -70,8 +70,6 @@ static const struct proto_ops msg_ops; | |||
| 70 | static struct proto tipc_proto; | 70 | static struct proto tipc_proto; |
| 71 | static struct proto tipc_proto_kern; | 71 | static struct proto tipc_proto_kern; |
| 72 | 72 | ||
| 73 | static int sockets_enabled; | ||
| 74 | |||
| 75 | /* | 73 | /* |
| 76 | * Revised TIPC socket locking policy: | 74 | * Revised TIPC socket locking policy: |
| 77 | * | 75 | * |
| @@ -999,7 +997,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | |||
| 999 | 997 | ||
| 1000 | for (;;) { | 998 | for (;;) { |
| 1001 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 999 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1002 | if (skb_queue_empty(&sk->sk_receive_queue)) { | 1000 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
| 1003 | if (sock->state == SS_DISCONNECTING) { | 1001 | if (sock->state == SS_DISCONNECTING) { |
| 1004 | err = -ENOTCONN; | 1002 | err = -ENOTCONN; |
| 1005 | break; | 1003 | break; |
| @@ -1625,7 +1623,7 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo) | |||
| 1625 | for (;;) { | 1623 | for (;;) { |
| 1626 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, | 1624 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
| 1627 | TASK_INTERRUPTIBLE); | 1625 | TASK_INTERRUPTIBLE); |
| 1628 | if (skb_queue_empty(&sk->sk_receive_queue)) { | 1626 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
| 1629 | release_sock(sk); | 1627 | release_sock(sk); |
| 1630 | timeo = schedule_timeout(timeo); | 1628 | timeo = schedule_timeout(timeo); |
| 1631 | lock_sock(sk); | 1629 | lock_sock(sk); |
| @@ -2027,8 +2025,6 @@ int tipc_socket_init(void) | |||
| 2027 | proto_unregister(&tipc_proto); | 2025 | proto_unregister(&tipc_proto); |
| 2028 | goto out; | 2026 | goto out; |
| 2029 | } | 2027 | } |
| 2030 | |||
| 2031 | sockets_enabled = 1; | ||
| 2032 | out: | 2028 | out: |
| 2033 | return res; | 2029 | return res; |
| 2034 | } | 2030 | } |
| @@ -2038,10 +2034,6 @@ int tipc_socket_init(void) | |||
| 2038 | */ | 2034 | */ |
| 2039 | void tipc_socket_stop(void) | 2035 | void tipc_socket_stop(void) |
| 2040 | { | 2036 | { |
| 2041 | if (!sockets_enabled) | ||
| 2042 | return; | ||
| 2043 | |||
| 2044 | sockets_enabled = 0; | ||
| 2045 | sock_unregister(tipc_family_ops.family); | 2037 | sock_unregister(tipc_family_ops.family); |
| 2046 | proto_unregister(&tipc_proto); | 2038 | proto_unregister(&tipc_proto); |
| 2047 | } | 2039 | } |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 7cb0bd5b1176..642437231ad5 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
| @@ -96,20 +96,16 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, | |||
| 96 | { | 96 | { |
| 97 | struct tipc_subscriber *subscriber = sub->subscriber; | 97 | struct tipc_subscriber *subscriber = sub->subscriber; |
| 98 | struct kvec msg_sect; | 98 | struct kvec msg_sect; |
| 99 | int ret; | ||
| 100 | 99 | ||
| 101 | msg_sect.iov_base = (void *)&sub->evt; | 100 | msg_sect.iov_base = (void *)&sub->evt; |
| 102 | msg_sect.iov_len = sizeof(struct tipc_event); | 101 | msg_sect.iov_len = sizeof(struct tipc_event); |
| 103 | |||
| 104 | sub->evt.event = htohl(event, sub->swap); | 102 | sub->evt.event = htohl(event, sub->swap); |
| 105 | sub->evt.found_lower = htohl(found_lower, sub->swap); | 103 | sub->evt.found_lower = htohl(found_lower, sub->swap); |
| 106 | sub->evt.found_upper = htohl(found_upper, sub->swap); | 104 | sub->evt.found_upper = htohl(found_upper, sub->swap); |
| 107 | sub->evt.port.ref = htohl(port_ref, sub->swap); | 105 | sub->evt.port.ref = htohl(port_ref, sub->swap); |
| 108 | sub->evt.port.node = htohl(node, sub->swap); | 106 | sub->evt.port.node = htohl(node, sub->swap); |
| 109 | ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, | 107 | tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base, |
| 110 | msg_sect.iov_base, msg_sect.iov_len); | 108 | msg_sect.iov_len); |
| 111 | if (ret < 0) | ||
| 112 | pr_err("Sending subscription event failed, no memory\n"); | ||
| 113 | } | 109 | } |
| 114 | 110 | ||
| 115 | /** | 111 | /** |
| @@ -153,14 +149,6 @@ static void subscr_timeout(struct tipc_subscription *sub) | |||
| 153 | /* The spin lock per subscriber is used to protect its members */ | 149 | /* The spin lock per subscriber is used to protect its members */ |
| 154 | spin_lock_bh(&subscriber->lock); | 150 | spin_lock_bh(&subscriber->lock); |
| 155 | 151 | ||
| 156 | /* Validate if the connection related to the subscriber is | ||
| 157 | * closed (in case subscriber is terminating) | ||
| 158 | */ | ||
| 159 | if (subscriber->conid == 0) { | ||
| 160 | spin_unlock_bh(&subscriber->lock); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* Validate timeout (in case subscription is being cancelled) */ | 152 | /* Validate timeout (in case subscription is being cancelled) */ |
| 165 | if (sub->timeout == TIPC_WAIT_FOREVER) { | 153 | if (sub->timeout == TIPC_WAIT_FOREVER) { |
| 166 | spin_unlock_bh(&subscriber->lock); | 154 | spin_unlock_bh(&subscriber->lock); |
| @@ -215,9 +203,6 @@ static void subscr_release(struct tipc_subscriber *subscriber) | |||
| 215 | 203 | ||
| 216 | spin_lock_bh(&subscriber->lock); | 204 | spin_lock_bh(&subscriber->lock); |
| 217 | 205 | ||
| 218 | /* Invalidate subscriber reference */ | ||
| 219 | subscriber->conid = 0; | ||
| 220 | |||
| 221 | /* Destroy any existing subscriptions for subscriber */ | 206 | /* Destroy any existing subscriptions for subscriber */ |
| 222 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 207 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
| 223 | subscription_list) { | 208 | subscription_list) { |
| @@ -278,9 +263,9 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
| 278 | * | 263 | * |
| 279 | * Called with subscriber lock held. | 264 | * Called with subscriber lock held. |
| 280 | */ | 265 | */ |
| 281 | static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, | 266 | static int subscr_subscribe(struct tipc_subscr *s, |
| 282 | struct tipc_subscriber *subscriber) | 267 | struct tipc_subscriber *subscriber, |
| 283 | { | 268 | struct tipc_subscription **sub_p) { |
| 284 | struct tipc_subscription *sub; | 269 | struct tipc_subscription *sub; |
| 285 | int swap; | 270 | int swap; |
| 286 | 271 | ||
| @@ -291,23 +276,21 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, | |||
| 291 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | 276 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { |
| 292 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | 277 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); |
| 293 | subscr_cancel(s, subscriber); | 278 | subscr_cancel(s, subscriber); |
| 294 | return NULL; | 279 | return 0; |
| 295 | } | 280 | } |
| 296 | 281 | ||
| 297 | /* Refuse subscription if global limit exceeded */ | 282 | /* Refuse subscription if global limit exceeded */ |
| 298 | if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { | 283 | if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { |
| 299 | pr_warn("Subscription rejected, limit reached (%u)\n", | 284 | pr_warn("Subscription rejected, limit reached (%u)\n", |
| 300 | TIPC_MAX_SUBSCRIPTIONS); | 285 | TIPC_MAX_SUBSCRIPTIONS); |
| 301 | subscr_terminate(subscriber); | 286 | return -EINVAL; |
| 302 | return NULL; | ||
| 303 | } | 287 | } |
| 304 | 288 | ||
| 305 | /* Allocate subscription object */ | 289 | /* Allocate subscription object */ |
| 306 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); | 290 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); |
| 307 | if (!sub) { | 291 | if (!sub) { |
| 308 | pr_warn("Subscription rejected, no memory\n"); | 292 | pr_warn("Subscription rejected, no memory\n"); |
| 309 | subscr_terminate(subscriber); | 293 | return -ENOMEM; |
| 310 | return NULL; | ||
| 311 | } | 294 | } |
| 312 | 295 | ||
| 313 | /* Initialize subscription object */ | 296 | /* Initialize subscription object */ |
| @@ -321,8 +304,7 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, | |||
| 321 | (sub->seq.lower > sub->seq.upper)) { | 304 | (sub->seq.lower > sub->seq.upper)) { |
| 322 | pr_warn("Subscription rejected, illegal request\n"); | 305 | pr_warn("Subscription rejected, illegal request\n"); |
| 323 | kfree(sub); | 306 | kfree(sub); |
| 324 | subscr_terminate(subscriber); | 307 | return -EINVAL; |
| 325 | return NULL; | ||
| 326 | } | 308 | } |
| 327 | INIT_LIST_HEAD(&sub->nameseq_list); | 309 | INIT_LIST_HEAD(&sub->nameseq_list); |
| 328 | list_add(&sub->subscription_list, &subscriber->subscription_list); | 310 | list_add(&sub->subscription_list, &subscriber->subscription_list); |
| @@ -335,8 +317,8 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, | |||
| 335 | (Handler)subscr_timeout, (unsigned long)sub); | 317 | (Handler)subscr_timeout, (unsigned long)sub); |
| 336 | k_start_timer(&sub->timer, sub->timeout); | 318 | k_start_timer(&sub->timer, sub->timeout); |
| 337 | } | 319 | } |
| 338 | 320 | *sub_p = sub; | |
| 339 | return sub; | 321 | return 0; |
| 340 | } | 322 | } |
| 341 | 323 | ||
| 342 | /* Handle one termination request for the subscriber */ | 324 | /* Handle one termination request for the subscriber */ |
| @@ -350,10 +332,14 @@ static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, | |||
| 350 | void *usr_data, void *buf, size_t len) | 332 | void *usr_data, void *buf, size_t len) |
| 351 | { | 333 | { |
| 352 | struct tipc_subscriber *subscriber = usr_data; | 334 | struct tipc_subscriber *subscriber = usr_data; |
| 353 | struct tipc_subscription *sub; | 335 | struct tipc_subscription *sub = NULL; |
| 354 | 336 | ||
| 355 | spin_lock_bh(&subscriber->lock); | 337 | spin_lock_bh(&subscriber->lock); |
| 356 | sub = subscr_subscribe((struct tipc_subscr *)buf, subscriber); | 338 | if (subscr_subscribe((struct tipc_subscr *)buf, subscriber, &sub) < 0) { |
| 339 | spin_unlock_bh(&subscriber->lock); | ||
| 340 | subscr_terminate(subscriber); | ||
| 341 | return; | ||
| 342 | } | ||
| 357 | if (sub) | 343 | if (sub) |
| 358 | tipc_nametbl_subscribe(sub); | 344 | tipc_nametbl_subscribe(sub); |
| 359 | spin_unlock_bh(&subscriber->lock); | 345 | spin_unlock_bh(&subscriber->lock); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 29fc8bee9702..94404f19f9de 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -163,9 +163,8 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) | |||
| 163 | 163 | ||
| 164 | static inline unsigned int unix_hash_fold(__wsum n) | 164 | static inline unsigned int unix_hash_fold(__wsum n) |
| 165 | { | 165 | { |
| 166 | unsigned int hash = (__force unsigned int)n; | 166 | unsigned int hash = (__force unsigned int)csum_fold(n); |
| 167 | 167 | ||
| 168 | hash ^= hash>>16; | ||
| 169 | hash ^= hash>>8; | 168 | hash ^= hash>>8; |
| 170 | return hash&(UNIX_HASH_SIZE-1); | 169 | return hash&(UNIX_HASH_SIZE-1); |
| 171 | } | 170 | } |
| @@ -1788,8 +1787,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1788 | goto out; | 1787 | goto out; |
| 1789 | 1788 | ||
| 1790 | err = mutex_lock_interruptible(&u->readlock); | 1789 | err = mutex_lock_interruptible(&u->readlock); |
| 1791 | if (err) { | 1790 | if (unlikely(err)) { |
| 1792 | err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); | 1791 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN |
| 1792 | * sk_rcvtimeo is not honored by mutex_lock_interruptible() | ||
| 1793 | */ | ||
| 1794 | err = noblock ? -EAGAIN : -ERESTARTSYS; | ||
| 1793 | goto out; | 1795 | goto out; |
| 1794 | } | 1796 | } |
| 1795 | 1797 | ||
| @@ -1914,6 +1916,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1914 | struct unix_sock *u = unix_sk(sk); | 1916 | struct unix_sock *u = unix_sk(sk); |
| 1915 | DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name); | 1917 | DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name); |
| 1916 | int copied = 0; | 1918 | int copied = 0; |
| 1919 | int noblock = flags & MSG_DONTWAIT; | ||
| 1917 | int check_creds = 0; | 1920 | int check_creds = 0; |
| 1918 | int target; | 1921 | int target; |
| 1919 | int err = 0; | 1922 | int err = 0; |
| @@ -1929,7 +1932,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1929 | goto out; | 1932 | goto out; |
| 1930 | 1933 | ||
| 1931 | target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); | 1934 | target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); |
| 1932 | timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); | 1935 | timeo = sock_rcvtimeo(sk, noblock); |
| 1933 | 1936 | ||
| 1934 | /* Lock the socket to prevent queue disordering | 1937 | /* Lock the socket to prevent queue disordering |
| 1935 | * while sleeps in memcpy_tomsg | 1938 | * while sleeps in memcpy_tomsg |
| @@ -1941,8 +1944,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1941 | } | 1944 | } |
| 1942 | 1945 | ||
| 1943 | err = mutex_lock_interruptible(&u->readlock); | 1946 | err = mutex_lock_interruptible(&u->readlock); |
| 1944 | if (err) { | 1947 | if (unlikely(err)) { |
| 1945 | err = sock_intr_errno(timeo); | 1948 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN |
| 1949 | * sk_rcvtimeo is not honored by mutex_lock_interruptible() | ||
| 1950 | */ | ||
| 1951 | err = noblock ? -EAGAIN : -ERESTARTSYS; | ||
| 1946 | goto out; | 1952 | goto out; |
| 1947 | } | 1953 | } |
| 1948 | 1954 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 010892b81a06..a3bf18d11609 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -788,8 +788,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 788 | default: | 788 | default: |
| 789 | break; | 789 | break; |
| 790 | } | 790 | } |
| 791 | |||
| 792 | wdev->beacon_interval = 0; | ||
| 793 | } | 791 | } |
| 794 | 792 | ||
| 795 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | 793 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9b897fca7487..f0541370e68e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1700 | return; | 1700 | return; |
| 1701 | case NL80211_REGDOM_SET_BY_USER: | 1701 | case NL80211_REGDOM_SET_BY_USER: |
| 1702 | treatment = reg_process_hint_user(reg_request); | 1702 | treatment = reg_process_hint_user(reg_request); |
| 1703 | if (treatment == REG_REQ_OK || | 1703 | if (treatment == REG_REQ_IGNORE || |
| 1704 | treatment == REG_REQ_ALREADY_SET) | 1704 | treatment == REG_REQ_ALREADY_SET) |
| 1705 | return; | 1705 | return; |
| 1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | 1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); |
| @@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
| 2373 | int set_regdom(const struct ieee80211_regdomain *rd) | 2373 | int set_regdom(const struct ieee80211_regdomain *rd) |
| 2374 | { | 2374 | { |
| 2375 | struct regulatory_request *lr; | 2375 | struct regulatory_request *lr; |
| 2376 | bool user_reset = false; | ||
| 2376 | int r; | 2377 | int r; |
| 2377 | 2378 | ||
| 2378 | if (!reg_is_valid_request(rd->alpha2)) { | 2379 | if (!reg_is_valid_request(rd->alpha2)) { |
| @@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2389 | break; | 2390 | break; |
| 2390 | case NL80211_REGDOM_SET_BY_USER: | 2391 | case NL80211_REGDOM_SET_BY_USER: |
| 2391 | r = reg_set_rd_user(rd, lr); | 2392 | r = reg_set_rd_user(rd, lr); |
| 2393 | user_reset = true; | ||
| 2392 | break; | 2394 | break; |
| 2393 | case NL80211_REGDOM_SET_BY_DRIVER: | 2395 | case NL80211_REGDOM_SET_BY_DRIVER: |
| 2394 | r = reg_set_rd_driver(rd, lr); | 2396 | r = reg_set_rd_driver(rd, lr); |
| @@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2402 | } | 2404 | } |
| 2403 | 2405 | ||
| 2404 | if (r) { | 2406 | if (r) { |
| 2405 | if (r == -EALREADY) | 2407 | switch (r) { |
| 2408 | case -EALREADY: | ||
| 2406 | reg_set_request_processed(); | 2409 | reg_set_request_processed(); |
| 2410 | break; | ||
| 2411 | default: | ||
| 2412 | /* Back to world regulatory in case of errors */ | ||
| 2413 | restore_regulatory_settings(user_reset); | ||
| 2414 | } | ||
| 2407 | 2415 | ||
| 2408 | kfree(rd); | 2416 | kfree(rd); |
| 2409 | return r; | 2417 | return r; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4b98b25793c5..1d5c7bf29938 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -1158,7 +1158,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | |||
| 1158 | if (hlist_unhashed(&pol->bydst)) | 1158 | if (hlist_unhashed(&pol->bydst)) |
| 1159 | return NULL; | 1159 | return NULL; |
| 1160 | 1160 | ||
| 1161 | hlist_del(&pol->bydst); | 1161 | hlist_del_init(&pol->bydst); |
| 1162 | hlist_del(&pol->byidx); | 1162 | hlist_del(&pol->byidx); |
| 1163 | list_del(&pol->walk.all); | 1163 | list_del(&pol->walk.all); |
| 1164 | net->xfrm.policy_count[dir]--; | 1164 | net->xfrm.policy_count[dir]--; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a26b7aa79475..40f1b3e92e78 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -1159,6 +1159,11 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1159 | } | 1159 | } |
| 1160 | x->props.aalgo = orig->props.aalgo; | 1160 | x->props.aalgo = orig->props.aalgo; |
| 1161 | 1161 | ||
| 1162 | if (orig->aead) { | ||
| 1163 | x->aead = xfrm_algo_aead_clone(orig->aead); | ||
| 1164 | if (!x->aead) | ||
| 1165 | goto error; | ||
| 1166 | } | ||
| 1162 | if (orig->ealg) { | 1167 | if (orig->ealg) { |
| 1163 | x->ealg = xfrm_algo_clone(orig->ealg); | 1168 | x->ealg = xfrm_algo_clone(orig->ealg); |
| 1164 | if (!x->ealg) | 1169 | if (!x->ealg) |
| @@ -1201,6 +1206,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1201 | x->props.flags = orig->props.flags; | 1206 | x->props.flags = orig->props.flags; |
| 1202 | x->props.extra_flags = orig->props.extra_flags; | 1207 | x->props.extra_flags = orig->props.extra_flags; |
| 1203 | 1208 | ||
| 1209 | x->tfcpad = orig->tfcpad; | ||
| 1210 | x->replay_maxdiff = orig->replay_maxdiff; | ||
| 1211 | x->replay_maxage = orig->replay_maxage; | ||
| 1204 | x->curlft.add_time = orig->curlft.add_time; | 1212 | x->curlft.add_time = orig->curlft.add_time; |
| 1205 | x->km.state = orig->km.state; | 1213 | x->km.state = orig->km.state; |
| 1206 | x->km.seq = orig->km.seq; | 1214 | x->km.seq = orig->km.seq; |
| @@ -1215,11 +1223,12 @@ out: | |||
| 1215 | return NULL; | 1223 | return NULL; |
| 1216 | } | 1224 | } |
| 1217 | 1225 | ||
| 1218 | /* net->xfrm.xfrm_state_lock is held */ | ||
| 1219 | struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net) | 1226 | struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net) |
| 1220 | { | 1227 | { |
| 1221 | unsigned int h; | 1228 | unsigned int h; |
| 1222 | struct xfrm_state *x; | 1229 | struct xfrm_state *x = NULL; |
| 1230 | |||
| 1231 | spin_lock_bh(&net->xfrm.xfrm_state_lock); | ||
| 1223 | 1232 | ||
| 1224 | if (m->reqid) { | 1233 | if (m->reqid) { |
| 1225 | h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr, | 1234 | h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr, |
| @@ -1236,7 +1245,7 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n | |||
| 1236 | m->old_family)) | 1245 | m->old_family)) |
| 1237 | continue; | 1246 | continue; |
| 1238 | xfrm_state_hold(x); | 1247 | xfrm_state_hold(x); |
| 1239 | return x; | 1248 | break; |
| 1240 | } | 1249 | } |
| 1241 | } else { | 1250 | } else { |
| 1242 | h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr, | 1251 | h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr, |
| @@ -1251,11 +1260,13 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n | |||
| 1251 | m->old_family)) | 1260 | m->old_family)) |
| 1252 | continue; | 1261 | continue; |
| 1253 | xfrm_state_hold(x); | 1262 | xfrm_state_hold(x); |
| 1254 | return x; | 1263 | break; |
| 1255 | } | 1264 | } |
| 1256 | } | 1265 | } |
| 1257 | 1266 | ||
| 1258 | return NULL; | 1267 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); |
| 1268 | |||
| 1269 | return x; | ||
| 1259 | } | 1270 | } |
| 1260 | EXPORT_SYMBOL(xfrm_migrate_state_find); | 1271 | EXPORT_SYMBOL(xfrm_migrate_state_find); |
| 1261 | 1272 | ||
| @@ -1451,7 +1462,7 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, | |||
| 1451 | { | 1462 | { |
| 1452 | int err = 0; | 1463 | int err = 0; |
| 1453 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | 1464 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
| 1454 | struct net *net = xs_net(*dst); | 1465 | struct net *net = xs_net(*src); |
| 1455 | 1466 | ||
| 1456 | if (!afinfo) | 1467 | if (!afinfo) |
| 1457 | return -EAFNOSUPPORT; | 1468 | return -EAFNOSUPPORT; |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 1ae3ec7c18b0..2f7ddc3a59b4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -32,11 +32,6 @@ | |||
| 32 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | static inline int aead_len(struct xfrm_algo_aead *alg) | ||
| 36 | { | ||
| 37 | return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); | ||
| 38 | } | ||
| 39 | |||
| 40 | static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) | 35 | static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) |
| 41 | { | 36 | { |
| 42 | struct nlattr *rt = attrs[type]; | 37 | struct nlattr *rt = attrs[type]; |
| @@ -1226,7 +1221,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs | |||
| 1226 | return 0; | 1221 | return 0; |
| 1227 | 1222 | ||
| 1228 | uctx = nla_data(rt); | 1223 | uctx = nla_data(rt); |
| 1229 | return security_xfrm_policy_alloc(&pol->security, uctx); | 1224 | return security_xfrm_policy_alloc(&pol->security, uctx, GFP_KERNEL); |
| 1230 | } | 1225 | } |
| 1231 | 1226 | ||
| 1232 | static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, | 1227 | static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, |
| @@ -1631,7 +1626,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1631 | if (rt) { | 1626 | if (rt) { |
| 1632 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); | 1627 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
| 1633 | 1628 | ||
| 1634 | err = security_xfrm_policy_alloc(&ctx, uctx); | 1629 | err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL); |
| 1635 | if (err) | 1630 | if (err) |
| 1636 | return err; | 1631 | return err; |
| 1637 | } | 1632 | } |
| @@ -1933,7 +1928,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1933 | if (rt) { | 1928 | if (rt) { |
| 1934 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); | 1929 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
| 1935 | 1930 | ||
| 1936 | err = security_xfrm_policy_alloc(&ctx, uctx); | 1931 | err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL); |
| 1937 | if (err) | 1932 | if (err) |
| 1938 | return err; | 1933 | return err; |
| 1939 | } | 1934 | } |
